tags:

views:

376

answers:

4

I am trying to implement a function called "inet_pton" which will convert a string representation of an IPv4 or IPv6 (like "66.102.1.147" [google]) into binary network-byte ordered form. Here is the relevant part of my code:

#if defined WIN32
int inet_pton (int af, const char *src, void *dst)

{
    const void *data;
    size_t      len;
    struct      addrinfo hints, *res;

    hints.ai_family   = af;
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_protocol = IPPROTO_UDP;
    hints.ai_flags    = AI_NUMERICHOST;

    if (getaddrinfo (src, NULL, &hints, &res))
    {
        std::cout << "ERROR : inet_pton() in " << __FILE__ << " at line " << __LINE__ << std::endl;
        std::cout << "      : getaddrinfo() failed to get IP address info for \"" << src << "\"" << std::endl;
        return 0;
    }
...

So src is the incoming IP string. However, I always get an error like

getaddrinfo() failed to get IP address info for "66.102.1.147"

Can anyone with winsock experience comment? I also tried another method, the function

WSAStringToAddress ((LPTSTR)src, af, NULL, (LPSOCKADDR) &sa, &address_length)

But it always returns the error code WSAEINVAL, indicating an invalid IP string. This makes no sense to me. I'm using VS2005 as my IDE.

+2  A: 

MSDN has an excellent article on using getaddrinfo:

http://msdn.microsoft.com/en-us/library/ms738520(VS.85).aspx

There is even an example using AI_NUMERICHOST, which sounds like what you need. They setup their "hints" struct a bit differently than you:

ZeroMemory(&hints, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
hints.ai_family = AF_UNSPEC;

They don't set the other 2 properties. Maybe this will help?

Jon Tackabury
+2  A: 

Well, for a start you're asking for a stream socket with UDP as a protocol and that just isn't going to happen.

Try with:

hints.ai_family   = af;
hints.ai_socktype = 0; 
hints.ai_protocol = 0;
hints.ai_flags    = AI_NUMERICHOST;

and memset it to zero first as it has extra members that you're not setting...

Also in my code I pass an empty string for the port or service when I don't have one rather than a null. The docs don't seem to specify what to do when you don't have a value; but either way an empty string works for me.

Oh, and as always in these situations, it would be useful to know what value WSAGetLastError() returns...

Len Holgate
WSAGetLastError was returning WSAEINVAL. Your solution worked, I appreciate the help.
Zac
+2  A: 

What's the value you're passing in for af? I have some code to do the same thing and the only differences between mine and yours are:

  • I memset the hints structure to 0
  • I always pass in PF_UNSPEC for ai_family
  • I use IPPROTO_TCP rather than IPPROTO_UDP.
Graeme Perrow
+1  A: 

you could also use libcurl as a reference. reinventing the wheel isn't always necessary.

sfossen