PACKET(7) | Linux Programmer's Manual | PACKET(7) |
名前
packet -デバイスレベルのパケットインターフェース書式
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h> /* the L2 protocols */
packet_socket = socket(AF_PACKET, int socket_type , int protocol );
説明
packet ソケットは、デバイスドライバ (OSI レイヤ 2) レベルで生のパケット (raw packet) を送受信するために用いられる。 packet ソケットを使うと、ユーザー空間で物理層の上にプロトコルモジュールを実装することができる。アドレスのタイプ
sockaddr_ll はデバイスに依存しない物理層のアドレスである。struct sockaddr_ll {
unsigned short sll_family; /* 常に AF_PACKET */
unsigned short sll_protocol; /* 物理層のプロトコル */
int sll_ifindex; /* インターフェース番号 */
unsigned short sll_hatype; /* ARP ハードウェア種別 */
unsigned char sll_pkttype; /* パケット種別 */
unsigned char sll_halen; /* アドレスの長さ */
unsigned char sll_addr[8]; /* 物理層のアドレス */
};
ソケットオプション
packet ソケットは、物理層のマルチキャストや無差別モード (promiscuous mode) を設定して使うことができる。これには SOL_PACKET と以下のオプションのいずれかを指定して setsockopt(2) を呼べばよい。バインドを追加する場合は PACKET_ADD_MEMBERSHIP であり、取り去る場合は PACKET_DROP_MEMBERSHIP である。これらはいずれも packet_mreq 構造体を引き数に取る。struct packet_mreq {
int mr_ifindex; /* インターフェース番号 */
unsigned short mr_type; /* 動作 */
unsigned short mr_alen; /* アドレスの長さ */
unsigned char mr_address[8]; /* 物理層のアドレス */
};
ioctl
SIOCGSTAMP を用いると、最後に受信したパケットのタイムスタンプを得ることができる。引き数は struct timeval である。エラー処理
packet ソケットは、パケットをデバイスドライバに渡すときに起きたエラーしか処理しない。遅延エラー (pending error) に関する概念は持っていない。エラー
- EADDRNOTAVAIL
- 不明なマルチキャストグループアドレスが渡された。
- EFAULT
- ユーザが渡したメモリアドレスが不正。
- EINVAL
- 引き数が不正。
- EMSGSIZE
- パケットがインターフェースの MTU より大きい。
- ENETDOWN
- インターフェースが up でない。
- ENOBUFS
- パケットに割り当てるメモリが足りない。
- ENODEV
- デバイス名が不明。あるいはインターフェースアドレスで指定されたインターフェースインデックスが不明。
- ENOENT
- パケットを一つも受信していない。
- ENOTCONN
- インターフェースアドレスが渡されなかった。
- ENXIO
- インターフェースアドレスに不正なインターフェースインデックスが含まれている。
- EPERM
-
この操作を行うのに必要な権限をユーザが持っていない。
バージョン
AF_PACKET は Linux 2.2 の新機能である。これより古いバージョンの Linux では SOCK_PACKET のみをサポートしていた。インクルードファイル <netpacket/packet.h> が存在するのは glibc 2.1 以降である。それ以前のシステムでは以下のようにする必要がある:
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h> /* The L2 protocols */
注意
移植性の必要なプログラムでは、 pcap(3) 経由で AF_PACKET を用いることをお薦めする。ただし、この方法では AF_PACKET の機能すべてを利用することはできない。移植性
Linux 2.0 では、 packet ソケットを得る方法は socket(AF_INET, SOCK_PACKET, protocol ) を呼ぶやり方しかなかった。この方法はまだサポートされているが、用いないことを強く推奨する。現在の方法との主な違いは、 SOCK_PACKET ではインターフェースの指定に古い struct sockaddr_pkt を用いる点である。これには物理層からの独立性がない。struct sockaddr_pkt {
unsigned short spkt_family;
unsigned char spkt_device[14];
unsigned short spkt_protocol;
};
バグ
glibc 2.1 には SOL_PACKET の定義がない。回避策としては、以下のようにするとよい。
#ifndef SOL_PACKET
#define SOL_PACKET 263
#endif
この問題は新しいバージョンの glibc では修正されている。 libc5 のシステムにはこの問題はない。
IEEE 802.2/803.3 の LLC の扱い方は、バグと考えても良いだろう。
ソケットフィルターについて記載されていない。
MSG_TRUNC recvmsg(2) 拡張は非常にまずい対処であり、制御メッセージで置き換えるべきである。今のところ SOCK_DGRAM 経由でパケットについていた宛先アドレスを得る方法がない。
関連項目
socket(2), pcap(3), capabilities(7), ip(7), raw(7), socket(7)この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.51 の一部である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2012-05-10 | Linux |