4

I have a problem using getsockname function. I have this code:

struct sockaddr sa;
int sa_len;
sa_len = sizeof(sa);
if (getsockname(socketfd, &sa, &sa_len) != SOCKET_ERROR)
{
   ///
}
else
{
   int error = WSAGetLastError();
   //error here WSAEFAULT always
}

As you can see, i always have error when use getsockname function. Error - WSAEFAULT. But why? structure and structure size are right, why this happens?

WSAEFAULT desc:

The name or the namelen parameter is not a valid part of the user address space, or the namelen parameter is too small.

p.s. Application is 64 bit

Thanks!

Breakdown
  • 1,035
  • 4
  • 16
  • 26

2 Answers2

4

Your struct sockaddr is too small to accept the socket address. Either use an appropriately sized struct, such as struct sockaddr_in, or better yet, use a struct sockaddr_storage, which is guaranteed to be large enough to contain the address. Using a sockaddr_storage also allows you to easily support both IPv4 and IPv6 with minimal adjustments.

Edited code:

struct sockaddr_storage sa;
int sa_len;
sa_len = sizeof(sa);
if (getsockname(socketfd, (struct sockaddr *)&sa, &sa_len) != SOCKET_ERROR)
Hasturkun
  • 35,395
  • 6
  • 71
  • 104
  • Thanks for your answer! But how to get port from `sockaddr_storage`? I don't see `sin_port` value – Breakdown Jan 31 '13 at 11:37
  • 2
    That's easy. You check `sa->ss_family`, and then cast it to the appropriate type, ie. cast to `struct sockaddr_in` for `AF_INET`, and `struct sockaddr_in6` for `AF_INET6` – Hasturkun Jan 31 '13 at 11:41
  • Oh, also, if you want the port for display purposes, you can use `getnameinfo()` to return both the address and the port, all without fiddling with IPv4 and IPv6 specifics. – Hasturkun Jan 31 '13 at 12:47
1

Instead of general struct sockaddr use the one specified for your protocol i.e. *struct sockaddr_in* for IPv4 address. See here for a complete example.

KBart
  • 1,580
  • 10
  • 18