kazmax - Linux で自宅サーバー

netdevice - 約束事その他の説明 - Linux コマンド集 一覧表

  1. 名前
  2. 書式
  3. 説明
  4. IOCTL
  5. 注意
  6. バグ
  7. 関連項目

名前

netdevice - 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;
    };
};


struct ifconf { int ifc_len; /* size of buffer */ union { char * ifc_buf; /* buffer address */ struct ifreq * ifc_req; /* array of structures */ }; };

通常、ユーザーによる設定対象デバイスの指定は、 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 には以下の値のビットマスクが入る。
.TS tab(:); c s l l. デバイスフラグ IFF_UP:インターフェースは動作中。 IFF_BROADCAST:T{ 有効なブロードキャストアドレスがセットされている。 T} IFF_DEBUG:内部のデバッグフラグ。 IFF_LOOPBACK:インターフェースはループバックである。 IFF_POINTOPOINT:T{ インターフェースは point-to-point リンクである。 T} IFF_RUNNING:リソースが割り当て済み。 IFF_NOARP:arp プロトコルがない。 IFF_PROMISC:インターフェースは promiscuous モードである。 IFF_NOTRAILERS:trailer の利用を避ける。 IFF_ALLMULTI:全てのマルチキャストパケットを受信する。 IFF_MASTER:負荷分散グループのマスターである。 IFF_SLAVE:負荷分散グループのスレーブである。 IFF_MULTICAST:マルチキャストをサポートしている。 IFF_PORTSEL:ifmap によってメディアタイプを選択できる。 IFF_AUTOMEDIA:自動メディア選択が有効になっている。 IFF_DYNAMIC:T{ このインターフェースが閉じると、アドレスは失われる。 T}
acitive フラグワードの設定は特権が必要な操作である。 しかし読み出しはどんなプロセスからも可能である。
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) ファミリーのアドレスのみである。 ユーザーは ifconf 構造体を ioctl の引数として渡す。 これには ifreq 構造体の配列へのポインタである ifc_req と、その長さをバイト単位で指定する ifc_len を含む。 カーネルは ifreqs を現在動作している全ての L3 インターフェースアドレスで埋める。 ifr_name にはインターフェース名 (eth0:1 など) が入り、 ifr_addr にはアドレスが入る。 カーネルは実際の長さを ifc_len に返す。 ifc_len が元のバッファの長さと同じだった場合、 オーバーフローを起こしている可能性があるので、 全てのアドレスを所得するためにより大きなバッファで再試行するべきである。 エラーがなかった場合は ioctl は 0 を返す。 エラーがあった場合は -1 を返す。 オーバーフローはエラーとは見なされない。

ほとんどのプロトコルには、専用のインターフェースオプションを 設定するための独自の ioctl が存在する。 説明は各プロトコルの man ページを見よ。

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

注意

厳密にいうと、 SIOCGIFCONF は IP 固有であり、 ip(7) に属する。

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

ローカル IPV6 IP アドレスは /proc/net か   rtnetlink (7) で見つけることが出来る。

バグ

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

#ifndef ifr_newname
#define ifr_newname     ifr_ifru.ifru_slave
#endif

関連項目