passing structures in messages of mqueue

2.3k views Asked by At

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
1

There are 1 answers

2
Freddie Chopin On
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.