Sending/Recieving structures in UNIX

Posted on 2005-04-19
Last Modified: 2008-02-01

I am trying to send and receive structures that contain, char buffers inside of the structure between my kernel code and my user land/process. My problem lies in that I am passing a structure that has some pointers to buffers within this structure and these buffers are always showing empty/zeros when I receive them on the userland side.
I get all the correct values for ints/booleans and etc. that are in my structure but the _MALLOCed buffers, from the kernel extension are empty. I suspect it has to do something with the way I filling out the mbuf because like I said I can receive the struct on the userland side, the pointers seem good to the buffers with in the structure but these buffers are just empty, zeroed out.
Maybe if someone can take a look at the code below they have some suggestions or see something I do not.
The code from the kernel side is:
struct Test_Struct
    int n1;
    int n2;
    char* buf1;
struct Test_Struct *test;
test = _MALLOC(sizeof(struct Test_Struct), M_TEMP, M_WIATOK|M_ZERO);
if((test->buf1 = _MALLOC(50, M_TEMP, M_WAITOK|M_ZERO)) != 0)
    bcopy("Here comes the test data", test->buf1, 20);
    test->n1 = 66;
    test->n2 = 678;
// now send the struct to user land
struct mbuf *m;
size_t len = sizeof(Test_Struct);
if(len > MCLBYTES)
    return EMSGSIZE;
if ((m = m_gethdr(M_NOWAIT, MT_DATA)) == NULL)
    return ENOBUFS;
m->m_flags |= M_EOR;
if(len >MLEN)
    if(!(m->m_flags & M_EXT))
bcopy(test, mtod(m, void*), len);
m->m_pkthdr.len = m->m_len=len;
ctl_enqueuembuf(ctlref, m, flags);  // this is a call equivalent to send(nfd, void*, int), a Mac OS X thing, don't worry about it, it works.
// ctlref is a pointer to previously registered controller, that is hooked to this kernel extension
Below is a sample of the code in userland that receives the data from ctl_enqueuembuf:
struct Test_Struct teststruct;
int nBytesRc;
nBytesRc = recv(nfd, &teststruct, sizeof(teststruct), 0);
if(nBytesRc > 0)
    // do what every with teststruct.buf1; and other members of the received struct.
    This is where I can look at the teststruct and buf1 is always empty.
Question by:atomic928
    LVL 27

    Expert Comment

    If I may be allowed to start from scratch.

    This process of sending arbitary structures over communication links is called marshalling. Generally you'd send an indication of what object is being marshalled and the contents, usually in address order. Any dynamic contents would necessarily have to be prefixed by a length attribute followed by the data.

    Given a structure X you'd need two procedures, marshallX and unmarshallX. The first takes a struct and returns a string, the second takes a string and retuns a struct.

    Now strings are problamatic, since marshalling can include bytes of binary zero, so I'd have a global buffer of some large size and write the marshalled data into it. The marshall procedure returns the number of bytes written. Simarly the unmarshall procedure reads this global buffer, takes the length as a parameter and returns a new structure.

    I'd now have procedures which marshall and unmarshall integers (int2/long) and char*. These take a buffer position and write/read the data. With char* you'd write data into the  buffer incrementing the pointer until a binary zero, or read until a binary zero.

    Now when sending data over sockets you must NOT assume that the recv call will read exectly the same number of bytes that the send call has written. Therefore it is necessary to send a message length each time and to use this message length on reading. On unmarshalling you'd use this length to check that you have got and processed all the data. In this way you get a very secure communication.

    I hope that starts you off in thr right direction.
    LVL 55

    Accepted Solution

    I face sometimes this problem. I have solved this by creating a "universal" way to store binary data. Some kind of "binary XML", there are 4 sub-fields for each field:
    1 byte:   field code (instead of field name), to identify each field, because you can spare space by not including some unneeded fields
    1 byte:   specify data type (bool,int8,int16,int32,float,double,binary,string) and lenght type (int8, int16, int32)
    1-4 bytes: field lenght (according to previous byte, but only for binary and string)
    1-n bytes: the data itself

    Featured Post

    Enabling OSINT in Activity Based Intelligence

    Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

    Join & Write a Comment

    Suggested Solutions

    Title # Comments Views Activity
    fizzArray2 challenge 1 44
    object oriented javascript web form 8 51
    wordappend challenge 8 54
    Problem to event 3 28
    There is an easy way, in .NET, to centralize the treatment of all unexpected errors. First of all, instead of launching the application directly in a Form, you need first to write a Sub called Main, in a module. Then, set the Startup Object to th…
    If you haven’t already, I encourage you to read the first article ( in my series to gain a basic foundation of R and R Studio.  You will also find the …
    This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.
    The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

    745 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    14 Experts available now in Live!

    Get 1:1 Help Now