スポンサーリンク

IP(4) FreeBSD カーネルインタフェースマニュアル IP(4)

名称

ip − インターネットプロトコル

書式

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

int

socket(AF_INET, SOCK_RAW, proto);

説明

IP は、インターネットプロトコルファミリが用いるトランスポート層のプロトコ ルです。 IP に基づいた、より高位のプロトコル (例えば、 TCP や UDP ) を用 いているときには、 IP レベルでオプションを設定できます。また、新しいプロ トコルや特別な用途のアプリケーションを開発しているときには、 ‘‘raw ソケッ ト’’ を通してアクセスすることもできます。

IP レベルの setsockopt(2) ならびに getsockopt(2) オプションがいくつかあり ます。 IP_OPTIONS は、送信される各パケットの IP ヘッダ中に埋め込まれる IP オプションを提供したり、受信されるパケットのヘッダ部のオプションを検査し たりするために使われます。 IP オプションは、インターネットファミリの全て のソケットタイプで使うことができます。送信される IP オプションのフォー マットは、 IP プロトコルの仕様 (RFC-791) で決められています。ただし、1 つ 例外があります。指定経路制御オプション用のアドレスリストには、ゲートウェ イリストの先頭に、最初にパケットが通過するゲートウェイが含まれていること が必要です。最初にパケットが通過するゲートウェイのアドレスはオプションリ ストから取り出され、使用される前に適切な大きさに直されます。以前に指定さ れたオプションを無効にするには、長さ 0 のバッファを使用してください。

setsockopt(s, IPPROTO_IP, IP_OPTIONS, NULL, 0);

IP_TOS および IP_TTL は、 SOCK_STREAM および SOCK_DGRAM で用いられる IP ヘッダ内の、サービスタイプ (type-of-service) フィールドと生存時間 (time-to-live) フィールドを設定するために使用されます。例えば、以下のよう にします。

int tos = IPTOS_LOWDELAY;       /* <netinet/in.h> 参照 */
setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));
int ttl = 60;                   /* 最大値は 255 */
setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));

もし、 IP_RECVDSTADDR オプションが SOCK_DGRAM ソケットで有効になっていた 場合、 recvmsg(2) システムコールは、 UDP ダイアグラム用の送り先の IP アド レスを返します。 msghdr 構造体の msg_control フィールドは IP アドレスの後 に続いた cmsghdr 構造体の入ったバッファへのポインタになっています。 cmsghdr フィールドは以下のような値を持ちます。

cmsg_len = sizeof(struct in_addr)
cmsg_level = IPPROTO_IP
cmsg_type = IP_RECVDSTADDR

IP_PORTRANGE は、ポート番号の範囲を設定するために使されます。この範囲の ローカルポート番号のうちのひとつが、ポート番号を指定しなかった (0 が指定 された) ソケット用に選択されます。これは、以下のような値を取り得ます。

       IP_PORTRANGE_DEFAULT

デフォルトの範囲のポート番号値を使います。通常は IPPORT_RESERVED から IPPORT_USERRESERVED です。この 値は、sysctl の設定、 net.inet.ip.portrange.first および net.inet.ip.portrange.last を通して調整でき ます。

IP_PORTRANGE_HIGH
は、大きな値の範囲のポート番号を使います。通常は IPPORT_HIFIRSTAUTO および IPPORT_HILASTAUTO です。 この値は、sysctlの設定、 net.inet.ip.portrange.hifirst および net.inet.ip.portrange.hilast を通して調整できます。

IP_PORTRANGE_LOW
は、小さな値の範囲のポート番号を使います。通常は、 UNIX システム上で特権を持ったプロセスに使用が限定さ れています。この値の範囲は、通常 IPPORT_RESERVED か ら 1 までで、降順に並んでいます。この値の範囲は sysctl では設定できません。

マルチキャストオプション

IP のマルチキャストは SOCK_DGRAM および SOCK_RAW 型の AF_INET ソケット で、インタフェースドライバがマルチキャストに対応しているネットワークのみ で行えます。

IP_MULTICAST_TTL オプションは、送信されるマルチキャストデータグラムの生存 時間 (TTL) 値を変更します。この値を変更することでマルチキャストの範囲を制 御できます。

u_char ttl; /* 0 から 255 の範囲。 デフォルト値は 1 */
setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

TTL 値が 1 のデータグラムは、ローカルネットワークを超えて転送されることは ありません。 TTL 値が 0 のデータグラムはどのネットワークにも送信されませ んが、データグラムを送ったホストが送り先のグループに属しており、送信を行 うソケットがマルチキャストループパックを無効にしていなければ (下記参照)、 ローカルネットワークには送信されるかもしれません。 TTL 値が 1 より大きい データグラムは、ローカルネットワークにマルチキャストルータが接続されてい れば、他のネットワークに転送されます。

複数のインタフェースを持ったホストには、各マルチキャスト送信は、最初の ネットワークインタフェースから行われます。 IP_MULTICAST_IF オプションを使 うと、指定されたソケットからの次の送信のためにデフォルト値を書きかえるこ とができます。

struct in_addr addr;
setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr));

ここで、"addr" は、ローカルホストの使用したいインタフェースの IP アドレス です。または、 INADDR_ANY を指定して、デフォルトのインタフェースを示すよ うにもできます。インタフェースのローカル IP アドレスおよびマルチキャスト 能力の有無は、 SIOCGIFCONF および SIOCGIFFLAGS ioctl システムコールで得る ことができます。普通のアプリケーションではこのオプションを使う必要はない はずです。

もし、マルチキャストデータグラムが送り元のホスト自身が属しているグループ (送り先のインタフェース上にある) に送信されるのであれば、デフォルトでは ローカルへの配送用に、そのダイアグラムのコピーが IP 層によってループバッ クされます。 IP_MULTICAST_LOOP オプションは、送信ホストに今後のデータグラ ムをループバックするのかどうかを制御する権限を明示的に与えます。

u_char loop;    /* 0 = 無効, 1 = 有効 (デフォルト) */
setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));

このオプションは、自身が送信したパケットを受け取る際のオーバヘッドを軽減 することで、1 つのホストに 1 つしか実体を持たないアプリケーション (例え ば、ルータデーモン) のパフォーマンスを向上させます。このオプションは、1 つのホスト上で複数の実体を持ち得るアプリケーション (例えば、会議プログラ ム) や、送信元のホストが送信先のグループに属さないアプリケーション (例え ば、時刻問い合わせプログラム) では使われません。

TTL の初期値を 1 より大きくして送信されたマルチキャストデータグラムは、送 信元のインタフェースとは別のインタフェース上のホストから送信元のホストに 配送されるかもしれません。ただし、送信元ではない方のインタフェース上で、 このホストが宛先のグループに属している場合です。ループバックコントロール オプションは、このような配送に対しては何の効力も持ちません。

あるマルチキャストグループから送信されたデータグラムを受け取るには、ホス トがそのマルチキャストグループに属していることが必要です。あるマルチキャ ストグループに加わるには、 IP_ADD_MEMBERSHIP オプションを使用します。

struct ip_mreq mreq;
setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

ここでは、 mreq は以下のような構造体です。

struct ip_mreq {
struct in_addr imr_multiaddr; /* グループの IP マルチキャストアドレス */
struct in_addr imr_interface; /* インタフェースのローカル IP アドレス */
}

デフォルトのマルチキャストインタフェースを選択するには、 imr_interface は INADDR_ANY にします。また、ホストがマルチホームに設定されていれば、特定の マルチキャスト可能なインタフェースの IP アドレスに指定することが必要で す。メンバシップは、1 つのインタフェースに結びついています。そのため、マ ルチホームホスト上で動作しているプログラムは、 1 つ以上のインタフェース上 で同一のグループに入る必要があるかもしれません。 1 つのソケットに最大 IP_MAX_MEMBERSHIPS (現在では 20) 個のメンバシップを設定できます。

メンバから抜けるには、以下の関数を使います。

struct ip_mreq mreq;
setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq));

ここで、 mreq はメンバに加わるときに使ったのと同じ値が入ります。ソケット を閉じたりプロセスが終了したりした場合はメンバから抜けます。

raw IP ソケット

raw IP ソケットは、コネクションを持たないソケットで、通常は sendto(2)recvfrom(2) コールと一緒に使われます。ただし、 connect(2) コールは、これ から流れてくるパケットの送り先を定めるためにも使われます。 (この場合に は、 read(2) もしくは recv(2) 、および write(2) もしくは send(2) システム コールが使われるでしょう。)

proto が 0 の場合には、パケットの送信にはデフォルトのプロトコルである IPPROTO_RAW が使われ、このプロトコルに向かって送られてきたパケットだけが 受信されます。 proto が 0 でない場合、そのプロトコルの番号が送信パケット 上で使われ、また、入力パケットをフィルタリングするために使われます。

送信パケットには、自動的に IP ヘッダ (これは、送り先アドレスおよびソケッ トが作成されたときのプロトコル番号にもどづいています) が与えられます。た だし、 IP_HDRINCL オプションが設定されているときは IP ヘッダは与えられま せん。受信パケットは、完全な形の IP ヘッダおよびオプションと一緒に受け取 られます。

IP_HDRINCL は、データと一緒に完全な IP ヘッダが含まれていることを示し、 SOCK_RAW 型でしか使われません。

#include <netinet/in_systm.h>
#include <netinet/ip.h>

int hincl = 1;                  /* 1: オン , 0: オフ */
setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl));

以前の BSD リリースとは違って、このプログラムでは、すべての IP ヘッダの フィールドを設定することが必要です。これには次のフィールドも含みます。

ip->ip_v = IPVERSION;
ip->ip_hl = hlen >> 2;
ip->ip_id = 0;  /* 0 ということは、カーネルが適切な値を
設定してくれるということです。 */
ip->ip_off = offset;

ヘッダの送り元のアドレスが INADDR_ANY に設定されていたら、カーネルが適切 なアドレスを選択します。

診断

ソケット操作が次のようなエラーのいずれかを返して失敗することがあります。

       [EISCONN]

すでに接続が確立されたソケットに接続を試みようとしたとき や、送り先アドレスを指定してデータグラムを送信しようとし たときに送り先のソケットがすでに接続されているときに生じ ます。

[ENOTCONN]
データグラムを送信しようとしたときに、送り先アドレスが指 定されておらず、ソケットがまだ接続されていないときに生じ ます。

[ENOBUFS]
内部のデータ構造でシステムがメモリを使い果たしたときに生 じます。

[EADDRNOTAVAIL]
ネットワークアドレスを用いてソケットを作成しようとした が、そのためのネットワークインタフェースが存在しないとき に生じます。

[EACESS]
特権のないプロセスによって raw IP ソケットを作成しようと したときに生じます。

次のような、 IP に特有のエラーが IP のオプションを設定したり取得したりす る際に生じることがあります。

[EINVAL]
ソケットのオプション名に不明なものが与えられました。

[EINVAL]
IP のオプションフィールドが適切な形になっていませんでし た。すなわち、オプションフィールドが最小値より短かった り、与えられたオプションバッファよりも長かったりしたとい うことです。

関連項目

getsockopt(2), recv(2), send(2), icmp(4), inet(4), intro(4)

歴史

ip プロトコルは、 4.2BSD から登場しました。

4.2 Berkeley Distribution November 30, 1993 4.2 Berkeley Distribution

スポンサーリンク