9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

CでEtherフレームを理解する

Last updated at Posted at 2015-01-06

#概要
EtherフレームはOSI参照モデルのレイヤー2に位置します。
直接通信する機器間でデータをやり取りする為の情報が入ったフレームです。
この記事ではC言語によるEtherフレームの解析を行い、Etherフレームについて理解を深めてみます。

#環境構築
CentOSを想定しています。
フレームの取得にはlibpcapというCライブラリを利用します。

yum -y update
yum install -y gcc vim wget tar flex byacc
wget http://www.tcpdump.org/release/libpcap-1.6.2.tar.gz
tar zxvf libpcap-1.6.2.tar.gz
cd libpcap-1.6.2
./configure
make -j 8
make install

#Etherフレームについて
##フレームフォーマット
Etherフレームの内容(IEEE802.3形式)は以下となっています。

概要 サイズ 説明
プリアンブル 7byte タイミングを取るための固定ビット列
SFD 1byte タイミング用。
次のビットからデータが開始されるよ的な。
宛先MAC 6byte 通信先の機器を識別する為の番号
送信元MAC 6byte 通信元の機器を識別する為の番号
Etherタイプ 2byte 上位のプロトコルを表す値。
但し1500以下だったらデータサイズを表す
データ 可変 カプセル化した中身のデータ
FCS 2byte 受け取り側でエラーが発生してないかをチェックする用

###Etherタイプ(一部)
defineはnet/ethernet.hに定義されています。
以下はその値と説明についてです。

define 説明
0x0000-0x05DC - フレームの長さ
0x0800 ETHERTYPE_IP IPパケット
0x0806 ETHERTYPE_ARP ARPパケット
0x8100 ETHERTYPE_VLAN dot1Q VLANフレーム
0x86DD ETHERTYPE_IPV6 IPv6パケット

###Etherフレーム構造体
CでEtherフレームを扱う場合、net/ethernet.hに構造体が定義されています。

net/ethernet.h
struct ether_header
{
  u_int8_t  ether_dhost[ETH_ALEN];      /* destination eth addr */
  u_int8_t  ether_shost[ETH_ALEN];      /* source ether addr    */
  u_int16_t ether_type;                 /* packet type ID field */
} __attribute__ ((__packed__));

#EtherフレームのDump
フレームの受信処理はコチラを参照してください。
以下ではフレームを受信した後、コールバック関数内でEtherヘッダ内容をDump表示しています。

ether_hdr.c
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <string.h>
char * convmac_tostr(u_char *,char *,size_t);

void start_pktfunc( u_char *user,                 // pcap_loop関数の第4引数
                    const struct pcap_pkthdr *h , // 受信したPacketの補足情報
                    const u_char *p               // 受信したpacketへのポインタ
                  ){
  char dmac[18] = {0};
  char smac[18] = {0};
  struct ether_header *eth_hdr = (struct ether_header *)p;
  
  printf("ether header---------\n");
  printf("dest mac %s\n",convmac_tostr(eth_hdr->ether_dhost,dmac,sizeof(dmac)));
  printf("src mac %s\n",convmac_tostr(eth_hdr->ether_shost,smac,sizeof(smac)));
  printf("ether type %x\n\n",ntohs(eth_hdr->ether_type));
}
char * convmac_tostr(u_char *hwaddr,char *mac,size_t size){
  snprintf(mac,size,"%02x:%02x:%02x:%02x:%02x:%02x",
                     hwaddr[0],hwaddr[1],hwaddr[2],
                     hwaddr[3],hwaddr[4],hwaddr[5]);
  return mac;
}
9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?