Antonio MG
Antonio MG

Reputation: 20410

How do I populate socket address properly?

I'm sending a ICMP packet through a socket in iOS:

struct sockaddr         hostAddress;

self->hostAddress.sa_family = AF_INET;
inet_pton(AF_INET, "173.194.67.93", &self->hostAddress.sa_data);

Then, I open the socket and I send the packet:

bytesSent = sendto(
                   CFSocketGetNative(self->_socket),
                   [packet bytes],
                   [packet length],
                   0,
                   &self->hostAddress,
                   sizeof(self->hostAddress)
                   );

When I see the packet in WireShark, it's being sent to "67.93.0.0", instead to "173.194.67.93".

Where could be the problem?

Upvotes: 1

Views: 1338

Answers (1)

Useless
Useless

Reputation: 67713

inet_pton(AF_INET, ...);

should take a struct in_addr as the 3rd argument (see docs).

You're giving it sa_data, from

struct sockaddr {
    unsigned short    sa_family;    // address family, AF_xxx
    char              sa_data[14];  // 14 bytes of protocol address
};

which is really treated as:

struct sockaddr_in {
    short            sin_family;   // e.g. AF_INET, AF_INET6
    unsigned short   sin_port;     // e.g. htons(3490)
    struct in_addr   sin_addr;     // see struct in_addr, below
    char             sin_zero[8];  // zero this if you want to
};

So, the first 16 bits are going in the port, the second 16 bits of the IPV4 address are actually making it into sin_addr, and the rest appears to be zero-initialized.


You should be doing this (I'll put loads of casts in for clarity)

struct sockaddr *addr = &self->hostAddress; // generic address
struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr; // downcast to ipv4
inet_pton(AF_INET, "173.194.67.93", &ipv4->sin_addr);

Upvotes: 3

Related Questions