Android Packet Filter

O filtro de pacotes do Android (APF, na sigla em inglês) permite que o framework controle a lógica de filtragem de pacotes de hardware no momento da execução. Isso permite que o sistema economize energia descartando pacotes na hardware, permitindo que o framework do Android mude as regras de filtragem no momento da execução com base nas condições da rede.

Visão geral do APF

O APF consiste em dois componentes principais:

  • O interpretador APF é executado em hardware de rede (normalmente, o chipset Wi-Fi). O interpretador do APF executa o bytecode do APF em pacotes recebidos pelo hardware e decide se vai aceitar, descartar ou responder a eles.
  • O código de geração de programas APF é executado na CPU principal. O código cria e atualiza programas APF de acordo com a rede e o estado do dispositivo.

Os métodos do HAL do Wi-Fi permitem que o framework do Android instale o bytecode do programa do APF e leia os contadores atuais. O módulo de linha principal da pilha de rede pode atualizar o bytecode do programa APF a qualquer momento durante a execução do APF.

Há vários filtros APF implementados. Por exemplo, o APF inclui filtros para descartar ethertypes não permitidos, filtrar pacotes de anúncio de roteador IPv6 (RA), filtrar o tráfego multicast e broadcast se o bloqueio multicast não estiver ativo, descartar pacotes DHCP para outros hosts e descartar pacotes de protocolo de resolução de endereço (ARP) e de descoberta de vizinho (ND) não solicitados. Se o firmware oferecer suporte ao APFv6, o ApfFilter também vai gerar regras para responder a tipos de pacotes comuns que, de outra forma, exigiriam que a CPU fosse ativada para responder, como consultas ARP e consultas NS. A lista completa de filtros é definida em ApfFilter.

Como o código de geração de programa APF faz parte do módulo de pilha de rede, é possível usar mensalmente as [Mainline updates (em inglês) para adicionar novos filtros e atualizar a lógica de filtragem.

Revisão de APF

A lista a seguir descreve o histórico de revisões do APF:

  • APFv6:introduzida no Android 15, essa versão oferece suporte à filtragem de pacotes, inclui contadores para depuração e métricas e oferece suporte à transmissão de pacotes.
  • APFv4:introduzida no Android 10, essa versão oferece suporte à filtragem de pacotes e inclui contadores para depuração e métricas.
  • APFv2:introduzida no Android 7, essa versão oferece suporte à filtragem de pacotes.

Integração com o APF

As APIs APF entre o intérprete APF e o hardware são definidas em apf_interpreter.h (APFv4, APFv6). O código do firmware do Wi-Fi chama accept_packet() no APFv4 ou apf_run() no APFv6 para determinar se o pacote deve ser descartado (valor de retorno zero) ou transferido para o processador do app (valor de retorno diferente de zero). Se um pacote precisar ser transmitido, apf_run() também retornará zero, porque o pacote não precisa ser transmitido ao processador do app. Se o firmware oferecer suporte ao APFv6, ele precisará implementar as APIs apf_allocate_buffer() e apf_transmit_buffer(). O interpretador APF chama essas duas APIs durante a lógica de transmissão de pacotes. As instruções APF têm comprimento variável. Cada instrução tem pelo menos 1 byte de comprimento. Os códigos de instrução do APF são definidos em apf.h para APFv4 e são inline diretamente em apf_interpreter.c para APFv6.

A APF depende de memória dedicada. A memória é usada para o programa APF e para o armazenamento de dados. Ela não pode ser limpa ou gravada pelo chipset, exceto pelos métodos HAL do APF. O bytecode do APF usa o armazenamento de dados para armazenar contadores de pacotes aceitos e descartados. A região de dados pode ser lida do framework do Android. As instruções APF são eficientes em termos de memória, mas maximizar o potencial de economia de energia e funcionalidade exige regras de filtragem complexas e dinâmicas. Essa complexidade exige uma parte dedicada de memória no chipset. O requisito mínimo de memória para APFv4 é de 1.024 bytes, enquanto o APFv6 requer 2.048 bytes. No entanto, recomendamos alocar 4096 bytes para o APFv6 para garantir o desempenho ideal. O intérprete do APF precisa ser compilado no firmware. Os intérpretes APFv4 e APFv6 são otimizados para o tamanho do código. Na arquitetura arm32, o interpretador APFv4 compilado tem cerca de 1,8 KB, enquanto o interpretador APFv6 mais complexo, com recursos adicionais (por exemplo, suporte nativo a checksum e código de descompressão DNS nativo), é aproximadamente 4 KB.

Os filtros APF podem funcionar com outros filtros específicos do fornecedor do chipset no firmware. Os fornecedores de chipset podem executar a lógica de filtragem antes ou depois do processo de filtragem da APF. Se um pacote for descartado antes de chegar ao filtro APF, ele não será processado.

Para garantir a funcionalidade correta do filtro APF, quando o APF está ativado, o firmware precisa fornecer ao filtro APF acesso a todo o pacote, não apenas ao cabeçalho, quando o APF está ativado.

Exemplos de programas de APF

ApfTest e ApfFilterTest contêm programas de teste de exemplo que ilustram como cada filtro APF funciona. Para estudar o programa gerado, modifique o caso de teste para imprimir o programa como uma string hexadecimal.

A pasta testdata contém programas APFv4 de exemplo para filtros RA do APF. A pasta samples contém utilitários Python que geram programas de transferência de APFv6. Para mais detalhes, consulte a documentação nos arquivos de utilitários do Python.

Depurar APF

Para verificar se o APF está ativado no dispositivo, mostre o programa atual, mostre os contadores atuais e execute o comando adb shell dumpsys network_stack. Confira a seguir um exemplo desse comando:

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

A saída do comando adb shell dumpsys network_stack deste exemplo inclui o seguinte:

  • ApfCapabilities{version: 4, maxSize: 4096, format: 1}: significa que os chips Wi-Fi oferecem suporte a APF (versão 4).
  • Last program: esta seção é o binário do programa APF instalado mais recente no formato de string hexadecimal.
  • APF packet counters: esta seção mostra quantos pacotes são transmitidos ou descartados pelo APF e os motivos específicos.

Para decodificar e desmontar o código em uma linguagem assembly legível por humanos, use a ferramenta apf_disassembler. Para compilar o binário executável, execute o comando m apf_disassembler. Confira a seguir um exemplo de como usar a ferramenta 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
......

Para verificar os resultados da APF off-line, use a ferramenta apf_run. Para compilar o binário executável, execute o comando m apf_run. A ferramenta apf_run oferece suporte a intérpretes APFv4 e APFv6.

Confira a seguir o manual do comando apf_run. Por padrão, o comando apf_run é executado no interpretador APFv4. A transmissão do argumento --v6 para apf_run permite que ele seja executado no interpretador APFv6. Todos os outros argumentos podem ser usados para APFv4 e 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.

Confira um exemplo de como transmitir um pacote para o APF para verificar se ele pode ser excluído ou transmitido.

Para fornecer a apresentação de string binária hexadecimal do pacote bruto, use a opção --packet. Para fornecer a string binária hexadecimal da região de dados, que é usada para armazenar o contador APF, use o --data option. Como cada contador tem 4 bytes, as regiões de dados precisam ser longas o suficiente para garantir que não ocorra um buffer overflow.

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

Para verificar os resultados do APF em relação ao arquivo pcap capturado pelo tcpdump, use o comando apf_run da seguinte maneira:

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

Para testar os recursos de transmissão do APFv6, use o comando apf_run da seguinte maneira:

$ 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

Quando você usa o parâmetro --trace, a ferramenta apf_run fornece uma saída detalhada de cada etapa na execução do interpretador, o que é útil para depurar. Neste exemplo, inserimos um pacote de consulta ARP no programa APF. A saída mostra que a consulta ARP foi descartada, mas um pacote de resposta foi gerado. Os detalhes desse pacote gerado são mostrados na seção transmitted packet.

Problemas comuns de integração

Esta seção destaca vários problemas comuns encontrados durante a integração da APF:

  • Limpeza inesperada da região de dados:a memória do APF precisa ser totalmente dedicada ao APF. Somente o código do intérprete ou do framework (pela API HAL) pode modificar a região de memória do APF.
  • Problemas de instalação com programas APF de X bytes (X <= maxLen): o firmware precisa oferecer suporte à leitura ou gravação de qualquer comprimento de programa até maxLen sem falhas, travamentos ou truncamentos. As gravações não podem alterar bytes entre X e maxLen.
  • Implementação de APF no código do driver:o APF precisa ser implementado apenas no firmware, não no código do driver. Caso contrário, não há benefícios de economia de energia porque a CPU precisa ser ativada para processar o pacote.
  • Valores filter_age ou filter_age_16384th incorretos:os valores filter_age (APFv4) e filter_age_16384th (APFv6) precisam ser transmitidos corretamente para as funções accept_packet() e apf_run(). Para mais detalhes sobre o cálculo de filter_age_16384th, consulte a documentação em apf_interpreter.h.
  • APF não ativado quando necessário:o APF precisa estar ativado quando a tela estiver desligada e o link Wi-Fi estiver inativo ou o tráfego estiver abaixo de 10 Mbps.
  • Pacotes truncados transmitidos para accept_packet() ou apf_run():todos os pacotes unicast, broadcast e multicast transmitidos para accept_packet() ou apf_run() precisam estar completos. A transmissão de pacotes truncados para o APF não é válida.

Testes de APF

A partir do Android 15, o Android oferece casos de teste do CTS para um dispositivo e vários dispositivos para o filtro APF e a integração do interpretador APF para garantir a funcionalidade correta do APF. Confira o objetivo de cada caso de teste:

  • Teste de integração de ApfFilter e apf_interpreter:verifica se ApfFilter gera o bytecode correto e se apf_interpreter executa o código corretamente para produzir os resultados esperados.
  • CTS de APF para um único dispositivo:usa um único dispositivo para testar a funcionalidade de APF no chipset Wi-Fi. Confirma que:
    • O APF é ativado quando a tela está desligada e o tráfego de Wi-Fi está abaixo de 10 Mbps.
    • Os recursos do APF são declarados corretamente.
    • As operações de leitura e gravação na região de memória do APF são bem-sucedidas, e a região de memória não é modificada de forma inesperada.
    • Os argumentos são transmitidos corretamente para accept_packet() ou apf_run().
    • O firmware integrado ao APFv4/APFv6 pode descartar pacotes.
    • O firmware integrado ao APFv6 pode responder a pacotes.
  • CTS de vários dispositivos do APF:usa dois dispositivos (um emissor e um receptor) para testar o comportamento de filtragem do APF. Vários tipos de pacotes são gerados no lado do remetente, e o teste confirma se eles são descartados, transmitidos ou respondidos corretamente com base nas regras configuradas em ApfFilter.

Instruções adicionais para testes de integração

Além disso, recomendamos que os fornecedores de chipset incorporem os testes de APF nas próprias suítes de teste de integração do firmware Wi-Fi.

A integração de testes de APF em pacotes de testes de integração de Wi-Fi de firmware é crucial para verificar a funcionalidade adequada do APF em cenários complexos de conexão Wi-Fi, como cenários de conexão Wi-Fi de make-before-break ou roaming. Confira instruções detalhadas sobre como realizar testes de integração na seção a seguir.

Pré-requisitos

Ao realizar testes de integração, faça o seguinte:

  • O APF precisa ser ativado em todos os casos de teste de integração (por exemplo, roaming, make-before-break).
  • No início de cada teste, limpe a memória do APF.
  • Instale ou reinstale os programas APF a cada 5 minutos durante o teste.

Cenários de teste

O APF precisa estar ativo durante os testes de integração. Há dois programas de APF fornecidos neste documento que podem ser instalados durante o teste. Os programas estão no formato de string hexadecimal, e o testador precisa converter a string hexadecimal em binário e instalá-la no firmware para que os programas possam ser executados por apf_interpreter. Durante o teste de integração, o testador precisa enviar pacotes que devem acionar a lógica de filtragem no programa 1 e no programa 2.

Programa APF 1

Quando a tela do dispositivo estiver ligada, instale o programa APF 1. Esse programa pode descartar pacotes inofensivos que não afetam a funcionalidade do dispositivo. Esses pacotes são usados para testar se o APF está filtrando corretamente o tráfego de rede.

A lógica do programa 1 do APF é a seguinte:

  1. Contador de queda e incremento:
    1. Valores de EtherType: 0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1, 0x88E3
    2. Pacotes de descoberta ou solicitação DHCP IPv4
    3. Pacotes RS
  2. Contador de passagem e incremento: todos os outros pacotes.

Os códigos de 1 byte do programa APF são os seguintes:

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C005D88A27C005888A47C005388B87C004E88CD7C004988E17C004488E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE8721D120C84000E86DD0A1482093A0A368204856BE072086BDCB03A01B87206B03A01B87201
Programa APF 2

Quando a tela do dispositivo estiver desligada, instale o programa 2 do APF. Esse programa filtra todos os pacotes que o programa 1 do APF filtra, bem como pacotes de solicitação de ping. Para verificar se o programa 2 do APF está instalado corretamente, envie pacotes de ping para o dispositivo em teste.

A lógica do programa 2 do APF é a seguinte:

  1. Contador de queda e incremento:
    1. Valores de EtherType: 0x88A2, 0x88A4, 0x88B8, 0x88CD, 0x88E1, 0x88E3
    2. Pacotes de descoberta ou solicitação DHCP IPv4
    3. Pacotes RS
  2. Contador de descarte e incremento: pacotes de solicitação de ping ICMP
  3. Contador de passagem e incremento: todos os outros pacotes

Os códigos de 2 bytes do programa APF são os seguintes:

6BF0B03A01B86BF8AA0FB86BF4AA09B8120C6BEC7C007488A27C006F88A47C006A88B87C006588CD7C006088E17C005B88E3120C84002008001A1A821B001A1E8600000010FFFFFFFF0A17820B11AB0D2A108204436BE87234120C84000E86DD0A1482093A0A368204856BE0721F120C84001008000A17820B01AB0D220E8204086BE472086BDCB03A01B87206B03A01B87201
Verificação de dados

Para verificar se o programa APF é executado e os pacotes são transmitidos ou descartados corretamente, faça o seguinte:

  • Extraia e verifique a região de dados do APF a cada cinco minutos.
  • Não limpe o contador.
  • Gerar pacotes de teste para acionar cada regra de filtro.
  • Verifique os incrementos do contador usando os seguintes locais de memória:

    Nome do contador Local de memória
    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]

Pseudocódigo para o programa 1 e 2 da APF

O pseudocódigo a seguir explica a lógica dos programas 1 e 2 da APF em detalhes:

// 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