4

IP アドレス/ネットマスクを in_addr/in6_addr 構造体に格納する必要があります。IPv4 の場合、次のコードを使用して、ネットマスクが連続しているかどうかをテストします。

((((~netmask + 1) & (~netmask)) != 0)  && (netmask != 0))

IPv6で同じことを行うスマートな方法があるかどうか疑問に思っていました.

4

2 に答える 2

1

私は次の解決策に出くわしました:

IPV6 バイトを 32 ビットの 4 つのチャンクに分割し、次の方法で 3 つの部分を作成します。

uint64_t netmask1, netmask2, netmask3;
netmask1 = (netmask.s6_addr32[0] << 32) + in6_netmask.s6_addr32[1];
netmask2 = (netmask.s6_addr32[1] << 32) + in6_netmask.s6_addr32[2];
netmask3 = (netmask.s6_addr32[2] << 32) + in6_netmask.s6_addr32[3];

この部分の 1 つが連続していない場合、ネットマスクは連続していません。

 if ((((~address1 + 1) & (~address1)) != 0) ||
    (((~address2 + 1) & (~address2)) != 0) ||
    ((~address3 + 1) & (~address3)) != 0))) {
  // Netmask is not valid!
}
于 2015-01-06T21:19:53.157 に答える
1

一部のコンパイラには 128 ビット整数があります。AMD64 アーキテクチャで gcc を使用してコンパイルされたコードで __uint128_t を使用しました。

128 ビット整数のコンパイラを使用している場合、既存のコードを単純に再利用できます。これは、ワード サイズに関する仮定がないためです。

より小さなワード サイズで計算を実行する必要がある場合、当然複雑になりますが、それほど多くはありません。最初にマスクの単語を介してポインターを実行し、ビットがゼロの最初の単語を見つけます (たとえば)。

for (i = 0; i < 4 && netmask[i] != 0xffffffff; ++i)

次に、元のテストを に適用できます。netmask[i]最後に、残りの単語がゼロであることをテストする必要があります。

別のアプローチは、元のテストを個々の単語に適用し、さらに、単語のすべてのペアが最初がすべて 1 であるか、2 番目がすべて 0 であるかをテストすることです。

int contiguous(uint32_t **netmask)
{
    int i;
    for (i = 0; i < 4; ++i) {
        if ((~netmask[i] + 1) & (~netmask[i])) return 0;
    }
    for (i = 0; i < 3; ++i) {
        if ((netmask[i] != 0xffffffff) && (netmask[i+1] != 0)) return 0;
    }
    return 1;
}

マスクを入力として使用せず、代わりに 0 ~ 128 の範囲の整数として指定されたプレフィックス長を入力として使用する、より一般的な方法を使用することもできます。次に、ビットマスクを自分で構築し、それが連続していることを知ることができます。

于 2014-12-27T15:23:02.993 に答える