そのためにどのライブラリを使用しましたか?それらは互いにどの程度互換性がありますか?または、独自の解析ルーチンを作成しましたか?
特に、Java、C ++、Python、JavaScriptの相互互換性のある実装に興味があります。これらは以下をサポートしています。
- ゼロ圧縮( "
::
") - IPv4にマップされたアドレス( "
::ffff:123.45.67.89
") - 正規化(人間が読みやすいように、短い形式を含む)
- CIDRスタイルのネットマスク(
/64
最後の ""など)
そのためにどのライブラリを使用しましたか?それらは互いにどの程度互換性がありますか?または、独自の解析ルーチンを作成しましたか?
特に、Java、C ++、Python、JavaScriptの相互互換性のある実装に興味があります。これらは以下をサポートしています。
::
")::ffff:123.45.67.89
")/64
最後の ""など)POSIXシステムでは、正規化を行うために組み合わせてinet_pton
使用できます。inet_ntop
それでも、独自のCIDR解析を行う必要があります。幸い、IPv6で有効なCIDR構文は/ number_of_bits表記だけなので、かなり簡単です。
あなたが遭遇する他の問題は、インターフェース仕様のサポートの欠如です。リンクローカルアドレスの場合%eth0
、最後にローカルのリンクを指定するようなものが表示されます。 getaddrinfo
それを解析しますが、解析しinet_pton
ません。
実行できる戦略の1つはgetaddrinfo
、解析とinet_ntop
正規化に使用することです。
getaddrinfo
Windowsで利用できます。 inet_pton
そしてそうでinet_ntop
はありません。幸い、正規形のIPv6アドレスを生成するコードを書くのはそれほど難しくありません。ただし、0圧縮のルールは、最初に発生する0の最大の文字列であるため、2つのパスが必要になります。また、IPv4形式(つまり)はまたは::127.0.0.1
にのみ使用されます。::IPv4
::ffff:IPv4
テストするWindowsマシンはありませんが、ドキュメントから、Windows上のPythonがサポートしているように見えinet_pton
ますinet_ntop
。
標準形を作成するための独自のルーチンを作成することは悪い考えではないかもしれません。なぜなら、あなたの標準形が他の人と同じでなくても、それが有効である限り、他の人がそれを解析できるからです。しかし、私はいかなる状況でも、IPv6アドレスを解析するための独自のルーチンを作成することはありません。
上記の私のアドバイスは、Python、C、およびC++に適しています。JavaまたはJavascriptでこの問題を解決する方法についてはほとんどまたはまったく知りません。
編集:私はgetaddrinfoとそれに対応するgetnameinfoを調べてきました。inet_pton
これらは、ほとんどすべての点でおよびよりも優れていますinet_ntop
。これらはスレッドセーフであり、オプション(AI_NUMERICHOST
のgetaddrinfo
場合、およびNI_NUMERCHOST
のgetnameinfo
場合)を渡して、あらゆる種類のDNSクエリを実行しないようにすることができます。それらのインターフェースは少し複雑で、いくつかの点で醜いWindowsインターフェースを思い出させますが、必要なものを取得するために渡すオプションを見つけるのはかなり簡単です。両方を心からお勧めします。
Javaでは、次を使用できます
InetAddress.getByName(IP)
次に、IPv6アドレスを検証するためにこれによってスローされた例外を確認します
よろしければ、SunPropreitaryAPIを使用することもできます。これはDNSルックアップを実行しません。(独自のAPIであるため、予告なしに変更/削除する場合があります。これは、これを使用してコードをコンパイルするときに表示される警告です)
boolean sun.net.util.IPAddressUtil.isIPv6LiteralAddress(String IP)
Javaでは、Guavaライブラリにcom.google.common.net.InetAddressesクラスのIPv6(およびIPv4)を検証するためのユーティリティ関数があります。 http://goo.gl/RucRU
私はまさにこの目的のためにjavascript-ipv6を書きました。現在、v6decode.comに電力を供給しています。
APIの簡単な例を次に示します。
var address = new v6.Address("::ffff:7b2d:4359/64");
if (address.isValid()) {
// Do something if the address is valid
}
console.log(address.correctForm()); // "::ffff:7b2d:4359"
console.log(address.canonicalForm()); // "0000:0000:0000:0000:0000:ffff:7b2d:4359"
console.log(address.v4Form()); // "::ffff:123.45.67.89"
console.log(address.subnetMask); // "64"
console.log(address.possibleAddresses(96)); // "4,294,967,296"
OSサポートが利用できない場合は正規表現を使用します-REはC/C ++ / Java / Python / Perl / bash / ...を含むほとんどの言語で利用できます。次のPythonコードは、起動時にREをビルドし、結果としてREを作成します。 sourceは厄介ですが、reエンジンによってコンパイルされると、ネイティブコードと同じくらい高速になります。
PAT_IP4 = r'\.'.join([r'(?:\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])']*4)
RE_IP4 = re.compile(PAT_IP4+'$')
RE_IP6 = re.compile( '(?:%(hex4)s:){6}%(ls32)s$'
'|::(?:%(hex4)s:){5}%(ls32)s$'
'|(?:%(hex4)s)?::(?:%(hex4)s:){4}%(ls32)s$'
'|(?:(?:%(hex4)s:){0,1}%(hex4)s)?::(?:%(hex4)s:){3}%(ls32)s$'
'|(?:(?:%(hex4)s:){0,2}%(hex4)s)?::(?:%(hex4)s:){2}%(ls32)s$'
'|(?:(?:%(hex4)s:){0,3}%(hex4)s)?::%(hex4)s:%(ls32)s$'
'|(?:(?:%(hex4)s:){0,4}%(hex4)s)?::%(ls32)s$'
'|(?:(?:%(hex4)s:){0,5}%(hex4)s)?::%(hex4)s$'
'|(?:(?:%(hex4)s:){0,6}%(hex4)s)?::$'
% {
'ls32': r'(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|%s)'%PAT_IP4,
'hex4': r'[0-9a-f]{1,4}'
}, re.IGNORECASE)
私が収集できることから、getaddrinfo()
それを備えたシステム、つまりLinuxやPOSIXの場所で使用する必要があります。独自の低レベルパーサーを作成する必要はありません。
Windowsは、XP以降でもを提供します。 getaddrinfo()
Pythonの場合、最適なソリューションはIPy(http://pypi.python.org/pypi/IPy/0.51)です。
getaddrinfoはすでに最短のテキスト形式を返しているため、長い形式の場合は、getaddrinfoを再度実行して正規化できます。Pythonの例、
import sys, socket;
result = socket.getaddrinfo('0:0::0:1', None);
print "family:%i socktype:%i proto:%i canonname:%s sockaddr:%s"%result[0];
以下を出力し、
family:10 socktype:1 proto:6 canonname: sockaddr:('::1', 0, 0, 0)
IPv6 CIDRブロックは十分に文書化または定義されていないようであるため、それを処理するために独自のinet6_network実装を作成しました(C99)。
私は単にアドホックなアプローチを経て、IPV4とIPV6の両方のアドレス指定スキームの有効性をチェックしました。これが私のコードです...私のコードではいつでも修正を歓迎します。私の解決策が間違っているなら、私を許してください。
#include <cstdio>
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
#include <sstream>
#include <utility>
#include <cmath>
#include <cstring>
#include <map>
#include <queue>
#include <limits.h>
using namespace std;
bool check6(string s)
{
for(int i=0;i<s.length();i++)
{
if((s[i] < '0' || s[i] > '9') && (s[i] < 'a' || s[i]> 'f') &&
(s[i] < 'A' || s[i] > 'F'))
return false;
}
return true;
}
bool check4(string s)
{
for(int i=0; i< s.length(); i++)
{
if(!(s[i]>= '0' && s[i] <= '9'))
return false;
}
stringstream ss(s);
int e;
ss >> e;
if( e < 0 || e > 255 )
return false;
else
return true;
}
int main()
{
string s;
cin>>s;
vector<string> v;
int i=0;
int d=0;
if((s.find(":")!=std::string::npos ||
s.find("::")!=std::string::npos)&&
s.find(".")==std::string::npos)
{
int x=0;
while(i< s.length())
{
string s1 ="";
while(i< s.length() && s[i]!= ':')
{
s1+= s[i];
i++;
}
if(s1!="")
v.push_back(s1);
if((i+1)< s.length() && s[i]==':' && s[i+1]==':')
x++;
i++;
if(i< s.length())
d++;
}
if(x > 1 || d > 7 || v.size() > 8 || (x==1 && d >6))
{
cout<<"Not Valid"<<endl;
return 0;
}
else if(d > 2 && v.size() ==0)
{
cout<<"Not Valid"<<endl;
return 0;
}
else
{
for(int i=0;i< v.size();i++)
{
if((v[i]).length() > 4)
{
cout<<"Not Valid"<<endl;
return 0;
}
else
{
if(!check6(v[i]))
{
cout<<"Not Valid"<<endl;
return 0;
}
}
}
cout<<"Valid Ipv6"<<endl;
return 0;
}
}
else if(s.find(":")==std::string::npos && s.find(".")!=std::string::npos)
{
while(i< s.length())
{
string s1="";
while( i< s.length() && s[i]!='.')
{
s1+=s[i];
i++;
}
i++;
if(i< s.length())
d++;
v.push_back(s1);
}
if(d > 4 || v.size()> 4)
{
cout<<"Not Valid"<<endl;
return 0;
}
else
{
for(int i=0;i<v.size();i++)
{
if((v[i]).length() > 3)
{
cout<<"Not Valid"<<endl;
return 0;
}
if(!check4(v[i]))
{
cout<<"Not Valid"<<endl;
return 0;
}
}
}
cout<<"Valid Ipv4"<<endl;
return 0;
}
cout<<"Not Valid"<<endl;
return 0;
}
Python3.1がipaddrlibを失ったのは残念です。
サードパーティのライブラリとして引き続き利用できます:py-ipaddrはPyPIで利用できます。
>>> ipaddr.IPv6Address('0:0::0:1').compressed
'::1'
>>> ipaddr.IPv6Address('::ffff:123.45.67.89').ipv4_mapped
IPv4Address('123.45.67.89')
>>> ipaddr.IPv6Network('::ffff:123.45.67.89/128')
IPv6Network('::ffff:7b2d:4359/128')
C#の場合は、IPNetworkライブラリhttps://github.com/lduchosal/ipnetworkの使用をお勧めします。バージョン2では、IPv4とIPv6もサポートしています。
IPv6
IPNetwork ipnetwork = IPNetwork.Parse("2001:0db8::/64");
Console.WriteLine("Network : {0}", ipnetwork.Network);
Console.WriteLine("Netmask : {0}", ipnetwork.Netmask);
Console.WriteLine("Broadcast : {0}", ipnetwork.Broadcast);
Console.WriteLine("FirstUsable : {0}", ipnetwork.FirstUsable);
Console.WriteLine("LastUsable : {0}", ipnetwork.LastUsable);
Console.WriteLine("Usable : {0}", ipnetwork.Usable);
Console.WriteLine("Cidr : {0}", ipnetwork.Cidr);
出力
Network : 2001:db8::
Netmask : ffff:ffff:ffff:ffff::
Broadcast :
FirstUsable : 2001:db8::
LastUsable : 2001:db8::ffff:ffff:ffff:ffff
Usable : 18446744073709551616
Cidr : 64
楽しむ !