4

のようstruct sockaddrな IPv4 マップ IPv6 アドレスを含む構造があります::ffff:10.0.0.110.0.0.1C言語の文字列(この場合は)でIPv4版のみ取得したい。どうすればそれを達成できますか?

4

3 に答える 3

3

構造体には IPV6 アドレスが含まれているため、構造体を指すstruct sockaddr *ポインター (名前を付けましょう) があると仮定します。addrPtrstruct sockaddr_in6

アドレスバイトを簡単に取得できます。

const uint8_t *bytes = ((const struct sockaddr_in6 *)addrPtr)->sin6_addr.s6_addr;

次に、最初の 12 バイトは重要ではないため (10 0x00、次に 2 0xff)、ポインターに 12 を追加します。最後の4つだけが重要です。

bytes += 12;

これで、これらの 4 バイトを使用して、必要なことを行うことができます。たとえば、それらを IPv4struct in_addrアドレスに格納する場合があります。

struct in_addr addr = { *(const in_addr_t *)bytes };

次に、inet_ntop(で宣言<arpa/inet.h>) を使用して文字列を取得できます。

char buffer[16]; // 16 characters at max: "xxx.xxx.xxx.xxx" + NULL terminator
const char *string = inet_ntop(AF_INET, &addr, buffer, sizeof(buffer));
于 2012-06-27T19:36:48.617 に答える
1

他のタイプのアドレスと互換性を持たせたい場合は、getnameinfo を使用してください。

char hostbuf[NI_MAXHOST];
char *host;

if (getnameinfo(addr, addrlen, hostbuf, sizeof(hostbuf), NULL, 0, NI_NUMERICHOST))
    ;//error

if (strncmp(hostbuf, "::ffff:", sizeof("::ffff:") - 1) == 0)
    host = hostbuf + sizeof("::ffff:") - 1;
else
    host = hostbuf;
于 2012-06-27T21:52:29.347 に答える
0

IPv4 マップ アドレスを認識すると、IPv4 部分は単純にアドレスの最下位 4 バイトになります。これは次のようにできると思います。

struct sockaddr *address;  // this is the address
struct sockaddr_in6 *addrv6 = (struct sockaddr_in6 *)address;
unsigned long address;
memcpy(&address, addrv6->sin6_addr.s6_addr + 11, 4);

ドキュメントには、アドレスがネットワーク順 (最上位バイトが最初) に表示されると記載されています。これがマシン アーキテクチャと異なる場合は、バイト オーダーを逆にするために htonl() を呼び出す必要があります。

于 2012-06-27T19:41:35.787 に答える