4

私はIPv6プロトコルについてあまり知識がないので、質問がばかげていると思われる場合は申し訳ありません。ネットワーク内のすべてのIPv6アドレスのリストを取得すると、以下に示すように、scopeという名前のフィールドが表示されます。

      inet6 addr: 2001:470:1:82::11/64 Scope:Global
      inet6 addr: 2001:470:1:82::10/64 Scope:Global
      inet6 addr: 2001:470:1:82::13/64 Scope:Global
      inet6 addr: fe80::21d:9ff:fe69:2c50/64 Scope:Link
      inet6 addr: 2001:470:1:82::12/64 Scope:Global
      inet6 addr: 2001:470:1:82::15/64 Scope:Global
      inet6 addr: 2001:470:1:82::14/64 Scope:Global
      inet6 addr: 2001:470:1:82::5/64 Scope:Global
      inet6 addr: 2001:470:1:82::17/64 Scope:Global
      inet6 addr: 2001:470:1:82::6/64 Scope:Global
      inet6 addr: 2001:470:1:82::16/64 Scope:Global
      inet6 addr: 2001:470:1:82::7/64 Scope:Global
      inet6 addr: 2001:470:1:82::19/64 Scope:Global
      inet6 addr: 2001:470:1:82::8/64 Scope:Global
      inet6 addr: 2001:470:1:82::18/64 Scope:Global
      inet6 addr: 2001:470:1:82::9/64 Scope:Global
      inet6 addr: 2001:470:1:82::1b/64 Scope:Global
      inet6 addr: 2001:470:1:82::a/64 Scope:Global
      inet6 addr: 2001:470:1:82::1a/64 Scope:Global
      inet6 addr: 2001:470:1:82::b/64 Scope:Global
      inet6 addr: 2001:470:1:82::1d/64 Scope:Global
      inet6 addr: 2001:470:1:82::c/64 Scope:Global
      inet6 addr: 2001:470:1:82::1c/64 Scope:Global
      inet6 addr: 2001:470:1:82::d/64 Scope:Global
      inet6 addr: 2001:470:1:82::1f/64 Scope:Global
      inet6 addr: 2001:470:1:82::e/64 Scope:Global
      inet6 addr: 2001:470:1:82::1e/64 Scope:Global
      inet6 addr: 2001:470:1:82::f/64 Scope:Global
      inet6 addr: ::1/128 Scope:Host

私のアプリケーションでは、スコープが「リンク」であるアドレスを取得する必要があります。ifconfigへのシステムコールを使用してから、出力を解析して対応するアドレスを抽出することもできます。しかし、問題は、getifaddrs()の呼び出しを使用していることです。これは、次のように指定された構造体ifaddrのリンクリストを返します。

       struct ifaddrs {
           struct ifaddrs  *ifa_next;    /* Next item in list */
           char            *ifa_name;    /* Name of interface */
           unsigned int     ifa_flags;   /* Flags from SIOCGIFFLAGS */
           struct sockaddr *ifa_addr;    /* Address of interface */
           struct sockaddr *ifa_netmask; /* Netmask of interface */
           union {
               struct sockaddr *ifu_broadaddr;
                                /* Broadcast address of interface */
               struct sockaddr *ifu_dstaddr;
                                /* Point-to-point destination address */
           } ifa_ifu;
       #define              ifa_broadaddr ifa_ifu.ifu_broadaddr
       #define              ifa_dstaddr   ifa_ifu.ifu_dstaddr
           void            *ifa_data;    /* Address-specific data */
       };

問題は、このリストから「リンク」スコープのアドレスを取得する方法です。

4

3 に答える 3

8

支援するヘルパーマクロがあります:

struct sockaddr_in6 s6;
if (IN6_IS_ADDR_LINKLOCAL(&s6.sin6_addr)) {
  puts ("link-local");
} else if (IN6_IS_ADDR_SITELOCAL(&s6.sin6_addr)) {
  puts ("site-local");
} else if (IN6_IS_ADDR_V4MAPPED(&s6.sin6_addr)) {
  puts ("v4mapped");
} else if (IN6_IS_ADDR_V4COMPAT(&s6.sin6_addr)) {
  puts ("v4compat");
} else if (IN6_IS_ADDR_LOOPBACK(&s6.sin6_addr)) {
  puts ("host");
} else if (IN6_IS_ADDR_UNSPECIFIED(&s6.sin6_addr)) {
  puts ("unspecified");
} else {
  puts ("global");
}
于 2012-12-29T16:31:36.650 に答える
6

これを行う1つの方法は、アドレスが内にあるかどうかを確認することfe80::/10です。IPv6アドレス空間はIANAから入手できます。これには、使用可能なスコープの詳細が記載されています。

ソースコードをnet-tools(ifconfigのソースパッケージ)にダウンロードしましたが、解析しているよう/proc/net/if_inet6です。(コメントは、次のコードへの私自身の追加です。また、以下は非常に簡略化されており、コンパイルされないことは間違いありません。)

/* some defines collected around the place: */

#define _PATH_PROCNET_IFINET6   "/proc/net/if_inet6"
#define IPV6_ADDR_LOOPBACK      0x0010U
#define IPV6_ADDR_LINKLOCAL     0x0020U
#define IPV6_ADDR_SITELOCAL     0x0040U
#define IPV6_ADDR_COMPATv4      0x0080U

int scope; /* among other stuff */

/* looks like here we parse the contents of /proc/net/if_inet6: */

if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
          addr6p[0], addr6p[1], addr6p[2], addr6p[3],
          addr6p[4], addr6p[5], addr6p[6], addr6p[7],
      &if_idx, &plen, &scope, &dad_status, devname) != EOF) {

/* slightly later: */

printf(_(" Scope:"));
switch (scope) {
case 0:
    printf(_("Global"));
    break;
case IPV6_ADDR_LINKLOCAL:
    printf(_("Link"));
    break;
case IPV6_ADDR_SITELOCAL:
    printf(_("Site"));
    break;
case IPV6_ADDR_COMPATv4:
    printf(_("Compat"));
    break;
case IPV6_ADDR_LOOPBACK:
    printf(_("Host"));
    break;
default:
    printf(_("Unknown"));
}

それでは、上記の構文解析を見てみましょう。

$ cat /proc/net/if_inet6
20010db8000008000000000000000001 03 40 00 00     eth0
fe800000000000000000000000004321 03 40 20 80     eth0
00000000000000000000000000000001 01 80 10 80       lo

0x00したがって、左から3番目の列(グローバル、0x20リンクローカル、および0x10ループバック)がスコープであることがわかります。net-toolsコードからの上記の定数を使用して、それらが何を意味するかを理解することができます。/proc/net/if_inet6このような定数のより信頼できる情報源を特定し、構文解析が最善の選択肢であるかどうかを判断するには、さらに調査が必要です。

于 2012-07-24T14:24:08.770 に答える
1

スコープがそのデータ構造に明示的に格納されているとは思いません。ただし、IPアドレス自体からスコープを推測することはできます。http://en.wikipedia.org/wiki/IPv6_address#Address_scopesを参照してください

于 2012-07-24T14:17:31.037 に答える