What is the Windows XP equivalent of inet_pton or

2019-04-07 06:08发布

问题:

I need to determine whether a particular string is a valid IPv4 or IPv6 address literal. If I understand correctly, the correct way to do this on POSIX systems is to use inet_pton to convert it into a network address structure and see if it succeeds. Windows Vista and later have InetPton which does essentially the same thing. But as far as I can tell, Windows XP doesn't declare either of those, and I need to be able to do this correctly on XP. So, the question is what system function to use to do this?

Worst case, I can write a function to parse it myself, but I'd prefer a standard, system function which has therefore been thoroughly tested and properly handles all corner cases and whatnot. It's already bad enough that Microsoft couldn't just declare inet_pton like everyone else and went with InetPton for their newer OSes.

回答1:

In windows XP you can use these functions:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#include <winsock2.h>
#include <ws2tcpip.h>


int inet_pton(int af, const char *src, void *dst)
{
  struct sockaddr_storage ss;
  int size = sizeof(ss);
  char src_copy[INET6_ADDRSTRLEN+1];

  ZeroMemory(&ss, sizeof(ss));
  /* stupid non-const API */
  strncpy (src_copy, src, INET6_ADDRSTRLEN+1);
  src_copy[INET6_ADDRSTRLEN] = 0;

  if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0) {
    switch(af) {
      case AF_INET:
    *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
    return 1;
      case AF_INET6:
    *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
    return 1;
    }
  }
  return 0;
}

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
{
  struct sockaddr_storage ss;
  unsigned long s = size;

  ZeroMemory(&ss, sizeof(ss));
  ss.ss_family = af;

  switch(af) {
    case AF_INET:
      ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
      break;
    case AF_INET6:
      ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
      break;
    default:
      return NULL;
  }
  /* cannot direclty use &size because of strict aliasing rules */
  return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0)?
          dst : NULL;
}

That's it. Link with ws2_32 library.



回答2:

But as far as I can tell, Windows XP doesn't declare either of those, and I need to be able to do this correctly on XP.

InetPton documentation states the following requirements:

  • Minimum supported client: Windows Vista [desktop apps only]
  • Minimum supported server: Windows Server 2008 [desktop apps only]

Worst case, I can write a function to parse it myself, but I'd prefer a standard, system function which has therefore been thoroughly tested and properly handles all corner cases and whatnot.

How about relying of a portion of code from the OSS network tool Wireshark?

You can find their reimplementation of inet_pton in their source code repository.

The licence (see below) is very permissive, so that may be a good alternative.

Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.



回答3:

Looking through the SDK header files I find inet_pton() declared in "c:\Program Files\Microsoft SDKs\Windows\v7.1\Include\WS2tcpip.h". InetPton is only a #define to that.

So, it seems MS is providing the proper interface after all, but only starting with Vista. But XP has no IPv6 support that is worth mentioning, if I recall correctly.

The other choice is to wrap it yourself with two calls to WSAAddressToString(), one with AF_INET, one with AF_INET6. I'm guessing here from the docs, haven't tried it.