EN JA
IP6(4)
IP6(4) FreeBSD Kernel Interfaces Manual IP6(4)

名称

ip6インターネットプロトコルバージョン 6 (IPv6) ネットワークレイヤ (層)

書式

#include < sys/socket.h>
#include < netinet/in.h>

int
socket( AF_INET6, SOCK_RAW, proto);

解説

IPv6 ネットワーク層 (レイヤ) は、データを転送するために IPv6 プロトコルファミリによって使用されます。 IPv6 パケットは、アプリケーションに渡されるときペイロード (訳注: ヘッダ部を除いたデータの本体) コンテンツ (内容) の一部として提供されない IPv6 ヘッダを含んでいます。 IPv6 ヘッダオプションは、このプロトコルの振る舞いに影響して、直接低レベルで IPv6 メッセージを処理する“生のソケット”と同様に ( tcp(4)udp(4) プロトコルのような) 高レベルのプロトコルによって使用され、新しいプロトコルと特殊目的のアプリケーションの開発に役立ちます。

ヘッダ

すべての IPv6 パケットは、IPv6 ヘッダで始まります。カーネルによって受信されたデータがアプリケーションに渡されるとき、生のソケットが使用されているときでさえ、このヘッダは、バッファに含まれていません。同様に、アプリケーションから転送されるデータがカーネルに送られるとき、バッファは、IPv6 ヘッダを調べません: カーネルは、常にヘッダを構築します。受信れたパケットから IPv6 ヘッダに直接アクセスして、カーネルに渡されたバッファの一部としてそれらを指定するためには、リンクレベルアクセス (例えば、 bpf(4)) を代わりに利用しなければなりません。

ヘッダには、次の定義があります:

struct ip6_hdr { 
     union { 
          struct ip6_hdrctl { 
               uint32_t  ip6_un1_flow; /* フロー ID の 20 ビット */ 
               uint16_t  ip6_un1_plen; /* ペイロード長 */ 
               uint8_t  ip6_un1_nxt; /* 次のヘッダ */ 
               uint8_t  ip6_un1_hlim; /* 中継限界数 (hop limit) */ 
          } ip6_un1; 
          uint8_t ip6_un2_vfc; /* バージョンとクラス */ 
     } ip6_ctlun; 
     struct in6_addr ip6_src; /* 発信元 (始点) アドレス 
            (source address) */ 
     struct in6_addr ip6_dst; /* 宛先 (終点) アドレス 
            (destination address) */ 
} __packed; 
 
#define ip6_vfc  ip6_ctlun.ip6_un2_vfc 
#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow 
#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen 
#define ip6_nxt  ip6_ctlun.ip6_un1.ip6_un1_nxt 
#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim 
#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim

すべてのフールドは、ネットワークバイト順です。どんなオプション指定 (下記の 「オプション」 参照) もネットワークバイト順で指定しなければなりません。

ip6_flow は、フロー ID を指定します。 ip6_plen は、ペイロードの長さを指定します。 ip6_nxt は、次のヘッダのタイプを指定します。 ip6_hlim は、中継限界数 (hop limit) を指定します。

ip6_vfc の最上位 4 ビットは、クラスを指定し、下位 4 ビットは、バージョンを指定します。

ip6_srcip6_dst は、発信元 (始点) アドレスと宛先 (終点) アドレスを指定します。

IPv6 ヘッダは、次の一般的な定義で始まるいくつもの拡張ヘッダが続きます:

struct ip6_ext { 
     uint8_t ip6e_nxt; 
     uint8_t ip6e_len; 
} __packed;

オプション

IPv6 は、パケットのヘッダオプションがプロトコルの振る舞いを操作することを許します。これらのオプションと他のコントロール要求は、レベル IPPROTO_IPV6recvmsg(2)sendmsg(2) の付属のデータを使用することによって、 getsockopt(2)setsockopt(2) システムコールでアクセスされます。それらは、IPv6 ヘッダと拡張ヘッダ中のフィールドの大部分にアクセスするために使用することができます。

次のソケットオプションがサポートされています:

IPV6_UNICAST_HOPS int *
このソケットに送信された発信ユニキャストデータグラムのためのデフォルトの中継限界数 (hop limit) ヘッダフィールドを取得するか、または設定します。
IPV6_MULTICAST_IF u_int *
マルチキャストパケットが送信されるインタフェースを取得するか、または設定します。複数のインタフェースがあるホストに関しては、それぞれのマルチキャスト送信は、プライマリネットワークインタフェースから送信されます。インタフェースは、 if_nametoindex(3) によって提供されるインデックスとして指定されます。 0 の値は、デフォルトのインタフェースを指定します。
IPV6_MULTICAST_HOPS int *
このソケットに送信された発信マルチキャストデータグラムのためのデフォルトの中継限界数 (hop limit) ヘッダフィールドを取得するか、または設定します。このオプションは、マルチキャストデータグラム送信のスコープを制御します。

1 の中継限界数 (hop limit) があるデータグラムは、ローカルネットワークを超えて転送されません。 0 の中継限界数 (hop limit) があるデータグラムは、どんなネットワークにも転送されませんが、送信ホストが宛先 (終点) グループに属していて、マルチキャストループバック (下記参照) が送信ソケット上で無効にされないなら、ローカルには配信されます。 1 以上の中継限界数 (hop limit) があるデータグラムは、 ( mrouted(8) ( ports/net/mrouted) のような) マルチキャストルータがローカルネットワークにアタッチされているなら、他のネットワークに転送されます。

IPV6_MULTICAST_LOOP u_int *
マルチキャストデータグラムが送信ホストが属するグループに送信されるとき、ローカルの配信のためにマルチキャストデータグラムがループバックするかどうかに関する状態を取得するか、または設定します。

このオプションは、それら自身の送信を受信するオーバヘッドを取り除くことによって (ルータデーモンのような) 単一のホスト上で 1 つ以下のインスタンスがあるアプリケーションの性能を向上させます。一般的に、(会議プログラムのような) 単一のホスト上で 1 つ以上のインスタンスがある、または送信側が (時間問い合わせプログラムのような) 宛先 (終点) グループに属さないアプリケーションでそれを使用するべきではありません。

1 以上の中継限界数 (hop limit) があるデータグラムの送信は、ホストがその他のインタフェースで宛先 (終点) グループに属すなら、それが送信されたことによって異なったインタフェースで送信ホストに配信されます。マルチキャストループバック制御オプションは、そのような配信のときに効果がありません。

IPV6_JOIN_GROUP struct ipv6_mreq *
マルチキャストグループに加わります。ホストは、グループに送られたデータグラムを受信する前にマルチキャストグループのメンバにならなければなりません。

struct ipv6_mreq { 
 struct in6_addr ipv6mr_multiaddr; 
 unsigned int ipv6mr_interface; 
};

ipv6mr_interface は、ホストがマルチホームであるるなら、デフォルトマルチキャストインタフェースを選ぶために、または、特定のマルチキャスト能力があるインタフェースのインデックスのために 0 に設定されます。メンバシップは、単一のインタフェースに関連しています。マルチホームホストで実行しているプログラムは、 1 つ以上のインタフェースで同じグループにに加わる必要があります。

マルチキャストアドレスが不特定 (すなわち、すべて 0) であるなら、すべてのマルチキャストアドレスからのメッセージは、このグループによって受け付けられます。この値に設定することは、スーパユーザの特権が必要であることに注意してください。

IPV6_LEAVE_GROUP struct ipv6_mreq *
関連するマルチキャストグループからメンバシップを脱会します。メンバシップは、ソケットがクローズされるときかプロセスが終了するとき、自動的に脱会されます。
IPV6_PORTRANGE int *
カーネルが自動的にローカルアドレスをこのソケットにバインドするとき、短命のポートの割り付けポリシを取得するか、または設定します。次の値が利用可能です:

IPV6_PORTRANGE_DEFAULT
予約されていないポート (異なったものについては、 ip(4) 参照) の正規の範囲を使用します。
IPV6_PORTRANGE_HIGH
高い範囲を使用します (異なったものについては、 ip(4) 参照)。
IPV6_PORTRANGE_LOW
低く予約された範囲 (600-1023、 ip(4) 参照) を使用します。
IPV6_PKTINFO int *
その後の recvmsg(2) 呼び出しでペイロードに伴う付属のデータとして提供されるその後のパケットに関する追加情報かどうかを取得するか、または設定します。返された付属データで次の構造体に情報は格納されます:

struct in6_pktinfo { 
 struct in6_addr ipi6_addr;    /* src/dst IPv6 アドレス */ 
 unsigned int    ipi6_ifindex; /* send/recv if index */ 
};
IPV6_HOPLIMIT int *
その後の recvmsg(2) 呼び出しでペイロードに伴う付属のデータとして提供されるその後のパケットからの中継限界数 (hop limit) のヘッダフィールドかどうかを取得するか、または設定します。値は、返された付属のデータの int として格納されます。
IPV6_HOPOPTS int *
その後の recvmsg(2) 呼び出しでペイロードに伴う付属のデータとして提供されるその後のパケットからの中継点ごと (hop-by-hop) のオプションかどうかを取得するか、または設定します。オプションは、返された付属のデータで次の構造体に格納されます:

struct ip6_hbh { 
 uint8_t ip6h_nxt; /* 次のヘッダ */ 
 uint8_t ip6h_len; /* 8 オクテットのユニットの長さ */ 
/* followed by options */ 
} __packed;

inet6_option_space() ルーチンとルーチンのファミリは、このデータを操作するために使用されます。

このオプションは、スーパユーザの特権を必要とします。

IPV6_DSTOPTS int *
その後の recvmsg(2) 呼び出しでペイロードに伴う付属のデータとして提供されるその後のパケットからの宛先 (終点) のオプションかどうかを取得するか、または設定します。オプションは、返された付属のデータで次の構造体に格納されます:

struct ip6_dest { 
 uint8_t ip6d_nxt; /* 次のヘッダ */ 
 uint8_t ip6d_len; /* 8 オクテットのユニットの長さ */ 
/* followed by options */ 
} __packed;

inet6_option_space() ルーチンとルーチンのファミリは、このデータを操作するために使用されます。

このオプションは、スーパユーザの特権を必要とします。

IPV6_TCLASS int *
このソケットで発信データグラムに使用されるトラフィッククラスフィールドの値を取得するか、または設定します。値は、-1 と 255 の間でなければなりません。-1 の値は、デフォルトに値をリセットします。
IPV6_RECVTCLASS int *
その後の recvmsg(2) 呼び出しでペイロード (パケットの本体) とともに付属のデータとして、トラフィッククラスヘッダフィールドを提供するかどうかの状態を取得するか、または設定します。ヘッダフィールドは、タイプ int の単一の値として格納されます。
IPV6_RTHDR int *
その後の recvmsg(2) 呼び出しでペイロードに伴う付属のデータとして提供されるその後のパケットからの経路制御 (routing) ヘッダかどうかを取得するか、または設定します。ヘッダは、返された付属のデータで次の構造体に格納されます:

struct ip6_rthdr { 
 uint8_t ip6r_nxt; /* 次のヘッダ */ 
 uint8_t ip6r_len; /* 8 オクテットのユニットの長さ */ 
 uint8_t ip6r_type; /* 経路制御タイプ */ 
 uint8_t ip6r_segleft; /* セグメント left */ 
/* 経路制御タイプ特有データが続く */ 
} __packed;

inet6_option_space() ルーチンとルーチンのファミリは、このデータを操作するために使用されます。

このオプションは、スーパユーザの特権を必要とします。

IPV6_PKTOPTIONS struct cmsghdr *
ソケット上で送信されるか、または受信される最後のパケット上ですべてのヘッダオプションと拡張ヘッダを一度に取得するか、または設定します。すべてのオプションは、mbuf のサイズに適合しなければなりません mbuf(9) 参照)。オプションは、対応する値が続く、ひと続きの cmsghdr 構造として指定されます。 cmsg_level は、 IPPROTO_IPV6 に、 cmsg_type は、このリスト中の他の値の 1 つに、および後続するデータは、オプション値に設定されます。オプションを設定するとき、 setsockopt(2) への長さ optlen が 0 であるなら、すべてのヘッダオプションは、それらのデフォルト値にリセットされます。そうでなければ、長さは、消費するひと続きのコントロールメッセージのサイズを指定するべきです。

オプション値を指定するために sendmsg(2) を使用する代わりに、必要なヘッダオプションに対応するこれらの呼び出しに使用される付属のデータは、 setsockopt(2) への引数として提供されるコントロールメッセージのシリーズにおけるコントロールメッセージとして直接指定されます。

IPV6_CHECKSUM int *
16 ビットのチェックサムがどこに位置付けられているかのパケット中のバイトオフセットを取得するか、または設定します。設定されると、このバイトオフセットは、着信パケットは、どこに格納されたそれらのデータのチェックサムがあるはずか、そして、発信パケットは、どこにカーネルによって計算され格納されたそれらのデータのチェックサムがあるかです。-1 の値は、発信パケットでチェックサムがチェックされない、そして着信パケットでチェックサムが計算されず格納されないことを指定します。 ICMPv6 ソケットのためのチェックサムのオフセットは、移動することもできず、オフにすることもできません。
IPV6_V6ONLY int *
IPv6 接続のみこのソケットに作ることができるかどうかを取得するか、または設定します。ワイルドカードソケットに関しては、これは、IPv6 だけに制限して接続できます。
IPV6_FAITH int *
faith(4) 接続をこのソケットに作ることができるかどうかの状態を取得するか、または設定します。
IPV6_USE_MIN_MTU int *
最小の IPv6 最大トランスミッションユニット (MTU) サイズがその後の発信データグラムのためにフラグメント化が起きないように避けるために使用されるかどうかを取得するか、または設定します。
IPV6_AUTH_LEVEL int *
ipsec(4) 認証レベルを取得するか、または設定します。
IPV6_ESP_TRANS_LEVEL int *
ESP 転送レベルを取得するか、または設定します。
IPV6_ESP_NETWORK_LEVEL int *
ESP カプセル化レベルを取得するか、または設定します。
IPV6_IPCOMP_LEVEL int *
ipcomp(4) レベルを取得するか、または設定します。

IPV6_PKTINFO, IPV6_HOPLIMIT, IPV6_HOPOPTS, IPV6_DSTOPTSIPV6_RTHDR オプションは、 cmsg_levelIPPROTO_IPV6 に設定し、 cmsg_type を個別のオプション名の値 (例えば、 IPV6_HOPTLIMIT) に設定してその後の recvmsg(2) 呼び出しで、ペイロードの内容に伴う付属のデータを返します。また、これらのオプションは、呼び出しによって送信されるパケットでオプションを設定するために sendmsg(2) 中の付属の cmsg_type 値として直接使用されます。 cmsg_level 値は、 IPPROTO_IPV6 でなければなりません。これらのオプションにおいて、付属のデータオブジェクト値の形式は、 recvmsg(2) で受信されたときごとに説明される返り値と同様です。

特定のパケット上でオプションを指定するために sendmsg(2) を使用することは、UDP と生のソケットだけで動作することに注意してください。 TCP ソケット上でパケットのためのヘッダオプションを操作するために、ソケットオプションだけを使用することができます。

ある場合には、IPv6 ヘッダフィールドを操作するために定義された複数の API があります。良い例は、 IPV6_PKTINFO オプションを通して、そして sendto(2) システムコールに渡されたソケットアドレスの sin6_scope_id フィールドを通して IPV6_MULTICAST_IF ソケットオプションによって設定できる、マルチキャストデータグラムのための発信インタフェースです。

これらの競合を解決するのは、実装に依存しています。この実装は、次の方法で値を決定します: 付属のデータ (すなわち、 sendmsg(2)) を使用することによって指定されたオプションは、最初に検討されます。“sticky”オプションを設定するために IPV6_PKTOPTIONS を使用することによって指定されたオプションは、2 番目に検討されます。個別、基本的で直接ソケットオプション (例えば、 IPV6_UNICAST_HOPS) を使用することによって指定されたオプションは、3 番目に検討されます。そして、 sendto(2) に供給されたソケットアドレスで指定されたオプションは、最後に選択されます。

マルチキャスティング

IPv6 マルチキャスティングは、タイプ SOCK_DGRAMSOCK_RAWAF_INET6 ソケット上だけ、およびインタフェースドライバがマルチキャスティングをサポートするネットワーク上だけでサポートされます。マルチキャストグループのメンバシップを操作するソケットオプション (上記参照) と他のマルチキャストオプションは、 IPV6_MULTICAST_IF, IPV6_MULTICAST_HOPS, IPV6_MULTICAST_LOOP, IPV6_LEAVE_GROUPIPV6_JOIN_GROUP を含みます。

生のソケット

生の IPv6 ソケットは、コネクションレスであり、通常、 sendto(2)recvfrom(2) 呼び出しで使用され、 connect(2) 呼び出しは、 send(2) が代わりに使用できるように将来の発信パケットのための宛先 (終点) アドレスを固定するために使用され、 bind(2) 呼び出しは、カーネルに発信元 (始点) アドレスを選択させることの代わりに将来の発信パケットのための発信元 (始点) アドレスを固定するために使用されます。

connect(2) またh bind(2) を使用することによって、生のソケット入力は、 connect(2) が使用されたなら、それらの発信元 (始点) アドレスがソケットの宛先 (終点) アドレスに一致している唯一のパケットに制約され、 bind(2) が使用されたなら、それらの宛先 (終点) アドレスがソケットの発信元 (始点) アドレスに一致しているパケットに制約されます。

socket(2) への proto 引数が 0 であるなら、デフォルトプロトコル ( IPPROTO_RAW) が発信パケットのために使用されます。着信パケットに関して、カーネルによって認識されたプロトコルは、いくつかの ICMPv6 メッセージを除いて、アプリケーションソケット (例えば、 tcp(4)udp(4)) に渡され ません。 生のソケットに渡されなかった ICMPv6 メッセージは、エコー、タイムスタンプ、およびアドレスマスク要求を含んでいます。 proto が 0 でなければ、このプロトコルのパケットだけがソケットに渡されます。

また、それらが再構築されるまで、IPv6 フラグメントは、アプリケーションソケットに渡されません。すべてのパケットの受信が要求されているなら、 ( bpf(4) のような) リンクレベルアクセスが代わりに使用されなければなりません。

発信パケットは、自動的に (ソケットが作成された宛先 (終点) アドレスとプロトコル番号に基づいている) それらに IPv6 ヘッダを先頭に追加します。着信パケットは、IPv6 ヘッダまたは拡張ヘッダなしでアプリケーションに受け取られます。

発信パケットは、それらが大き過ぎるなら、カーネルによって自動的にフラグメント化されます。着信パケットは、パケットフラグメントまたはフラグメントヘッダが生のソケット上で決して見られないので、生のソケットに送信する前に再構築されます。

使用例

以下は、次のパケット受信時に中継限界数 (hop limit) を決定します:

struct iovec iov[2]; 
u_char buf[BUFSIZ]; 
struct cmsghdr *cm; 
struct msghdr m; 
int optval; 
bool found; 
u_char data[2048]; 
 
/* ソケット作成. */ 
 
(void)memset(&m, 0, sizeof(m)); 
(void)memset(&iov, 0, sizeof(iov)); 
 
iov[0].iov_base = data;  /* パケットのペイロードのためのバッファ */ 
iov[0].iov_len = sizeof(data); /* 予期されるパケット長 */ 
 
m.msg_name = &from;  /* ピアの sockaddr_in6 */ 
    /* 訳注: ピアは通信相手 */ 
m.msg_namelen = sizeof(from); 
m.msg_iov = iov; 
m.msg_iovlen = 1; 
m.msg_control = (caddr_t)buf; /* コントロールメッセージのバッファ */ 
m.msg_controllen = sizeof(buf); 
 
/* 
 * ペイロードと共に返される受信パケットからの 
 * 中継限界数の値を有効にします。 
 */ 
optval = 1; 
if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval, 
    sizeof(optval)) == -1) 
 err(1, "setsockopt"); 
 
found = false; 
do { 
 if (recvmsg(s, &m, 0) == -1) 
  err(1, "recvmsg"); 
 for (cm = CMSG_FIRSTHDR(&m); cm != NULL; 
      cm = CMSG_NXTHDR(&m, cm)) { 
  if (cm->cmsg_level == IPPROTO_IPV6 && 
      cm->cmsg_type == IPV6_HOPLIMIT && 
      cm->cmsg_len == CMSG_LEN(sizeof(int))) { 
   found = true; 
   (void)printf("hop limit: %d\n", 
       *(int *)CMSG_DATA(cm)); 
   break; 
  } 
 } 
} while (!found);

診断

ソケット操作は、失敗すれば、次のエラーのうちの 1 つを返します:
[ EISCONN]
既に接続があるソケットに接続を確立しようとしたとき、または宛先 (終点) アドレスが指定されたデータグラムを送信しようとし、ソケットが既に接続されているとき。
[ ENOTCONN]
データグラムを送信しようと試みるが、宛先 (終点) アドレスが指定されていない、そしてソケットが接続されていないとき。
[ ENOBUFS]
システムが内部のデータ構造のためのメモリを使い果たすとき。
[ EADDRNOTAVAIL]
ネットワークインタフェースが存在しないネットワークアドレスでソケットを作成する試みをするとき。
[ EACCES]
特権のないプロセスによって生の (raw) IPv6 ソケットを作成する試みをするとき。

ヘッダオプションを設定するか取得するとき、次の IPv6 特有のエラーが発生するかもしれません:

[ EINVAL]
未知のソケットオプション名が与えられました。
[ EINVAL]
付属のデータオブジェクトが不適切に形成されました。

関連項目

getsockopt(2), recv(2), send(2), setsockopt(2), socket(2), if_nametoindex(3), bpf(4), icmp6(4), ip(4), inet6(4), netintro(4), tcp(4), udp(4) W. Stevens and M. Thomas, Advanced Sockets API for IPv6, RFC 2292, February 1998. S. Deering and R. Hinden, Internet Protocol, Version 6 (IPv6) Specification, RFC 2460, December 1998. R. Gilligan, S. Thomson, J. Bound, and W. Stevens, Basic Socket Interface Extensions for IPv6, RFC 2553, March 1999. W. Stevens, B. Fenner, and A. Rudoff, UNIX Network Programming, third edition.

規格

ソケットオプションの大部分は、RFC 2292 または RFC 2553 で定義されています。 IPV6_V6ONLY ソケットオプションは、RFC 3493 セクション 5.3 で定義されています。 IPV6_PORTRANGE ソケットオプションと競合解決規則は、RFC で定義されていないので、実装に依存していると考えらます。
March 13, 2011 FreeBSD