0

I am passing char * pointer from main to a function abc which is uninitialized pointer. And I am composing a network packet so like what allocated in the function I want it to be the representation of a packet. So This is my passing of uninitialized pointer in function call inside main

            char *pay;
            abc(&pay);

in the function I have as signature of a function like following

            void abc(char **c)

this is the full function

        void abc(char **c)
        {
            *c=(char *) malloc(sizeof(struct ethhdr)+sizeof(struct iphdr)+sizeof(struct tcphdr)+1000/*1000=payload*/);
            struct ethhdr *eth=(struct ethhdr *)&*c;
            struct iphdr *ip=(struct iphdr *)(&*eth+sizeof(struct ethhdr));
            struct tcphdr *tcp=(struct tcphdr *)(&*ip+sizeof(struct iphdr));
            //populate eth
            //...
            //populate ip
            //...
            //populate tcp
            tcp->source=80;
            printf("%d\n",tcp->source);
            int *x=(int *)*c;
            //x=10;

        }

I like to know how can I cast second line in abc function I am doing like this

        struct ethhdr *eth=(struct ethhdr *)&*c;

second line inside abc function.

But at line containing this instruction tcp->source=80; its causing segFault.

So my question is how can I cast the c double pointer in function and to assign it tostruct ethhdr *,struct iphd * and struct tcphdr * pointers

And how to assign the values to members of struct ethhdr , struct iphdr and struct tcphdr

I tried like

tcp->source=80;

But causing segFault

user786
  • 3,902
  • 4
  • 40
  • 72

1 Answers1

2

You have two problems.

The first is the use of both the address-of and dereference operators in:

struct ethhdr *eth=(struct ethhdr *)&*c;

The expression &*c is the same as plain c, which isn't correct. You need *c here:

struct ethhdr *eth = (struct ethhdr *) *c;

You have similar problem with the other pointers (e.g. &*eth) but there it doesn't cause any problems because of this. Use just plain eth (for example).


The second problem is two-fold, and is all the other assignments. First of all the pointers you use are not byte pointers which means casting to another structure pointer will break strict aliasing.

Secondly you have to remember that for any pointer or array p and index/offset i, the expression *(p + i) is exactly equal to p[i]. For an expression like eth+sizeof(struct ethhdr) that means it's the same as &)eth[sizeof(struct ethhdr)]). Which is clearly wrong (eth could be seen as an array of one element, not an array of at least sizeof(struct ethaddr) + 1 elements.

To fix both these problems, strict aliasing and the offsets, you need to use the original byte-pointer *c and add the offsets in bytes to that:

struct iphdr *ip = (struct iphdr *) (*c + sizeof(struct ethhdr));
struct tcphdr *tcp = (struct tcphdr *) (*c + sizeof(struct ethhdr) + sizeof(struct iphdr));

From the above it should now be relatively easy to figure out how to get a pointer to the payload data, because it's not plain *c as used in your code.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • `First of all the pointers you use are not byte pointers which means casting to another structure pointer will break strict aliasing.` what do u mean by aliasing does this statement `struct ethhdr *eth=(struct ethhdr *)*c` ; is correct` but this `struct iphdr *ip=(struct iphdr *)(&*eth+sizeof(struct ethhdr));` Is NOT correct. what I understood is that `struct iphdr *` is not byte pointer because its size is different and not `1 byte` – user786 Apr 01 '21 at 14:10
  • @666 https://stackoverflow.com/questions/46790550/c-undefined-behavior-strict-aliasing-rule-or-incorrect-alignment this is related. – Antti Haapala -- Слава Україні Apr 04 '21 at 08:04