「学習ドリブン - プロセス分析ifconfigコマンドカーネルを呼び出すために、達成するために、カーネルが自動的に設定されたMACアドレス(オリジナル)を起動します」

カーネルのバージョン:Linuxバージョン3.10.14

eth0のの各開発ボードブートカードの物理アドレスとして、1はランダムであります

その後の行は、物理アドレス設定macコマンドを達成するために、インターネット上で見つけることができます:

ifconfigコマンドeth0の下
にifconfig eth0をHWエーテル1234567890ab 
ifconfigコマンドeth0をアップ

そして、カーネルコマンドラインifconfigコマンドは、私が試してみたい、と相互作用しているかを確認するために好奇心がかかり、自動的にカーネルによって直接MACを設定する方法


2.分析入門

コマンドはifconfigコマンドであるため、コードはbusyboxのですが、私たちは、ifconfigコマンドの導入のカーネルのドキュメントディレクトリにある、コードファイルは次の場所にあります。紹介:ドキュメント\ネットワーク\のifenslave.c

2.1を以下に示し、対応するifconfigコマンドeth0をダウンifconfigコマンドはeth0アップ関数です。

 

 

 たとえば、私たちがノックするときにifconfig eth0のダウン時間を、実際にはそれが呼び出すことです。

set_if_down(" eth0を"、master_flags.ifr_flags)。

マップ上のファイルに加えて、以下の機能が使用されます。

set_if_addrは();            // (IP、マスク、ブロードキャスト、宛先を含む)のアドレスを設定し 
set_master_hwaddrを();      // 物理アドレス、MACを設定します

次は追跡するため、例えばは、eth0 /ダウンifconfigコマンドを起動し、ifconfigコマンドeth0をHWエーテルカーネルを呼び出す方法

3. set_if_up()関数を分析

3.1分析set_if_up()

set_if_up()関数が呼び出されます| set_if_flags(IFF_UP "eth0を"、旗)を追加し、インターフェイス(eth0)のifNameをオープンフラグ

 

 

3.2分析set_if_up() - > set_if_flags( "eth0の"、旗| IFF_UP)

次のように関数は次のとおりです。

静的 INT set_if_flags(CHAR *のifName、ショートフラグ)
{ 
         構造体いるifreq IFR;
          INT RES = 0 ; 
         ifr.ifr_flagsは = フラグを、                                             
         strncpyを(ifr.ifr_name、のifName、IFNAMSIZ);     // ifr.ifr_name = "eth0の" 

         RES = IOCTL (skfd、SIOCSIFFLAGS、&IFR);     // のioctl()コマンドによって、カーネル変数SIOCSIFFLAGSに送信され、IFRソケット
         IF(RES < 0 ){ 
                  saved_errno = ; errnoを
                  v_print("インターフェイス'%s'はエラー:SIOCSIFFLAGSに失敗しました:%S \ nを" 
                          のifName、にstrerror(saved_errno)); 
         } { 
                  v_print(" インターフェイス'%S':%04Xに設定されたフラグ\ N。" 、のifName、フラグ); 
         } 戻りRES; 
}
         

カーネルでそれを達成するための場所を確認するために探して3.3マクロSIOCSIFFLAGS

ネット\コアを見つけます\のDev_ioctl.c dev_ioctl()関数

次のように機能コードの重要な部分は次のとおりです。

int型 dev_ioctl(構造体 NET * NET、符号なし整数 CMD、無効 __user * のArg)
{ 
         構造体いるifreq IFR;
          int型RET;
          char型 * コロン;
          // ... ... 

         スイッチ(CMD){
          // ... ... 

         ケース SIOCSIFFLAGS:    // 設定されたフラグ、このようにifconfigアップ/ダウンなどの
         ケース:SIOCSIFMETRIC    
          ケース SIOCSIFMTU:      // 設定MUT長
         ケース SIOCSIFHWADDR:   // 物理アドレス、MACを設定
          // ... ...

         dev_load(NET、ifr.ifr_name);            // ifr.ifr_name(eth0の)名前でカードをロードする 
         rtnl_lock();                            // net_deviceするためには、操作との競合を避けるために、ロックされて 
         RET = dev_ifsioc(NET、&IFR、CMDを);       / / 最後に、関数呼び出し

rtnl_unlockを(); 
         戻りRET;
          // ... 
}

上記からわかるように、物理アドレスも最終的に、彼らは呼ぶ、ここで実行されているとき、私たちは、Macの流れを設定しdev_ifsioc(ネット&IFR、CMD ) 機能を

4.バックは非常に簡単で、そして最終的にはifconfigコマンドは、最大カーネルプロセスを呼び出すはeth0:

set_if_up() - > 

  set_if_flags(" eth0の"、旗| IFF_UP) - > 

   dev_ifsioc(ネット、&IFR、CMD) - > 

      dev_change_flags(DEV、IFR - > ifr_flags) - >  

           __dev_change_flags(DEV、フラグ);

次いで、4.1 __dev_change_flags(DEV、フラグ)関数は、eth0のを切り替える)((達成__dev_closeを呼び出し、逆IFF_UPビットかどうかのフラグの値によって決定される)、または__dev_openれます

下図のように:

net_device_ops構造4.2と__dev_openでのメンバ関数は、()のオープンを達成するためにNICドライバを呼び出します。

 

__dev_open(DEV):
   DEV - > netdev_ops-> ndo_validate_addr(DEV); // テストDEV-> dev_addr(HW ADDR)有効な、通常eth_validate_addr()を呼び出す関数である、あなたがhw_addrに注意を払う必要があるが[0]の最下位ビットがすることはできませんです1 
   DEV-> netdev_ops-> ndo_open(DEV);           // ifconfigコマンドを達成するために()関数を呼び出すオープン

4.3同様__dev_close()メンバ関数はクロージャを達成するため次の呼び出し:

DEV-> netdev_ops-> ndo_stop(DEV);                 //はダウンifconfigコマンドを達成するために、停止()関数を呼び出します

4.4どこに位置net_device_ops構造メンバ関数を見つけるために

構造体net_device DEV変数の型は、上記で述べたように、そして構造体net_deviceは、当社のネットワークカードドライバ機器のいずれかを表し、登録文書はregister_netdevにより、カーネル内()カーネル関数を登録するには、変数のカーネルドライバ/ netディレクトリにあります。

我々は)私たちのボードDM9000カードを持って、たとえば、ファイルは、ドライバ/ネット/イーサネット/のDavicom / dm9000.cに位置しており、その後、あなたは(それがndo_open見つけることができます:

以下のようにifconfigのeth0 HWエーテルNIC設定処理について5です。

 

set_master_hwaddr(master_ifname、&(slave_hwaddr.ifr_hwaddr)) - > 

  のioctl(skfd、SIOCSIFHWADDR、&IFR) - >                   

       dev_ifsioc(NET、&IFR、CMD) - > 

            dev_set_mac_address(DEV、&ifr-> ifr_hwaddrの値) - >              // 設定するMACアドレス

                  DEV - > netdev_ops-> ndo_set_mac_address(DEV、&ifr-> ifr_hwaddrの値);  
                // 最後のコールnet_deviceオプスメンバ関数セットを達成するために、

6.カーネルブート自動的に設定された固定MACアドレスを実装

分析プロセスの後、我々はそれを実装する必要があります。

一例として、私たちのボードに6.1 DM9000カード

私たちは、ネット/イーサネット/のDavicom / /ドライバーにregister_netdev()の場所を見つける dm9000.c dm9000_probeに機能:

 

その後、6.2 register_netdev()関数は、以下のコードを追加します。

ストラクト        のsockaddrのHWaddrを;                    // MACアドレス構造ストアに

rtnl_lockを(); 
RET = dev_close(jz_ndev);                           // ケースで、カードを閉鎖する最初必要性
; rtnl_unlock()

hwaddr.sa_family = ndev-> 型; 

のHWaddr .sa_data [ 0 ] = 0x12を ;                       // ノート、データが[0]の最下位ビットが1ではない、それは最初の奇数ない 
hwaddr.sa_data [ 1 ] = 0x34の; 
hwaddr.sa_data [ 2 ] = 0x56 ; 
[hwaddr.sa_data 3 ] = 0x78と; 
hwaddr.sa_dataの[ 4 ] =0x90を; 
hwaddr.sa_data [ 5 ] = 0xAB ;               

rtnl_lock(); 
RET = dev_set_mac_address(jz_ndev、&のHWaddr);   // 我々の分析に関数を呼び出すは、MACアドレスを設定すること 
)(rtnl_unlockします。

6.3コンパイル - テスト

 入力開始後にifconfigコマンドを、あなたはカーネルは私が設定役立っている見ることができます。

 

おすすめ

転載: www.cnblogs.com/zhuangquan/p/11707262.html