Android Packet Filter

Android Packet Filter(APF)を利用して、フレームワークで実行時にハードウェア パケット フィルタリング ロジックを管理できます。これにより、ハードウェアでパケットをドロップすることによってシステムの電力使用量を削減できるだけでなく、Android フレームワークはネットワーク状態に応じて実行時にフィルタリング ルールを変更することが可能となります。

APF の概要

APF は次の 2 つのメイン コンポーネントで構成されています。

  • APF インタープリタ: ネットワーキング ハードウェア(一般に、Wi-Fi チップセット)で実行されます。APF インタープリタは、ハードウェアから受け取ったパケットで APF バイトコードを実行し、そのパケットを受け入れるか、ドロップするか、返信するかを判断します。
  • APF プログラム生成コード: メイン CPU で実行されます。このコードにより、ネットワークとデバイスの状態に応じて APF プログラムが作成、更新されます。

Wi-Fi HAL メソッドにより、Android フレームワークは APF プログラムのバイトコードをインストールし、現在のカウンタを読み取ることができます。Network Stack Mainline モジュールは、APF の実行中いつでも APF プログラムのバイトコードを更新できます。

実装済みの APF フィルタがいくつかあります。たとえば、APF には、許可されていない EtherType をドロップするフィルタ、IPv6 ルーター広告(RA)パケットを除外するフィルタ、マルチキャスト ロックが保持されていない場合にマルチキャストとブロードキャストのトラフィックを除外するフィルタ、他のホストの DHCP パケットをドロップするフィルタ、未承諾の Address Resolution Protocol(ARP)や近隣探索(ND)のパケットをドロップするフィルタなどが含まれています。ファームウェアが APFv6 をサポートしている場合、ApfFilter は、通常なら CPU を起動して応答する必要があるパケット(ARP クエリや NS クエリなど)に自動で返信するためのルールも生成します。フィルタの全リストは ApfFilter で定義されています。

APF プログラム生成コードは Network Stack モジュールの一部であるため、毎月の Mainline アップデートを使用して新しいフィルタを追加したり、フィルタリング ロジックを更新したりできます。

APF リビジョン

以下に、APF の変更履歴について詳細を説明します。

  • APFv6: Android 15 で導入されたこのバージョンでは、パケット フィルタがサポートされ、デバッグ用のカウンタと指標が含まれており、パケット送信がサポートされています。
  • APFv4: Android 10 で導入されたこのバージョンでは、パケット フィルタがサポートされ、デバッグ用のカウンタと指標が含まれています。
  • APFv2: Android 7 で導入されたこのバージョンでは、パケット フィルタがサポートされています。

APF の統合

APF インタープリタとハードウェア間の APF API は、apf_interpreter.hAPFv4APFv6)で定義されています。Wi-Fi ファームウェア コードは、APFv4 では accept_packet() を、APFv6 では apf_run() を呼び出し、パケットをドロップするか(ゼロの戻り値)、アプリ プロセッサに渡すか(ゼロ以外の戻り値)を判断します。パケットを送信する必要がある場合、そのパケットをアプリ プロセッサに渡す必要はないため、apf_run() もゼロを返します。ファームウェアが APFv6 をサポートしている場合は、apf_allocate_buffer() API および apf_transmit_buffer() API を実装する必要があります。APF インタープリタは、パケット送信の処理中にこれら 2 つの API を呼び出します。APF 命令は可変長です。各命令は長さが 1 バイト以上あります。APF 命令コードは、APFv4 では apf.h に定義され、APFv6 では apf_interpreter.c 内に直接インライン化されます。

APF は専用メモリを利用します。このメモリは APF プログラム自体とデータ ストレージの両方に使用され、APF HAL メソッドを使用する場合を除き、チップセットでメモリを消去したりメモリに書き込んだりすることはできません。APF バイトコードは、受け入れたパケットとドロップしたパケットのカウンタを格納するためにデータ ストレージを使用します。データ領域は Android フレームワークから読み取ることができます。APF 命令はメモリ効率に優れていますが、省電力性と機能性を最大限に高めるには、複雑で動的なフィルタリング ルールが必要です。この複雑さには、チップセット内に専用のメモリ領域が必要となります。APFv4 の最小メモリ要件は 1,024 バイトですが、APFv6 では 2,048 バイトが必要です。ただし、最適なパフォーマンスを確保するために、APFv6 には 4,096 バイトを割り当てることを強くおすすめします。APF インタープリタはファームウェアにコンパイルする必要があります。APFv4 と APFv6 の両方のインタープリタはコードサイズに最適化されています。arm32 アーキテクチャでは、コンパイルされた APFv4 インタープリタは約 1.8 KB ですが、より複雑な APFv6 インタープリタは、追加機能(ネイティブのチェックサム サポートやネイティブ DNS 圧縮コードなど)を備えており、約 4 KB のサイズとなっています。

APF フィルタは、ファームウェア内の他のチップセット ベンダー固有のフィルタと一緒に動作できます。チップセット ベンダーは、APF フィルタリング プロセスの前または後に自分のフィルタリング ロジックを実行するかを選択できます。パケットが APF フィルタに到達する前にドロップされる場合、APF フィルタはそのパケットを処理しません。

APF フィルタが正しく機能するためには、APF がオンになっているときに、ファームウェアは APF フィルタにパケットのヘッダーだけでなく、パケット全体へのアクセスを提供する必要があります。

APF プログラムのサンプル

ApfTest および ApfFilterTest には、各 APF フィルタの動作を示すテスト プログラム例が含まれています。実際に生成されたプログラムを調べるには、テストケースを変更し、プログラムを 16 進文字列として出力します。

testdata フォルダには、APF RA フィルタの APFv4 プログラム例が含まれています。samples フォルダには、APFv6 オフロード プログラムを生成する Python ユーティリティが含まれています。詳細については、Python ユーティリティ ファイルのドキュメントをご覧ください。

APF のデバッグ

APF がデバイスで有効かどうかを確認するには、現在のプログラムで、現在のカウンタを表示して、adb shell dumpsys network_stack コマンドを実行します。このコマンドの例を以下に示します。

adb shell dumpsys network_stack
......
IpClient.wlan0 APF dump:
    Capabilities: ApfCapabilities{version: 4, maxSize: 4096, format: 1}
......
    Last program:
      6bfcb03a01b8120c6b9494026506006b907c025e88a27c025988a47c025488b87c024f88cd7c024a88e17c024588e384004408066a0e6bdca4022b000600010800060412147a1e016bd884021f00021a1c6b8c7c021c0000686bd4a402080006ffffffffffff6a266bbca402010004c0a801eb6bf87401f6120c84005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506c2fc393057dd6bf47401cb0a1e52f06bac7c01c600e06bb41a1e7e000001b9ffffffff6bb07e000001aec0a801ff6be868a4019a0006ffffffffffff6bb874019b6bf07401907c001386dd686bd0a4017d0006ffffffffffff6bc874017e0a147a0e3a6b980a267c017000ff6be07401650a366ba87c016200858219886a26a2050fff02000000000000000000000000006ba4740146aa0e84013700e6aa0f8c0130006068a4011b000f33330000000184c9b26aed4c86dd606a12a2f02600b03afffe8000000000000086c9b2fffe6aed4cff02000000000000000000000000000186006a3aa2e9024000123c92e4606a3ea2d70800000000000000006a56a2ce04030440c01a5a92c9601a5e92c4606a62a2bb04000000006a66a2a6102401fa00049c048400000000000000006a76a29d04030440c01a7a9298601a7e9293606c0082a28904000000006c0086a27310fdfd9ed67950000400000000000000006c0096a2690418033c001a9a9264606c009ea24e102401fa00049c048000000000000000006c00aea24404180330001ab2923f606c00b6a22910fdfd9ed67950000000000000000000006c00c6a21f04190300001aca921a606c00cea20410fdfd9ed67950000400000000000000016bc472086be4b03a01b87206b03a01b87201
    APF packet counters:
      TOTAL_PACKETS: 469
      PASSED_DHCP: 4
      PASSED_IPV4: 65
      PASSED_IPV6_NON_ICMP: 64
      PASSED_IPV4_UNICAST: 64
      PASSED_IPV6_ICMP: 223
      PASSED_IPV6_UNICAST_NON_ICMP: 6
      PASSED_ARP_UNICAST_REPLY: 4
      PASSED_NON_IP_UNICAST: 1
      DROPPED_RA: 4
      DROPPED_IPV4_BROADCAST_ADDR: 7
      DROPPED_IPV4_BROADCAST_NET: 27

このコマンド例 adb shell dumpsys network_stack の出力には以下が含まれます。

  • ApfCapabilities{version: 4, maxSize: 4096, format: 1}: Wi-Fi チップが APF(バージョン 4)をサポートしていることを意味します。
  • Last program: このセクションは、最新のインストールされている 16 進数文字列形式の APF プログラム バイナリです。
  • APF packet counters: このセクションには、APF で渡された、またはドロップされたパケットの数とその理由が表示されます。

コードを人が読めるアセンブリ言語にデコードして逆アセンブルするには、apf_disassembler ツールを使用します。実行可能なバイナリをコンパイルするには、m apf_disassembler コマンドを実行します。apf_disassembler ツールを使用する方法の例を以下に示します。

echo "6bfcb03a01b8120c6b949401e906006b907c01e288a27c01dd88a47c01d888b87c01d388cd7c01ce88e17c01c988e384004008066a0e6bdca401af000600010800060412147a1e016bd88401a300021a1c6b8c7c01a00000686bd4a4018c0006ffffffffffff1a266bc07c018900006bf874017e120c84005408000a17821f1112149c00181fffab0d2a108211446a3239a205065a56483ac3146bf47401530a1e52f06bac7c014e00e06bb41a1e7e00000141ffffffff6be868a4012d0006ffffffffffff6bb874012e6bf07401237c001386dd686bd0a401100006ffffffffffff6bc87401110a147a0d3a6b980a267c010300ff6be072f90a366ba87af8858218886a26a2040fff02000000000000000000000000006ba472ddaa0e82d0aeaa0f8c00c9025868a2b60f5a56483ac3140c8126f3895186dd606a12a28b2600783afffe8000000000000002005efffe00026fff02000000000000000000000000000186006a3aa284024000123c94007d02586a3ea2700800000000000000006a56a26704190500001a5a94006002586a5ea23b2020014860486000000000000000006464200148604860000000000000000000646a7ea23204030440c01a8294002b02581a8694002402586c008aa21a04000000006c008ea204102a0079e10abcf60500000000000000006bc472086be4b03a01b87206b03a01b87201" | out/host/linux-x86/bin/apf_disassembler
       0: li    r1, -4
       2: lddw  r0, [r1+0]
       3: add   r0, 1
       5: stdw  r0, [r1+0]
       6: ldh   r0, [12]
       8: li    r1, -108
      10: jlt   r0, 0x600, 504
      15: li    r1, -112
      17: jeq   r0, 0x88a2, 504
      22: jeq   r0, 0x88a4, 504
      27: jeq   r0, 0x88b8, 504
      32: jeq   r0, 0x88cd, 504
      37: jeq   r0, 0x88e1, 504
      42: jeq   r0, 0x88e3, 504
      47: jne   r0, 0x806, 116
......

APF の結果をオフラインで確認するには、apf_run ツールを使用します。実行可能なバイナリをコンパイルするには、m apf_run コマンドを実行します。apf_run ツールは APFv4 インタープリタと APFv6 インタープリタの両方をサポートしています。

以下は、apf_run コマンドのマニュアルです。デフォルトでは、apf_run コマンドは APFv4 インタープリタで実行されます。apf_run--v6 引数を渡すと、APFv6 インタープリタに対して実行されます。その他のすべての引数は、APFv4 と APFv6 の両方で使用できます。

apf_run --help
Usage: apf_run --program <program> --pcap <file>|--packet <packet> [--data <content>] [--age <number>] [--trace]
  --program    APF program, in hex.
  --pcap       Pcap file to run through program.
  --packet     Packet to run through program.
  --data       Data memory contents, in hex.
  --age        Age of program in seconds (default: 0).
  --trace      Enable APF interpreter debug tracing
  --v6         Use APF v6
  -c, --cnt    Print the APF counters
  -h, --help   Show this message.

1 つのパケットを APF に渡し、そのパケットをドロップできるか、渡すことができるかを確認する例を以下に示します。

元パケットを 16 進数バイナリ文字列形式で指定するには、--packet オプションを使用します。APF カウンタを格納するために使用するデータ領域を 16 進数バイナリ文字列で指定するには、--data option を使用します。各カウンタの長さは 4 バイトであるため、データ領域は、バッファ オーバーフローが発生しないよう十分な長さである必要があります。

out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b9494010c06006b907c010588a27c010088a47c00fb88b87c00f688cd7c00f188e17c00ec88e384003908066a0e6bdca2d40600010800060412147a18016bd882ca021a1c6b8c7ac900686bd4a2b706ffffffffffff6a266bbca2b204c0a814656bf872a8120c84005808000a17821e1112149c00171fffab0d2a108210446a3239a204064651dbcc88ff6bf4727e0a1e52f06bac7a7be06bb41a1e7e0000006effffffff6bb07e00000063c0a814ff6be868a25106ffffffffffff6bb872536bf072497c001086dd686bd0a23806ffffffffffff6bc8723a0a147a0b3a6b980a267a2eff6be072240a366ba87a23858218886a26a2040fff02000000000000000000000000006ba472086be4b03a01b87206b03a01b87201 --packet 5ebcd79a8f0dc244efaab81408060001080006040002c244efaab814c0a8ca1e5ebcd79a8f0d --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Packet passed
Data: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001

APF の結果を、tcpdump で取得した pcap ファイルに照らして確認するには、以下のように apf_run コマンドを使用します。

out/host/linux-x86/bin/apf_run --program 6bfcb03a01b8120c6b989401df06006b947c01d888a27c01d388a47c01ce88b87c01c988cd7c01c488e17c01bf88e384004408066a0e6bdca401a5000600010800060412147a1e016bd884019900021a1c6b907c01960000686bd4a401820006ffffffffffff6a266bc0a4017b0004c0a82b056bf874017084005f08000a17821f1112149c00181fffab0d2a108211446a3239a20506fabe589435936bf47401470a1e52f06bb07c014200e06bb81a1e7e00000135ffffffff6bb47e0000012ac0a82bff6be868a401160006ffffffffffff6bbc7401176bf074010c7c001086dd686bd0a2fb06ffffffffffff6bcc72fd0a147a0b3a6b9c0a267af1ff6be072e70a366bac7ae6858218886a26a2040fff02000000000000000000000000006ba872cbaa0e82be8eaa0f8c00b7025868a2a40ffabe5894359352a9874d08aa86dd606a12a2792600583afffe80000000000000f7d4e8ccd81ddb43fe80000000000000f8be58fffe94359386006a3aa272024108123c94006b02586a3ea25e0800000000000000006a56a25504030440c01a5a94004e02581a5e94004702586a62a23e04000000006a66a229102409891f9a26ae6d00000000000000006a76a22004190300001a7a94001902586a7ea204102409891f9a26ae6dba98e781ca9ef9ba6bc872086be4b03a01b87206b03a01b87201 --pcap apf.pcap --data 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
37 packets dropped
1733 packets passed
Data: 00000000000000000000000000000000000000000200000005000000000000000000000002000000000000001b000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000689000000000000003c00000000000000000000000000000000000006ea

APFv6 の送信機能をテストするには、apf_run コマンドを次のように使用します。

$ apf_run --program 75001001020304050608060001080006040002AA300E3CAA0FBA06AA09BA07AA08BA086A01BA09120C84006F08066A0EA30206000108000604032B12147A27017A020203301A1C820200032D68A30206FFFFFFFFFFFF020E1A267E000000020A000001032C020B1A267E000000020A000001032CAB24003CCA0606CB0306CB090ACB0306C60A000001CA0606CA1C04AA
0A3A12AA1AAA25FFFF032F020D120C84001708000A1782100612149C00091FFFAB0D2A10820207032A02117C000E86DD68A30206FFFFFFFFFFFF021603190A1482020002187A023A02120A36820285031F8216886A26A2020FFF020000000000000000000000000003200214 --packet FFFFFFFFFFFF112233445566080600010800060400011122334455660A0000020000000000000A0000
01 --data 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 --age 0 --v6 --trace
      R0       R1       PC  Instruction
-------------------------------------------------
       0        0        0: data        16, 01020304050608060001080006040002
       0        0       19: debugbuf    size=3644
       0        0       23: ldm         r0, m[15]
       0        0       25: stdw        counter=6, r0
       0        0       27: ldm         r0, m[9]
       0        0       29: stdw        counter=7, r0
       0        0       31: ldm         r0, m[8]
 134d811        0       33: stdw        counter=8, r0
 134d811        0       35: li          r0, 1
       1        0       37: stdw        counter=9, r0
       1        0       39: ldh         r0, [12]
     806        0       41: jne         r0, 0x806, 157
     806        0       46: li          r0, 14
       e        0       48: jbseq       r0, 0x6, 59, 000108000604
       e        0       59: ldh         r0, [20]
       1        0       61: jeq         r0, 0x1, 103
       1        0      103: ldw         r0, [38]
 a000001        0      105: jeq         r0, 0xa000001, 116
 a000001        0      116: allocate    60
 a000001        0      120: pktcopy     src=6, len=6
 a000001        0      123: datacopy    src=3, len=6
 a000001        0      126: datacopy    src=9, len=10
 a000001        0      129: datacopy    src=3, len=6
 a000001        0      132: write       0x0a000001
 a000001        0      137: pktcopy     src=6, len=6
 a000001        0      140: pktcopy     src=28, len=4
 a000001        0      143: ldm         r0, m[10]
      2a        0      145: add         r0, 18
      3c        0      147: stm         r0, m[10]
      3c        0      149: transmit    ip_ofs=255
      3c        0      153: drop        counter=47
Packet dropped
Data: 00000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000100000011d8340100000000000000000000000000000000000000000100000078563412
transmitted packet: 112233445566010203040506080600010800060400020102030405060a0000011122334455660a000002000000000000000000000000000000000000

--trace パラメータを使用すると、apf_run ツールはインタープリタの実行における各ステップの詳細な出力を提供するため、デバッグに役立ちます。この例では、ARP クエリパケットを APF プログラムに入力します。出力には、ARP クエリはドロップされたが、返信パケットが生成されたことが示されます。この生成されたパケットの詳細は transmitted packet セクションに表示されています。

統合に関する一般的な問題

このセクションでは、APF 統合中に発生するいくつかの一般的な問題について説明します。

  • 予期しないデータ領域のクリア: APF メモリは完全に APF 専用である必要があります。APF メモリ領域を変更できるのは、インタープリタ コードまたはフレームワーク コード(HAL API 経由)のみです。
  • X バイト(X <= maxLen)の APF プログラムのインストールに関する問題: ファームウェアは、失敗やクラッシュ、切り捨てを発生させることなく、maxLen までの任意の長さのプログラムを読み書きできる必要があります。書き込みにより、X から maxLen の間のバイトが変更されてはなりません。
  • ドライバコードへの APF 実装: APF はドライバコードではなく、ファームウェア内でのみ実装すべきです。そうでないと、CPU がパケット処理のために起動し、電力節約の効果がなくなります。
  • filter_agefilter_age_16384th 値の誤設定: filter_age(APFv4)と filter_age_16384th(APFv6)の値は、accept_packet()apf_run() 関数に正しく渡す必要があります。filter_age_16384th の計算方法の詳細については、apf_interpreter.h のドキュメントを参照してください。
  • 必要なときに APF が有効になっていない: APF は、画面がオフで Wi-Fi 接続がアイドル状態、またはトラフィックが 10 Mbps 未満のときに有効化する必要があります。
  • accept_packet()apf_run() に渡されるパケットの切り捨て: accept_packet()apf_run() に渡されるすべてのユニキャスト、ブロードキャスト、およびマルチキャスト パケットは完全でなければなりません。切り捨てられたパケットを APF に渡した場合は無効となります。

APF テスト

Android 15 以降、APF フィルタと APF インタープリタの統合を正しく機能させるために、シングル デバイスおよびマルチデバイス用の CTS テストケースが提供されています。各テストケースの目的の概要は以下のとおりです。

  • ApfFilterapf_interpreter の統合テスト: ApfFilter が正しいバイトコードを生成し、apf_interpreter がそのコードを正しく実行して期待どおりの結果になるどうかを確認します。
  • APF シングル デバイス CTS: シングル デバイスを使用して、Wi-Fi チップセットで APF の機能をテストします。以下の点を確認します。
    • スクリーンがオンで Wi-Fi トラフィックが 10 Mbps 未満のときに APF が有効になること。
    • APF 機能が正しく宣言されていること。
    • APF メモリ領域での読み書き操作が成功し、その領域が予期せず変更されていないこと。
    • accept_packet()apf_run() に引数が正しく渡されていること。
    • APFv4 または APFv6 が統合されたファームウェアがパケットをドロップできること。
    • APFv6 が統合されたファームウェアがパケットに返信できること。
  • APF マルチデバイス CTS: 2 台のデバイス(1 台は送信側、もう 1 台は受信側)を使用して、APF のフィルタリング動作をテストします。送信側でさまざまな種類のパケットを生成し、そのパケットが ApfFilter で設定されたルールに基づいて正しくドロップされるか、渡されるか、応答されるかどうかを確認します。

追加の統合テスト手順

チップセット ベンダーが、自社の Wi-Fi ファームウェア統合テストスイートに APF テストを組み込むことを強くおすすめします。

APF テストを Wi-Fi ファームウェア統合テストスイートに組み込むことは、make-before-break やローミングといった複雑な Wi-Fi 接続シナリオにおいて、APF が正しく機能することを確認するために重要です。統合テストを実施する方法に関する詳しい手順については、次のセクションをご覧ください。

前提条件

統合テストを実施する際は、次の手順を行います。

  • APF はすべての統合テストケース(例: ローミング、make-before-break)で有効にする必要があります。
  • 各テストの開始時に、APF メモリを消去します。
  • テスト中は 5 分ごとに APF プログラムをインストールまたは再インストールします。

テストシナリオ

統合テスト中は APF が常にアクティブである必要があります。このドキュメントには、テスト中にインストールできる 2 つの APF プログラムが提供されています。これらのプログラムは 16 進文字列形式で記述されており、テスターは 16 進文字列をバイナリに変換してファームウェアにインストールし、apf_interpreter でプログラムが実行できるようにします。統合テスト中、テスターは、プログラム 1 およびプログラム 2 のフィルタリング ロジックをトリガーすると期待されるパケットを送信します。

APF プログラム 1

デバイスのスクリーンがオンのときに、APF プログラム 1 をインストールします。このプログラムは、デバイスの機能に影響を与えない無害なパケットをドロップします。こうしたパケットは、APF がネットワーク トラフィックを正しくフィルタしているかどうかをテストするために使用されます。

APF プログラム 1 のロジックは次のとおりです。

  1. ドロップしてカウンタを増やすパケット:
    1. EtherType の値: 0x88A20x88A40x88B80x88CD0x88E10x88E3
    2. IPv4 DHCP Discover または Request パケット
    3. RS パケット
  2. 渡してカウンタを増やすパケット: 他のすべてのパケット

APF プログラム 1 のバイトコードは次のとおりです。

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C005D88A27C005888A47C005388B87C004E88CD7C004988E17C004488E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE8721D120C84000E86DD0A1482093A0A368204856BE072086BDCB03A01B87206B03A01B87201
APF プログラム 2

デバイスのスクリーンがオフのときに、APF プログラム 2 をインストールします。このプログラムは、APF プログラム 1 がフィルタするすべてのパケットに加え、ping リクエスト パケットもフィルタします。APF プログラム 2 が正しくインストールされていることを確認するため、テスト対象デバイスに ping パケットを送信します。

APF プログラム 2 のロジックは次のとおりです。

  1. ドロップしてカウンタを増やすパケット:
    1. EtherType の値: 0x88A20x88A40x88B80x88CD0x88E10x88E3
    2. IPv4 DHCP Discover または Request パケット
    3. RS パケット
  2. ドロップしてカウンタを増やすパケット: ICMP ping リクエスト パケット
  3. 渡してカウンタを増やすパケット: 他のすべてのパケット

APF プログラム 2 のバイトコードは次のとおりです。

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C007488A27C006F88A47C006A88B87C006588CD7C006088E17C005B88E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE87234120C84000E86DD0A1482093A0A368204856BE0721F120C84001008000A17820B01AB0D220E8204086BE472086BDCB03A01B87206B03A01B87201
データ検証

APF プログラムが実行され、パケットが正しく渡されたか、またはドロップされたかを確認するには、次の手順を行います。

  • 5 分ごとに APF データ領域を取得して確認します。
  • カウンタを消去しないでください。
  • 各フィルタルールをトリガーするテストパケットを生成します。
  • 次のメモリ位置を使用して、カウンタの増加を確認します。

    カウンタ名 メモリ位置
    DROPPED_ETHERTYPE_DENYLISTED [ApfRamSize - 20, ApfRamSize - 16]
    DROPPED_DHCP_REQUEST_DISCOVERY [ApfRamSize - 24, ApfRamSize - 20]
    DROPPED_ICMP4_ECHO_REQUEST [ApfRamSize - 28, ApfRamSize - 24]
    DROPPED_RS [ApfRamSize - 32, ApfRamSize - 28]
    PASSED_PACKET [ApfRamSize - 36, ApfRamSize - 32]

APF プログラム 1 および APF プログラム 2 の擬似コード

以下の擬似コードは、APF プログラム 1 および APF プログラム 2 のロジックについて詳しく説明しています。

// ethertype filter
If the ethertype in [0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1, 0x88E3]:
    drop packet and increase counter: DROPPED_ETHERTYPE_DENYLISTED

// dhcp discover/request filter
if ethertype != ETH_P_IP:
    skip the filter
if ipv4_src_addr != 0.0.0.0:
    skip the filter
if ipv4_dst_addr != 255.255.255.255
    skip the filter
if not UDP packet:
    skip the filter
if UDP src port is not dhcp request port:
    skip the filter
else:
    drop the packet and increase the counter: DROPPED_DHCP_REQUEST_DISCOVERY

// Router Solicitation filter:
if ethertype != ETH_P_IPV6:
    skip the filter
if not ICMP6 packet:
    skip the filter
if ICMP6 type is not a Router Solicitation:
    skip the filter
else:
    drop the packet and increase the counter: DROPPED_RS

// IPv4 ping filter (only included in Program 2)
if ethertype != ETH_P_IP:
    skip the filter
if it ipv4 protocol is not ICMP:
    skip the filter
if port is not a ping request port
    skip the filter
else:
    drop the packet and increase the counter: DROPPED_ICMP4_ECHO_REQUEST

pass the packet and increase: PASSED_PACKET