0

I am trying to read an IP/RAW socket packet with its parameters (such as char pointer to the IP packet and its size) put that in to a mqueue in WRONLY mode and retrieve the same parameters from the queue in RDONLY mode. I am using structures for the message(msg) to send and receive. While sending the msg, the both parameters are successfully placed in a queue but while on retrieving it returns me segmentation fault. My send and receive files are given below:

mq_send.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<mqueue.h>
#include<errno.h>
#include<netinet/ip_icmp.h>   
#include<netinet/udp.h> 
#include<netinet/tcp.h>  
#include<netinet/ip.h>
#include<netinet/in.h>
#include<netinet/if_ether.h>
#include<net/ethernet.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
#include"external.h"

#define QUEUE_NAME  "/test_queue"
#define MAX_SIZE    71680

#define CHECK(x) \
    do { \
        if (!(x)) { \
            fprintf(stderr, "%s:%d: ", __func__, __LINE__); \
            perror(#x); \
            exit(-1); \
        } \
    } while (0) \


struct sockaddr_in source,dest;
int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0,i,j;

struct mymsg
{
    char buff[MAX_SIZE];
    int size;
};


int main(int argc, char **argv)
{
    mqd_t mq;
    struct mymsg m;
    struct mq_attr attr;
    //char buff[MAX_SIZE];
    unsigned char* buffer = (unsigned char*) malloc(sizeof(65536));
    int saddr_size,sock_raw;
    struct sockaddr saddr;
    int data_size;

    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = MAX_SIZE;
    attr.mq_curmsgs = 0;

    mq = mq_open(QUEUE_NAME, O_CREAT | O_WRONLY, 0644, &attr);
    CHECK((mqd_t)-1 != mq);

    memset(buffer, 0, MAX_SIZE);    

    sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;
    if(sock_raw < 0)
    {
       perror("Socket Error\n");
       return 1;
    }
    saddr_size = sizeof saddr;
    data_size = recvfrom(sock_raw , buffer ,65536 , 0 , &saddr , (socklen_t*)&saddr_size);

    if(data_size <0 )
    {
       printf("Recvfrom error , failed to get packets\n");
       return 1;
    }

    memcpy(m.buff,buffer,65536);
    m.size=data_size;

    //char *a="hi";
    //CHECK(0 <= mq_send(mq, (char *)&a, MAX_SIZE, 0));
    CHECK(0 <= mq_send(mq, (char *)&m, MAX_SIZE, 0));

    printf("Packet msg:%s size:%d\n",buffer,data_size);
    printf("Sent msg:%s size:%d\n",m.buff,m.size);

    ProcessPacket(m.buff , m.size);

    CHECK((mqd_t)-1 != mq_close(mq));

    close(sock_raw);

    return 0;
}

mq_receive.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<mqueue.h>
#include<errno.h>
#include<netinet/ip_icmp.h>   
#include<netinet/udp.h> 
#include<netinet/tcp.h>  
#include<netinet/ip.h>
#include<netinet/in.h>
#include<netinet/if_ether.h>
#include<net/ethernet.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
#include"external.h"

#define QUEUE_NAME  "/test_queue"
#define MAX_SIZE    71680

#define CHECK(x) \
    do { \
        if (!(x)) { \
            fprintf(stderr, "%s:%d: ", __func__, __LINE__); \
            perror(#x); \
            exit(-1); \
        } \
    } while (0) \

struct sockaddr_in source,dest;
int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0,i,j;

typedef struct mymsg
{
    unsigned char *buff;
    int size;
}msg;

int main(int argc, char *argv[])
{
    mqd_t mq;
    msg *m=(msg *)malloc(sizeof(msg));
    m->buff=(unsigned char*) malloc(sizeof(MAX_SIZE));
    int data_size;

    mq = mq_open(QUEUE_NAME, O_RDONLY);
    CHECK((mqd_t)-1 != mq);

    memset(m->buff, 0, MAX_SIZE+1);

    ssize_t bytes_read;


    bytes_read = mq_receive(mq, (char *)m, MAX_SIZE, NULL);
    CHECK(bytes_read >= 0);
    printf("Received buff:%s size:%d\n", m->buff,m->size);
    //ProcessPacket(m.buff , data_size);

    /* cleanup */
    CHECK((mqd_t)-1 != mq_close(mq));
    CHECK((mqd_t)-1 != mq_unlink(QUEUE_NAME));

    return 0;
}

Output for mqueue_send.c:

bcg@BCGA53:~/Desktop/mqueue$ sudo ./mq_send
Packet msg:�������M��� size:60
Sent msg:�������M��� size:60

Output for mq_receive.c:

bcg@BCGA53:~/Desktop/mqueue$ sudo ./mq_receive
Segmentation fault
Cœur
  • 37,241
  • 25
  • 195
  • 267
Ashok Kumar
  • 21
  • 1
  • 5
  • As for the crash, have you tried running in a debugger to find out *where* the crash is? – Some programmer dude Dec 15 '14 at 09:35
  • Well, `mq_send(mq, (char *)&m, MAX_SIZE, 0))` is already wrong. You're sending `MAX_SIZE`, which is *not* the size of `m`. It only sends the first field of the structure. The `size` member is omitted from the send. It would seem to me `sizeof(m)` in this case would be more appropriate, as it is a self-contained struct (no pointers). Frankly I don't understand why your `size` isn't the **first** thing you send, followed by `size` bytes. – WhozCraig Dec 15 '14 at 09:36
  • Hi buddy, I am trying to send both the pointer to the packet as well as its size to the queue, so that it can be processed easily on the receiving end. The recvfrom() functions returns the packet(pointed by char*) and its size(int) for processing.Is it correct or am I going anywhere wrong?Ur suggestions.. – Ashok Kumar Dec 15 '14 at 11:32

1 Answers1

1
unsigned char* buffer = (unsigned char*) malloc(sizeof(65536));

The code above allocates memory that can hold sizeof(65536) bytes. The problem is that sizeof(65536) is the same as sizeof(int) and that is usually 4 or maybe 8 bytes.

You either should use this:

unsigned char* buffer = (unsigned char*) malloc(sizeof(char[65536]));

or this

unsigned char* buffer = (unsigned char*) malloc(65536);

There are other errors - for example you use MAX_SIZE in mq_send(), while you should be using sizeof(m). The root cause of your error is the problem outlined above.

In fact, this allocation is pointless (at least in the code you presented above), as you could receive directly into your message struct - you wouldn't see this problem then.

Freddie Chopin
  • 8,440
  • 2
  • 28
  • 58
  • Sorry,your suggestion of malloc() gave me a segmentation fault.However, I used your second suggestion like CHECK(0 <= mq_send(mq, (char *)m, sizeof(m), 0)); in mq_send.c and used the same in mq_receive.c as bytes_read = mq_receive(mq, (char *)m, sizeof(m), NULL);But this returned me main:68: bytes_read >= 0: Message too long error – Ashok Kumar Dec 15 '14 at 11:24
  • @AshokKumar You have an error somewhere else, and from what you write here and in the comments above, you don't seem to understand what you are actually doing. You are not passing pointers via the queue - you are passing a _copy_ of the buffer (but not the whole message). Your original `malloc()` call is completely broken (in both programs!), while both the calls above are correct (assuming you really want to allocate 65536 bytes). – Freddie Chopin Dec 15 '14 at 15:30