netdevice(7) Linux ネットワークデバイスへの低レベルアクセス

書式

#include <sys/ioctl.h>
#include <net/if.h>

説明

この man ページでは、ネットワークデバイスを設定するために 用いるソケットインターフェースについて解説する。

Linux はネットワークデバイスを設定するための標準的な ioctl を いくつか備えている。これらはどんなソケットのファイルディスクリプタにも 用いることができる。ファミリーやタイプは何でもよい。 これらの ioctl のほとんどは ifreq 構造体を渡す。

struct ifreq {
    char ifr_name[IFNAMSIZ]; /* Interface name */
    union {
        struct sockaddr ifr_addr;
        struct sockaddr ifr_dstaddr;
        struct sockaddr ifr_broadaddr;
        struct sockaddr ifr_netmask;
        struct sockaddr ifr_hwaddr;
        short           ifr_flags;
        int             ifr_ifindex;
        int             ifr_metric;
        int             ifr_mtu;
        struct ifmap    ifr_map;
        char            ifr_slave[IFNAMSIZ];
        char            ifr_newname[IFNAMSIZ];
        char           *ifr_data;
    };
};

通常、ユーザーによる設定対象デバイスの指定は、 ifr_name にインターフェースの名前をセットすることによって行う。 他の構造体の全てのメンバは、メモリを共有する。

ioctl

「特権が必要」と記述されている ioctl を実行するには、 実効ユーザー ID が 0 か、 CAP_NET_ADMIN 権限が必要である。これが満たされていない場合は EPERM が返される。
SIOCGIFNAME
ifr_ifindex を受け取り、インターフェースの名前を ifr_name に入れて返す。これは結果を ifr_name として返す唯一の ioctl である。
SIOCGIFINDEX
インターフェースの interface index を取得し、 ifr_ifindex に入れて返す。
SIOCGIFFLAGS, SIOCSIFFLAGS
デバイスの active フラグワードを取得または設定する。 ifr_flags には以下の値のビットマスクが入る。
デバイスフラグ
IFF_UPインターフェースは動作中。
IFF_BROADCAST有効なブロードキャストアドレスがセットされている。
IFF_DEBUG内部のデバッグフラグ。
IFF_LOOPBACKインターフェースはループバックである。
IFF_POINTOPOINTインターフェースは point-to-point リンクである。
IFF_RUNNINGリソースが割り当て済み。
IFF_NOARP arp プロトコルがない。 L2 宛先アドレスが設定されていない。
IFF_PROMISCインターフェースは promiscuous モードである。
IFF_NOTRAILERStrailer の利用を避ける。
IFF_ALLMULTI全てのマルチキャストパケットを受信する。
IFF_MASTER負荷分散グループのマスターである。
IFF_SLAVE負荷分散グループのスレーブである。
IFF_MULTICASTマルチキャストをサポートしている。
IFF_PORTSELifmap によってメディアタイプを選択できる。
IFF_AUTOMEDIA自動メディア選択が有効になっている。
IFF_DYNAMIC このインターフェースが閉じると、アドレスは失われる。
IFF_LOWER_UPドライバからの L1 アップの通知 (Linux 2.6.17 以降)
IFF_DORMANTドライバからの休止状態の通知 (Linux 2.6.17 以降)
IFF_ECHO送られたパケットをエコーする (Linux 2.6.25 以降)

active フラグワードの設定は特権が必要な操作である。 読み出しはどんなプロセスからも可能である。
SIOCGIFPFLAGS, SIOCSIFPFLAGS
デバイスの拡張 (プライベート) フラグを取得または設定する。 ifr_flags には以下の値のビットマスクが入る。
プライベートフラグ
IFF_802_1Q_VLANインターフェースは 802.1Q VLAN デバイスである。
IFF_EBRIDGEインターフェースは Ethernet ブリッジデバイスである。
IFF_SLAVE_INACTIVEインターフェースは非アクティブな bonding のスレーブである。
IFF_MASTER_8023ADインターフェースは 802.3ad bonding のマスターである。
IFF_MASTER_ALBインターフェースは balanced-alb bonding のマスターである。
IFF_BONDINGインターフェースは bonding のマスターかスレーブである。
IFF_SLAVE_NEEDARPインターフェースは検証に APR が必要である。
IFF_ISATAPインターフェースは RFC4214 ISATAP インターフェースである。

拡張 (プライベート) インターフェースフラグの設定には特権が必要である。

SIOCGIFADDR, SIOCSIFADDR
ifr_addr を用いてデバイスのアドレスの設定/取得を行う。 インターフェースのアドレスの設定は特権が必要な操作である。 互換性確保のため、設定/取得ができるのは AF_INET アドレスだけである。
SIOCGIFDSTADDR, SIOCSIFDSTADDR
point-to-point デバイスの宛先アドレスを ifr_dstaddr を用いて 設定/取得する。互換性確保のため、 設定/取得ができるのは AF_INET アドレスだけである。 宛先アドレスの設定は特権が必要な操作である。
SIOCGIFBRDADDR, SIOCSIFBRDADDR
デバイスのブロードキャストアドレスを ifr_brdaddr を用いて 設定/取得する。互換性確保のため、 設定/取得ができるのは AF_INET アドレスだけである。 ブロードキャストアドレスの設定は特権が必要な操作である。
SIOCGIFNETMASK, SIOCSIFNETMASK
デバイスのネットワークマスクを ifr_netmask を用いて 設定/取得する。互換性確保のため、 設定/取得ができるのは AF_INET アドレスだけである。 ネットワークマスクの設定は特権が必要な操作である。
SIOCGIFMETRIC, SIOCSIFMETRIC
デバイスのメトリックを ifr_metric を用いて取得・設定する。 これはまだ実装されていない。読み出そうとすると ifr_metric に 0 をセットして返り、設定しようとすると EOPNOTSUPP が返る。
SIOCGIFMTU, SIOCSIFMTU
デバイスの MTU (Maximum Transfer Unit) を ifr_mtu を用いて取得・設定する。 MTU の設定は特権が必要な操作である。 MTU の値を小さくしすぎるとカーネルがクラッシュするかもしれない。
SIOCGIFHWADDR, SIOCSIFHWADDR
デバイスのハードウェアアドレスを ifr_hwaddr を用いて取得・設定する。 ハードウェアアドレスは sockaddr 構造体に設定される。 sa_family には ARPHRD_* デバイスタイプが入り、 sa_data にはバイト 0 から始まる L2 ハードウェアアドレスが入る。 ハードウェアアドレスの設定は特権が必要な操作である。
SIOCSIFHWBROADCAST
デバイスのハードウェアブロードキャストアドレスを ifr_hwaddr の値に設定する。この操作には特権が必要である。
SIOCGIFMAP, SIOCSIFMAP
インターフェースのハードウェアのパラメータを ifr_map を用いて取得・設定する。 パラメータの設定は特権が必要な操作である。

struct ifmap {
    unsigned long   mem_start;
    unsigned long   mem_end;
    unsigned short  base_addr;
    unsigned char   irq;
    unsigned char   dma;
    unsigned char   port;
};

ifmap 構造体の解釈はデバイスドライバとアーキテクチャに依存する。

SIOCADDMULTI, SIOCDELMULTI
デバイスのリンク層のマルチキャストフィルターから、 ifr_hwaddr のアドレスを追加・削除する。これらの操作には特権が必要である。 別の方法が packet(7) で解説されている。
SIOCGIFTXQLEN, SIOCSIFTXQLEN
デバイスの送信キューの長さを ifr_qlen に取得・設定する。送信キューの長さの設定には特権が必要である。
SIOCSIFNAME
ifr_name で指定したインターフェースの名前を ifr_newname に変更する。この操作には特権が必要である。インターフェースが up していない 時にのみ使用できる。
SIOCGIFCONF
インターフェースの (トランスポート層の) アドレスのリストを返す。 現在のところ、互換性のため返されるのは AF_INET (IPv4) 系のアドレスだけである。 他の操作と違い、この ioctl では ifconf 構造体を渡す。

struct ifconf {
    int                 ifc_len; /* バッファサイズ */
    union {
        char           *ifc_buf; /* バッファアドレス */
        struct ifreq   *ifc_req; /* 構造体の配列 */
    };
};

ifc_req が NULL の場合、 SIOCGIFCONF はすべての取得できるアドレスを受け取るのに必要なバッファサイズ (バイト数) を ifc_len に格納して返す。 それ以外の場合は、ifc_req には ifreq 構造体の配列へのポインタを渡す。 この構造体の配列には現在アクティブな L3 インターフェースアドレスがすべて格納される。 ifc_len はバイト単位の配列のサイズを渡す。 ifreq 構造体内では、 ifr_name にインターフェース名が、 ifr_addr にそのアドレスが入る。 実際に格納されたバイト数は ifc_len で返される。

ifc_len で指定されたサイズがすべてのアドレスを格納するのに不十分な場合、 カーネルは超過分をスキップし、成功を返す。 この状況になった場合、それを検出する信頼できる方法はない。 したがって、 前もって ifc_req を NULL に設定して SIOCGIFCONF を呼び出して必要なバッファサイズを決定するか、 返された ifc_len と元の値の差分が sizeof(struct ifreq) よりも小さい場合は必ずバッファを大きくして再度呼び出すか、 のいずれかを行うことが推奨される。

ifconfifreq 構造体へのアクセスでエラーが置こった場合には EFAULT が返される。

ほとんどのプロトコルには、専用のインターフェースオプションを 設定するための独自の ioctl が存在する。 説明は各プロトコルの man ページを見よ。 IP アドレスの設定に関しては ip(7) を参照。

さらに、デバイスによってはプライベートな ioctl がある。 これらはここでは説明しない。

注意

厳密にいうと、 SIOCGIFCONF や、 AF_INET ソケットアドレスだけを 引き数に取ったり返したりする他の ioctl は IP 固有であり、 ip(7) に属する。

アドレスがなかったり、 IFF_RUNNING フラグがセットされていないインターフェースの名前は /proc/net/dev で知ることができる。

ローカル IPV6 IP アドレスは /proc/netrtnetlink(7) で知ることができる。

バグ

glibc 2.1 では <net/if.h>ifr_newname マクロがない。 とりあえずの対応策として、以下のコードを追加しておくこと。

#ifndef ifr_newname
#define ifr_newname     ifr_ifru.ifru_slave
#endif

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.65 の一部 である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。