Valeu ai pedro... vai ajudar muito o entendimento =D

--- Em [email protected], PEdroArthur_JEdi <[EMAIL PROTECTED]>
escreveu
>
> Boa tarde galera,
> 
> A alguns messes escrevi um guia do código do HLBR para meu orientador
> aqui na universidade. Estou enviando-o como anexo para que quem quiser
> possa dar uma olhada. Ele é baseado na versão 1.6 do código. Sempre
> que puder vou tentar melhorá-lo e mandar aqui pra vocês. Espero que
> gostem! Qualquer dúvida podem mandar pra lista, afinal sua dúvida pode
> ser a de outro participante. E quem quiser desenvolver, é só falar!
> 
> -- 
> PEdroArthur_JEdi
> 
> Nunca acredite num sistema que você não conhece o código fonte!
> Never trust a system you don't have sources for!
> 
> Após ler as configurações do sistemas, o HLBR entra em seu loop
principal para iniciar a verificação dos pacotes que trafégam em suas
interfaces. Esse comportamento é observável através do arquivo fonte
engine/main_loop.c (int MainLoop()).
> 
> A função MainLoop tem por principal função verificar se o sistema
está configurado para usar threads ou não. Em caso afirmativa,
MainLoop desviará sua execução para a função int MainLoopThreaded(),
caso contrário, será chamada a função int MainLoopPoll().
> 
>       engine/main_loop.c:
>       362:    if (!Globals.UseThreads){
>       363:            for (i = 0 ; i < Globals.NumInterfaces ; i++){
>       364:                    if (!Globals.Interfaces[i].IsPollable){
>       365:                            printf("Error. All interfaces must be 
> able to poll in
single thread mode.\n");
>       366:                            return FALSE;
>       367:                    }
>       368:            }
>       369:            return MainLoopPoll();
>       370:    }else{
>       371:            return MainLoopThreaded();
>       372:    }
> 
> MainLoopThread tentará iniciar uma thread para cada interface de
rede que será usada pelo HLBR, retonando FALSE caso não consiga lançar
uma das threads:
> 
>       engine/main_loop.c:
>       337:    for (i = 0 ; i < Globals.NumInterfaces ; i++)
>       338:            if (!StartInterfaceThread(i)){
>       339:                    printf("Couldn't start thread for interface\n");
>       340:                    return FALSE;
>       341:            }
> 
> Apartir desse momento, o HLBR começará a aceitar pacotes para
análise. MainLoopThreaded chamará a função void
ProcessPacketThread(void *), a qual é reponsável por manter um laço
infinito, representando uma relação de produtor/consumidor com os
threads das interfaces em meio ao uso da fila de pacotes pendentes
(Globals.Packets[MAX_PACKETS].status == PACKET_STATUS_PENDING definido
em engine/hlbr.h). O excerto de código reponsável por essa função se
encontra abaixo:
> 
>       engine/main_loop.c:
>       242:    while (!Globals.Done) {
>       243:            PacketSlot = PopFromPending();
>       244:
>       245:            if (PacketSlot != PACKET_NONE) {
>       246:                    ProcessPacket(PacketSlot);
>       247:            } else {
>       248:                    IdleFunc();
>       249:            }
>       250:    }
> 
> Podemos ver que enquanto a variável Globals.Done não for verdadeira,
a thread em questão ficará aguardando por pacotes. A cada iteração ela
irá ceder seu tempo de processamento para outra thread caso não tenha
nenhum pacote aguardando, ou, dado o número do pacote (int
PacketSlot), o fluxo será desviado para a função int
ProcessPacket(int), responsável por encaminhar o pacote para
decodificação (arquivo fonte decoders/decode.c), coletar algumas
estatísticas dos pacotes, chamar as funções de ação, encaminhar o
pacote para seu destino e retornar um slot vazio a fila de pacotes
ociosos.
> 
>       engine/main_loop.c:
>       191:    if (!Decode(Globals.DecoderRoot, PacketSlot)){
>       192:            printf("Error Processing Packet\n");
>       193:    }
> 
> O procedimento acima encaminha o pacote para a decodificação.
Globals.DecoderRoot é um inteiro que representa o primeiro
decodificador ao qual um pacote deve passar. Normalmente,
Globals.DecoderRoot contém o valor do DecoderInterface
(decoders/decode_interface.c). PacketSlot representa o número do
pacote a ser processado.
> 
>       engine/main_loop.c:
>       196:    PacketSec++;
>       198:    if (GetDataByID(PacketSlot, TCPDecoderID, &data))
>       199:            TCPSec++;
>       200:    else if (GetDataByID(PacketSlot, UDPDecoderID, &data))
>       201:            UDPSec++;
>       203:    if (Globals.Packets[PacketSlot].tv.tv_sec != LastTime){
>       204:            Globals.PacketsPerSec = PacketSec;
>       205:            Globals.TCPPerSec = TCPSec;
>       206:            Globals.UDPPerSec = UDPSec;
>       208:            PacketSec = 0;
>       209:            TCPSec = 0;
>       210:            UDPSec = 0;
>       212:            LastTime = Globals.Packets[PacketSlot].tv.tv_sec;
>       213:    }
> 
> Coleta estatísticas sobre a rede com informações baseadas nos
contadores dos pacotes.
> 
>       engine/main_loop.c
>       215:    if (!BitFieldIsEmpty(p->RuleBits,Globals.NumRules)){
>       219:            if (!PerformActions(PacketSlot)){
>       220:                    printf("Failed to execute the actions\n");
>       221:            }
>       222:    }
> 
> Verifica se alguma regra conferiu com o pacote.
> 
>       engine/main_loop.c
>       224:    RouteAndSend(PacketSlot);
> 
> Envia o pacote pela rede.
> 
>       engine/main_loop.c
>       225:    ReturnEmptyPacket(PacketSlot);
> 
> Retorna o pacote vazio a lista de ociosos.
> 
> Dentre os procedimentos chamados acima, int Decode(int, int),
definido em decoders/decode.c, tem predominância no comportamento do
HLBR. Ele é responsável por encaminhar recursivamente os pacotes por
entre os decodificadores até que se tenha uma decisão quanto ao
destino do pacote. O código reproduzido abaixo representa a chamada de
decodificação do pacote:
> 
>       decoders/decode.c:
>       277:    p->DecoderInfo[DecoderID].Data =
Globals.Decoders[DecoderID].DecodeFunc(PacketSlot);
> 
> Para entender melhor o que está acontecendo, devemos compreender o
que é um decoder. Um decoder nada mais é que uma estrutura de dados
onde são armazenados o nome do decoder, seu ID, sua mascará de
dependência, testes associados, módulos associados, decoders filhos,
decoder pai, próximo filho (campo acessado para escrita apenas pela
função int DecoderAddDecoder(int, int)), uma função de decodificação,
uma função de dealocação, uma função de configuração e sua flag de
atividade. A estrura de dados encontra-se definida no arquivo fonte
engine/hlbr.h, e reproduzida abaixo:
> 
>       engine/hlbr.h:
>       249:    typedef struct decoder_rec{
>       250:            char                    Name[MAX_NAME_LEN];
>       251:            int                     ID;
>       252:            unsigned char           DependencyMask[MAX_RULES/8];    
>         
>       253:            struct test_rec*        Tests;
>       254:            struct module_rec*      Modules;
>       255:            struct decoder_rec*     Children;
>       256:            struct decoder_rec*     Parent; 
>       257:            struct decoder_rec*     NextChild;
>       259:            void*                   (*DecodeFunc) (int PacketSlot);
>       260:            void                    (*Free) (void *pointer);
>       261:            int                     (*ConfigFunction) (FILE *fp);
>       263:            char                    Active; /*true if anything 
> actually uses it*/
>       264:    } DecoderRec;
> 
> Outra estrutura de dados importante para que possamos prosseguir é a
PacketRec (engine/hlbr.h). PacketRec possui todas as informações
relevantes a um pacote. Dentre elas, as mais importantes são
RawPacket, representando o pacote de dados em forma bruta, BeginData,
que representa o offset onde o primeiro byte não decodificado se
encontra, PacketLen, comprimento do pacote, PassRawPacket, flag de
bloqueio, e sua mascára de bits.
> 
>       engine/hlbr.h:
>       160     typedef struct packet_rec {
>       161             int                     PacketSlot;
>       162             unsigned int            PacketNum;
>       164             int                     InterfaceNum;
>       165             int                     TargetInterface;
>       167             unsigned char*          RawPacket;
>       168             char                    Pad[2];
>       169             unsigned char           
> TypicalPacket[TYPICAL_PACKET_SIZE];
>       170             char                    LargePacket;
>       171             int                     PacketLen;
>       173             unsigned char           RuleBits[MAX_RULES/8];
>       174             struct timeval          tv;
>       176             DecoderData             DecoderInfo[MAX_DECODER_DEPTH];
>       177             int                     DecodersUsed[MAX_DECODERS];
>       178             int                     NumDecoderData;
>       180             int                     BeginData;
>       183             char                    PassRawPacket;
>       184             int                     SaveCount;
>       187             char                    Status;
>       189             pthread_mutex_t         Mutex;
>       190             int                     LockID; 
>       192             struct port_pair*       Stream;
>       193     } PacketRec;
> 
> Com isso, podemos ver que o código executado na linha 277 de
decoders/decode.c coleta os dados importantes do pacote para um dado
decoder. Caso o pacote seja irrelevante ao decoder em questão (sua
decodificação retorne NULL), todas as regras que dependem desse
decoder são marcadas como inativa. Isso ocorre em:
> 
>       decoders/decode.c
>       281:    if (p->DecoderInfo[DecoderID].Data) {
>                       /* And the code Flows */
>       307:    } else {
>       309:            NotAndBitFields(p->RuleBits,
Globals.Decoders[DecoderID].DependencyMask, p->RuleBits,
Globals.NumRules);
>       310:            return TRUE;
>       311:    }
> 
> Caso contrário, o pacote possua informações relevantes ao decoder,
esse último é marcado como em uso e a função se encarrega de chamar os
testes associados:
> 
>       decoders/decode.c
>       287:    p->DecodersUsed[p->NumDecoderData++] = DecoderID;
>       290:    test = Globals.Decoders[DecoderID].Tests;
>       292:    while (test) {
>       293:            if (test->Active)
>       294:                    if (test->TestFunc) 
>       295:                            test->TestFunc(PacketSlot, 
> test->TestNodes);
>       296:            test = test->Next;
>       297:    }
> 
> Testes também são estrutura de dados. TestRec armazena o nome do
teste, o nome dos testes na escrita de regras, seu ID, o ID do
decodificador associado, os nós de teste (estrutura explicada mais
abaixo), um ponteiro para o proximo teste, a mascára de dependência,
uma função para adição de nós de teste, a função de teste, uma função
para finalizar a adição de testes e uma função reservada para uso futuro.
> 
>       engine/hlbr.h:
>       220:    typedef struct test_rec{
>       221:            char                    Name[MAX_NAME_LEN];
>       222:            char                    ShortName[MAX_NAME_LEN];
>       223:            int                     ID;
>       224:            int                     DecoderID;
>       225:            char                    Active;
>       226:            TestNode*               TestNodes;
>       227:            struct test_rec*        Next;
>       228:            unsigned char           DependencyMask[MAX_RULES/8];
>       230:            int                     (*AddNode)(int TestID, int 
> RuleID, char* Args);
>       231:            int                     (*FinishedSetup)();
>       232:            int                     (*TestFunc)(int PacketSlot, 
> TestNode* Nodes);
>       233:            int                     (*TestStreamFunc)(int 
> PacketSlot, TestNode* Nodes);
>       234:    } TestRec;
> 
> Os arquivos de regras formam os nós de um PacketRec. Como por exemplo:
> 
>       rules/www.rules
>       10:     <rule>
>       11:     ip dst(www)
>       12:     tcp dst(80)
>       13:     tcp regex(GET[ -~]+\.asp($|/|\&|\?))
>       14:     message=(www-1) .asp request
>       15:     action=action1
>       16:     </rule>
> 
> O que dizemos é: ao decodificador IP, adicionar um nó do teste DST
com o valor "www". Ao decodificador TCP, adicionar um nó do teste DST
com o valor 80 e adicionar um nó ao teste REGEX com o argumento "GET[
-~]+\.asp($|/|\&|\?)". Esses nós são armazenados em estruturas
TestNode e enfileirados em meio ao uso de ponteiros:
> 
>       engine/hlbr.h
>       209:    typedef struct test_node{
>       210:            int                     RuleID;
>       211:            void*                   Data;
>       212:            struct test_node*       Next;
>       213:    } TestNode;
> 
> Portanto, de forma bastante abstrata, na regra mostrada mais acima
teriámos:
> 
>       TestNode {10, www, *}
>       TestNode {10, 80, *}
>       TestNode {10, GET[ -~]+\.asp($|/|\&|\?), *}
> 
> Cada qual associado a seus respectivos decoders.
> 
> Voltando para a função Decode, após os testes, é checado se ainda
existem regras a serem conferidas. Caso não haja, a função retorna e
podemos procurar por outro pacote para analisar, caso haja, devemos
passar o pacote adiente, seguinda a hierárquia dos decodificadores. O
seguinte trecho de código concretiza essa idéia:
> 
>       decoders/decode.c
>       326:    child = Globals.Decoders[DecoderID].Children;
>       327:    while (child) {
>       328:            if (!Decode(child->ID, PacketSlot)) {
>       329:                    fprintf(stderr, "Decoder %s failed\n", 
> child->Name);
>       330:            }
>       331:            child = child->NextChild;
>       332:    }
> 
> Estamos chamando a função Decode recursivamente, passando dessa vez
como parâmetros o DecoderID do decoder filho e o pacote atual. Esse
processo irá se repetir até que a condição de não haver mais regras
seja atingida:
> 
>       decoders/decode.c
>       314:            if (!BitFieldIsEmpty(p->RuleBits, Globals.NumRules)) {
>       322:                    return TRUE;
>       323:            }
>


Responder a