[2] [DFN[IPv6 [RUBYB[アドレス]@en[address]]]]は、[[IPv6]] において通信の当事者を[[識別]]する[RUBY[[[番地]]]@en[[[アドレス]]]]です。 * IPv6 アドレスの文字列表現 [3] [[IPv6アドレス]]は [CODE@en[ABCD:EF01:2345:6789:ABCD:EF01:2345:6789]] のように16進数を16ビットごとに「[CODE(char)[[[:]]]]」で区切って表記することになっています。 ** 仕様書 - [4] [[RFC 4291]] -- [CSECTION@en[2.2. Text Representation of Addresses]] - [22] [[RFC 5952]] [CITE@en[A Recommendation for IPv6 Address Text Representation]] ([[IETF提案標準]]) ** 構文 [24] 以下で「制約」として述べるのは [[RFC 5952]] によって追加された規定です。 実装は引き続きそれに従わない旧来の形式の[[IPv6アドレス]]も受け付けなければ[['''なりません''']] が、生成する時は制約に従う[['''べきです''']]し、人間が書くときも従うのが[RUBYB[よいでしょう]@en[advised]] [SRC[>>22 4.]]。 ;; [25] 以下の「制約」は「[['''しなければなりません''']]」と述べているものの、 >>24 により実質的には「[['''するべきです''']]」レベルの要件になってしまいます。 - [6] [RUBYB[好ましい形]@en[preferred form]]は、16進数を16ビット分ずつ8回繰り返す表記です。 [SRC[>>4 2.2. 1.]] -- 例: [CODE[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]] - [7] ただし[[先導0]]は省略できます。 [SRC[>>4 2.2. 1.]] -- 例: [CODE[1080:0:0:0:8:800:200C:417A]] -- [26] 制約: [[先導0]]は省略しなければ[['''なりません''']]。 [SRC[>>22 4.1.]] - [8] 0ばかりが続くところは1回だけ「[CODE[[[::]]]]」により省略できます。 [SRC[>>4 2.2. 2.]] -- 例: [CODE[FF01::43]] = [CODE[FF01:0:0:0:0:0:0:43]] -- 例: [CODE[::]] = [CODE[0:0:0:0:0:0:0:0]] -- [27] 制約: 最短形でなければ[['''なりません''']]。 [SRC[>>22 4.2.1.]] --- 例: [CODE[2001:db8::2:1]] = × [CODE[2001:db8:0:0:0:0:2:1]] = × [CODE[2001:db8::0:1]] -- [28] 制約: [CODE[[[::]]]] は1つだけの「[CODE[[[0]]]]」の省略に使っては[['''なりません''']]。 [SRC[>>22 4.2.2.]] --- 例: [CODE[2001:db8:0:1:1:1:1:1]] = × [CODE[2001:db8::1:1:1:1:1]] -- [29] 制約: [CODE[[[::]]]] は一番長い「[CODE[[[0]]]]」の連続に使わなければ[['''なりません''']]。 [SRC[>>22 4.2.3.]] --- 例: [CODE[2001:0:0:1::1]] = × [CODE[2001::1:0:0:0:1]] = × [CODE[2001:0:0:1:0:0:0:1]] -- [30] 制約: [CODE[[[::]]]] を使う最長の「[CODE[[[0]]]]」の連続が複数ある時は最初のものに使わなければ[['''なりません''']]。 [SRC[>>22 4.2.3.]] --- 例: [CODE[2001:db8::1:0:0:1]] = × [CODE[2001:db8:0:0:1::1]] = × [CODE[2001:db8:0:0:1:0:0:1]] - [9] 最後の32ビットを[[IPv4アドレス]]形式で表記できます。 [SRC[>>4 2.2. 3.]] -- 例: [CODE[0:0:0:0:0:FFFF:129.144.52.38]] -- 例: [CODE[::FFFF:129.144.52.38]] -- [32] [[IPv4アドレス]]を埋め込んだものであると[[接頭辞]]だけから判断できる場合、この混合表記を用いる[['''べきです''']]。 [SRC[>>22 5.]] - [31] 制約: [[16進数]]には[[小文字]]を使わなければ[['''なりません''']]。 [SRC[>>22 4.3.]] -- 「[[D]]」と「[[0]]」、「[[8]]」と「[[B]]」のように[[大文字]]は紛らわしいからだそうです [SRC[>>22 3.4.3.]]。 *** ABNF 定義 [50] [[RFC 3986]] では構文を [[ABNF]] で表現しています。 ;; - [51] [[RFC 3986]] [CITE@en[Uniform Resource Identifier (URI): Generic Syntax]] -- [52] [CSECTION@en[3.2.2. Host]] [53] [PRE(ABNF code)[ IPv6address = 6( h16 ":" ) ls32 / "::" 5( h16 ":" ) ls32 / [ h16 ] "::" 4( h16 ":" ) ls32 / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 / [ *4( h16 ":" ) h16 ] "::" ls32 / [ *5( h16 ":" ) h16 ] "::" h16 / [ *6( h16 ":" ) h16 ] "::" ls32 = ( h16 ":" h16 ) / IPv4address ; least-significant 32 bits of address h16 = 1*4HEXDIG ; 16 bits of address represented in hexadecimal ]PRE] [54] この定義はかなり厳密ですが、 [[RFC 5952]] の制約は反映されていません。 (時期的にもそうですし、 技術的にも困難そうです。) [55] [[RFC 5321]] にも [[ABNF]] 定義がありますが、少し簡潔な分、不完全な定義になっています。 ;; - [58] [[RFC 2821]] [CITE@en[Simple Mail Transfer Protocol]] (廃止済み) -- [59] [CSECTION@en[4.1.3 Address Literals]] - [56] [[RFC 5321]] [CITE@en[Simple Mail Transfer Protocol]] -- [57] [CSECTION@en[4.1.3. Address Literals]] ** IPv4 アドレスが埋め込まれた IPv6 アドレス [36] >>32 によれば事前の知識により [[IPv4アドレス]]が埋め込まれていると[[接頭辞]]から判断できる [[IPv6アドレス]]は混合表記を使うべきです。これに該当する[[接頭辞]]は以下のものがあります。 - [37] [[::/96]] ([[IPv4互換IPv6アドレス]]) [[RFC 4291]] 2.5.5.1. - [38] [[::ffff:0:0/96]] ([[IPv4写像IPv6アドレス]]) [[RFC 4291]] 2.5.5.2. - [38] [[::ffff:0:0:0/96]] ([[IPv4翻訳IPv6アドレス]]) [[RFC 2765]] ;; [39] [[2008:db8::]] はしばしば [[IPv4アドレス]]を埋め込まれて使われるのを見かけますが、 これは [[RFC 3849]] で説明用に予約されている[[アドレス]]群なので、 純粋な [[IPv6アドレス]]として使われることもあり、>>32 には該当しません。 ** 問題点 - [10] 16進数表記の1部分の最大桁数が明確に定義されていません。「16ビット分」なので常識的には4桁ですが、先頭に「0」を付ければ同じ意味でいくらでも長くできます。 - [11] 16進数アルファベットが明確に定義されていません。例示はすべて[[大文字]]になっていますが、[[小文字]]でもよいのかは不明確です。 -- これは後に [[RFC 5952]] で[[小文字]]を使うように指示されています。 - [12] [[IPv4アドレス]]の表記法が明確に定義されていません。常識扱いされているようです。 - [13] >>8 と >>9 により文字列表記が一意に確定しないので、比較など場面によっては困りそうです。 -- これは後に [[RFC 5952]] で厳密化されましたが、やはり [[IPv4アドレス]]の表記で曖昧性が残ります。 -- そもそも [[IPv4アドレス]]が埋め込まれているかどうか自体が事前に一意に決定できないので仕方がない面はあります。 [[RFC 5952]] でも >>32 のように若干曖昧な規定となっています。 ** 歴史 [5] [[RFC 4291]] (>>4) 以前にも、[[RFC 3513]], [[RFC 2373]], [[RFC 1884]] の同じく [CSECTION@en[2.2. Text Representation of Addresses]] で[[IPv6アドレス]]の文字列表現が定義されていました。 これらは同じ [[RFC]] の他の部分の変更に伴う改訂で、文字列表現の部分はずっと変更されていません。 [23] >>5 の定義は柔軟で場面によっては却って使いづらいことがあり、[[RFC 5952]] でより好ましい表記方法が選択されることになりました。 [40] [[RFC 2373]] では[[附属書]]として文字列表現の [[ABNF]] 構文が追加されました。 この定義は実は間違っていて、 × [CODE@en[2001:db8:::192.0.2.1]] のような正しくない[[アドレス]]が[[生成]]されるものでした。 この [[ABNF]] は [[RFC 3513]] でなぜか削除されています。 [41] [[RFC 3261]] ([[SIP]]) は [[RFC 2373]] の [[ABNF]] を[[コピペ]]していたために同じ間違いを抱えており [SRC[>>48]]、 [[RFC 5954]] で訂正されています。 [[RFC 5954]] は [[RFC 3986]] からコピペしています。 [WEAK[(同時に [[IPv4アドレス]]の構文も厳密化されています。)]] ;; [[RFC 3261]] の前の版である [[RFC 2543]] は [[IPv6]] に対応していませんでした。 ;; -[47] [[RFC 3261]] [CITE@en[SIP: Session Initiation Protocol]] -- [48] [CSECTION@en[25.1 Basic Rules]] -[49] [[RFC 5954]] [CITE@en[Essential Correction for IPv6 ABNF and URI Comparison in RFC 3261]] [60] はじめて [[IPv6アドレス]]を [[URL]] に導入した [[RFC 2732]] ([[RFC 3986]] により廃止) は、[CODE(ABNF)@en[[[IPv6address]]]] の定義を >>40 の [[RFC 2373]] を参照しており、 同じ間違いを含有していました。[[RFC 3986]] では独自定義 (>>53) に変更することで修正されています。 * IPv6 アドレス接頭辞の文字列表現 [14] [[IPv6アドレス]]の[[接頭辞]]は「[CODE[2001:0DB8:0:CD30::/60]]」のように [[IPv6アドレス]]の後に先頭からのビット数を併記して表すことになっています。 ** 仕様書 - [15] [[RFC 4291]] -- [CSECTION@en[2.3. Text Representation of Address Prefixes]] ** 構文 [17] [SRC[>>15]] = [[IPv6アドレス]]の文字列表現 = [CODE(char)[[[/]]]] = 先頭から何ビット分かを表す整数 [18] [[IPv6アドレス]]は任意の文字列表現を使えるので、[CODE[[[::]]]] による省略も使えますが、 省略を展開してからビット長が適用されることに注意が必要です。 ;; 例えば [CODE[2001:0DB8::CD30/60]] は [CODE[2001:0DB8:0000:0000:0000:0000:0000:CD30/60]] と同じ意味で、[[接頭辞]]として考えると最後の「[CODE[CD30]]」は意味がなくなります。 これは[[接頭辞]]としてはおかしな表記ですが、 >>20 の用法では意味があります。 ** 歴史 [16] [[RFC 4291]] (>>15) 以前にも、[[RFC 3513]], [[RFC 2373]] の同じく [CSECTION@en[2.2. Text Representation of Addresses]] で[[IPv6アドレス]]の文字列表現が定義されていました。 これらは同じ [[RFC]] の他の部分の変更に伴う改訂で、文字列表現の部分はずっと変更されていません。 ;; [[RFC 2373]] の前の版である [[RFC 1884]] の時点では[[接頭辞]]の文字列表現は定義されていませんでした。 ** 例 [19] [SRC[>>15]] - [CODE[2001:0DB8:0000:CD30:0000:0000:0000:0000/60]] - [CODE[2001:0DB8::CD30:0:0:0:0/60]] - [CODE[2001:0DB8:0:CD30::/60]] これらはいずれも[[接頭辞]]として [CODE[20010DB80000CD3]] を表します。 * 節点のIPv6アドレスと接頭辞の併記 [20] [[IPv6アドレス]]の[[接頭辞]]の文字列表現を使って、 [RUBYB[[[節点]]]@en[node]]の[[IPv6アドレス]]と、その属する[[ネットワーク]]の[[IPv6アドレス]]の[[接頭辞]]を併記することができます。 [21] 例えば、 - [[節点]] [CODE[2001:0DB8:0:CD30:123:4567:89AB:CDEF]] - [[ネットワーク]] [CODE[2001:0DB8:0:CD30::/60]] ... は略して - [CODE[2001:0DB8:0:CD30:123:4567:89AB:CDEF/60]] ... と表記できます [SRC[>>15]]。 * ポート番号との併記 [33] [[TCP]] や [[UDP]] の[[ポート番号]]と [[IPv6アドレス]]を併記する場合にはいろいろな方法が採られています。 [[URL]] などでは「[CODE[[[:]]]]」が区切りに使われてきましたが、[[IPv6アドレス]]内部でも「[CODE[[[:]]]]」 が区切りに使われるため、曖昧性が生じます。 [[RFC 5952]] は基本的には [[IPv6アドレス]]を「[CODE(char)[[['''[''']]]]」,「[CODE(char)[[[''']''']]]]」 で括る方法 ([[URL]] で採用されている方法) を推奨しています。 ** 仕様書 - [34] [[RFC 5952]] [CITE@en[A Recommendation for IPv6 Address Text Representation]] ([[IETF提案標準]]) -- [CSECTION@en[6. Notes on Combining IPv6 Addresses with Port Numbers]] ** 例 [35] [SRC[>>34 6.]] - [CODE@en[ [2001:db8::1]:80 ]] 別途規定がなければこれを使う[['''べきです''']] - [CODE@en[2001:db8::1:80]] これは使う[['''べきではありません''']] - [CODE@en[2001:db8::1.80]] - [CODE@en[2001:db8::1 port 80]] - [CODE@en[2001:db8::1p80]] - [CODE@en[2001:db8::1#80]] 文脈的に曖昧性がなければ3つ目以降の書式を使っても問題ないとされています。 * ドメイン名や IPv4 アドレスとの併記 [42] [[IPv6アドレス]]は「[CODE(char)[[[:]]]]」を使っているので、 [[ドメイン名]]や[[IPv4アドレス]]とは完全に区別ができます。 ** URL の場合 [43] しかし、[[URL]] では >>33 の[[ポート番号]]の問題があるため、 [[IPv6アドレス]]は「[CODE(char)[[['''[''']]]]」,「[CODE(char)[[[''']''']]]]」 で括られることになっており、括られない[[ドメイン名]]や[[IPv4アドレス]]と区別されます。 [44] なお、 [[URL]] は将来の版の [[IP]] にも対応する構文があり、 [CODE(URI)['''['''v[VAR[n]].[VAR[...]]''']''']] のように記述できます。 「[CODE(URI)[v[VAR[n]].]]」の部分で [[IPv6アドレス]]と区別されます。 ** 電子メール・アドレスの場合 [45] [[電子メール]]の[[アドレス]]では以前から[[ドメイン名]]はそのまま、 [[IPv4アドレス]]は「[CODE(char)[[['''[''']]]]」,「[CODE(char)[[[''']''']]]]」 で括って表記、と区別がされてきました。 [46] [[IPv6アドレス]]は「[CODE(char)[[['''[''']]IPv6:]]」,「[CODE(char)[[[''']''']]]]」 となって更に区別されています。 * メモ [1] [CITE@en[IPv6 validation (and caveats) - Crisp's blog]] ([TIME[2009-07-05 12:39:37 +09:00]] 版) >I started out with the RFC mentioned in the title of the request, which was RFC-2732 which referred to RFC-2373 for the ABNF syntax of IPv6 >however, I quickly noticed that this expression (and thus the ABNF in the RFC) couldn't be correct because it doesn't limit the number of hex4 groups and is totally wrong in the way it checks for an IPv4 formatted part. > Luckily this has been fixed in RFC-3986 which mentions the following ABNF >Now that's something else... Also note how this strictly defines the format of an IPv4 address. This either called for a monstrous regular expression or a tokenizing approach. I started out with the latter but quickly abandoned it because it became rather chaotic and didn't perform very well. >These are 3 examples of invalid addresses which pass using PHP's filter_var: [PRE[ ::01.02.03.04 (leading zero's not allowed in IPv4 part digits) 0:0:0:255.255.255.255 (not enough parts and no compression) 1fff::a88:85a3::172.31.128.1 (only one part may be compressed) ]PRE]