zoukankan      html  css  js  c++  java
  • ntopng源码分析

    参数初始化以及ntop主流程启动


    1 #ifndef WIN32
    2   if((argc == 2) && (argv[1][0] != '-'))
    3     rc = prefs->loadFromFile(argv[1]);
    4   else
    5 #endif
    //一般启动ntopng的命令: ntopng /etc/ntopng/ntopng.conf 上面的代码就是读取配置文件/etc/ntopng/ntopng.conf里的配置信息。
    1 prefs->registerNetworkInterfaces();
    2 
    3   if(prefs->get_num_user_specified_interfaces() == 0) {
    4     /* We add all interfaces available on this host */
    5     prefs->add_default_interfaces();
    6   }
    //通过配置文件配置的interface信息注册可以使用的网卡信息:
    //如果没有配置网卡,ntopng会调用pcap的接口去查找所有可用的网卡,并注册。
    
    注:ntopng的配置文件跟命令行参数的输入是一样的 这种统一的配置方式非常方便,值得借鉴。
    
     1  // enable all protocols
     2     NDPI_BITMASK_SET_ALL(all);
     3     ndpi_set_protocol_detection_bitmask2(ndpi_struct, &all);
     4    // NetworkInterface类 初始化了协议检查的所有类型,并提供了报文分析的函数。
     5 
     6    if(iface == NULL) {
     7       try {
     8     iface = new PcapInterface(ifName);
     9       } catch(...) {
    10     ntop->getTrace()->traceEvent(TRACE_ERROR, "Unable to create interface %s", ifName);
    11     iface = NULL;
    12       }
    13     }
    14    //ntopng 默认使用libpcap来处理网卡抓包,这里默认使用PcapInterface这个类,PcapInterface继承了NetworkInterface类。
    15     
    16    iface->setCPUAffinity(core_id);
    17    //如果是多核多网卡的服务器,则需要考虑到性能,设置CPU亲和度,保证每个网卡能有对应的CPU处理
    18 
    19   ntop->start();
    20   //至此,进入抓包解析流程

    HTTPServer的初始化端口和lua CGI支持


     1  ntop->registerHTTPserver(new HTTPserver(prefs->get_http_port(),
     2                       prefs->get_docs_dir(),
     3                       prefs->get_scripts_dir()));
     4   //这里注册http服务器,以便后续的web监控使用。
     5 
     6   callbacks.begin_request = handle_lua_request;
     7   httpd_v4 = mg_start(&callbacks, NULL, (const char**)http_options);
     8   //然后调用第三方的http库,启用多线程的httpserver。
     9   //callbacks包含了处理http中请求lua脚本的功能函数。
    10 
    11 来到third-party/mongoose/mongoose.c文件, 函数mg_start:
    12   // Start master (listening) thread
    13   mg_start_thread(master_thread, ctx);
    14 
    15   // Start worker threads
    16   for (i = 0; i < atoi(ctx->config[NUM_THREADS]); i++) {
    17     if (mg_start_thread(worker_thread, ctx) != 0) {
    18       cry(fc(ctx), "Cannot start worker thread: %d", ERRNO);
    19     } else {
    20       ctx->num_threads++;
    21     }
    22   }
    23   //master_thread负责监听,并将accept接受的socket缓存到ctx->queue中;
    24   //worker_thread负责处理ctx->queue缓存的socket处理http请求。
    25 
    26   static void prepare_lua_environment(struct mg_connection *conn, lua_State *L)
    27   .....
    28   // Register "print" function which calls mg_write()
    29   lua_pushlightuserdata(L, conn);
    30   lua_pushcclosure(L, lsp_mg_print, 1);
    31   lua_setglobal(L, "print");
    32 
    33   // Register mg_read()
    34   lua_pushlightuserdata(L, conn);
    35   lua_pushcclosure(L, lsp_mg_read, 1);
    36   lua_setglobal(L, "read");
    37   //上面的代码注册了lua脚本使用的print和read函数。
    38   //prepare_lua_environment函数使得httpserver支持lua脚本作为CGI语言。
      //后续就可以通过lua脚本来回应web客户端的各种request;
      //lua又通过lua c api的扩展来获取后面报文分析的结果来填充网页的请求。
    

    抓包和报文分析主流程


    下面的代码是在src/ntopng.cpp  start函数:
    1 for(int i=0; i<num_defined_interfaces; i++) {
    2     iface[i]->allocateNetworkStats();
    3     iface[i]->startPacketPolling();
    4   }
    5 //allocateNetworkStats 初始化网络统计功能
    6 //开始抓包
    7 //startPacketPolling 注意是一个虚函数,这里是多态,实际是PcapInterface的startPacketPolling 函数。
    下面来到src/PcapInterface.cpp文件:
     1 void PcapInterface::startPacketPolling() { 
     2   pthread_create(&pollLoop, NULL, packetPollLoop, (void*)this);  
     3   pollLoopCreated = true;
     4   NetworkInterface::startPacketPolling();
     5 }
     6 
     7 //startPacketPolling函数创建了一个线程,线程主要处理函数是packetPollLoop。
     8 //static void* packetPollLoop(void* ptr), 就定义在PcapInterface.cpp文件里。
     9 
    10 //packetPollLoop函数开始了报文复制和分析的过程
    11     FILE *pcap_list = iface->get_pcap_list();
    12     ......
    13     hdr->caplen = min_val(hdr->caplen, iface->getMTU());
    14     iface->dissectPacket(hdr, pkt, &shaped, &p);
    //dissectPacket 是NetworkInterface类的成员函数,里面开始了复杂的报文解析流程。。。
    //bool dissectPacket(const struct pcap_pkthdr *h, const u_char *packet, bool *shaped, u_int16_t *ndpiProtocol);
    //分析出报文的类型之后,将报文传给processPacket函数处理和统计
     1 bool processPacket(const struct bpf_timeval *when,
     2              const u_int64_t time,
     3              struct ndpi_ethhdr *eth,
     4              u_int16_t vlan_id,
     5              struct ndpi_iphdr *iph,
     6              struct ndpi_ipv6hdr *ip6,
     7              u_int16_t ipsize, u_int16_t rawsize,
     8              const struct pcap_pkthdr *h,
     9              const u_char *packet,
    10              bool *shaped,
    11              u_int16_t *ndpiProtocol);
    12 
    13 inline void incStats(time_t when, u_int16_t eth_proto, u_int16_t ndpi_proto,
    14                u_int pkt_len, u_int num_pkts, u_int pkt_overhead) {
    15     ethStats.incStats(eth_proto, num_pkts, pkt_len, pkt_overhead);
    16     ndpiStats.incStats(ndpi_proto, 0, 0, 1, pkt_len);
    17     pktStats.incStats(pkt_len);
    18     if(lastSecUpdate == 0) lastSecUpdate = when; else if(lastSecUpdate != when) updateSecondTraffic(when);
    19   };
    20 //因涉及到pcap抓包,所以有些常量是pcap定义的
    21 #define DLT_NULL    0    /* BSD loopback encapsulation */
    22 #define DLT_EN10MB    1    /* Ethernet (10Mb) */
    23 #define DLT_EN3MB    2    /* Experimental Ethernet (3Mb) */
    24 #define DLT_AX25    3    /* Amateur Radio AX.25 */
    25 #define DLT_PRONET    4    /* Proteon ProNET Token Ring */
    26 #define DLT_CHAOS    5    /* Chaos */
    27 #define DLT_IEEE802    6    /* 802.5 Token Ring */
    28 #define DLT_ARCNET    7    /* ARCNET, with BSD-style header */
    29 #define DLT_SLIP    8    /* Serial Line IP */
    30 #define DLT_PPP        9    /* Point-to-point Protocol */
    31 #define DLT_FDDI    10    /* FDDI */
    32 
    33 /*
    34  * These are types that are different on some platforms, and that
    35  * have been defined by <net/bpf.h> for ages.  We use #ifdefs to
    36  * detect the BSDs that define them differently from the traditional
    37  * libpcap <net/bpf.h>
    38  *
    39  * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
    40  * but I don't know what the right #define is for BSD/OS.
    41  */
    42 #define DLT_ATM_RFC1483    11    /* LLC-encapsulated ATM */
    43 
    44 #ifdef __OpenBSD__
    45 #define DLT_RAW        14    /* raw IP */
    46 #else
    47 #define DLT_RAW        12    /* raw IP */
    48 #endif
    
    
  • 相关阅读:
    java的构造方法 java程序员
    No result defined for action cxd.action.QueryAction and result success java程序员
    大学毕业后拉开差距的真正原因 java程序员
    hibernate的回滚 java程序员
    验证码 getOutputStream() has already been called for this response异常的原因和解决方法 java程序员
    浅谈ssh(struts,spring,hibernate三大框架)整合的意义及其精髓 java程序员
    你平静的生活或许会在某个不可预见的时刻被彻底打碎 java程序员
    Spring配置文件中使用ref local与ref bean的区别. 在ApplicationResources.properties文件中,使用<ref bean>与<ref local>方法如下 java程序员
    poj1416Shredding Company
    poj1905Expanding Rods
  • 原文地址:https://www.cnblogs.com/danxi/p/5799518.html
Copyright © 2011-2022 走看看