libnids學習筆記

學習資料

[1]下載包內的doc/API.html,version:1.24

[2]http://blog.csdn.net/ningxiaowei2013/article/details/53035976

簡介

​ libnids(Network Intrusion Detection System Library),網絡入侵監測系統函數庫。具有重組TCP數據段、處理IP分片包和監測TCP端 口掃描的功能。

​ 所有的結構體和函數都在在“nids.h”,使用libnids的函數必須包含這個頭文件和libnids.a的鏈接。

​ 一個main函數的僞代碼:

int main()
{
    application private processing, not related to libnids
    optional modification of libnids parameters
    if (!nids_init() ) something's wrong, terminate;
    registration of callback functions
    nids_run();//or nids_next();
    // not reached in normal situation
}

IP重組

爲了使libnids能接收所有的IP數據包(包括分片包、畸形包等),程序員需要定義如下的回調函數:

void ip_frag_func(struct ip * a_packet, int len)

在調用nids_init()函數初始化後,使用nids的函數進行註冊:

nids_register_ip_frag(ip_frag_func);

這樣回調函數ip_frag_func會在適當的時候由libnids調用,參數a_packet指針將指向接收到的數據報,len是數據報長度。

類似地,如果僅接收目標主機會接受的數據包(如非碎片包、重組包或頭部校驗正確的數據包等),需要定義如下回調函數:

void ip_func(struct ip * a_packet, int len)

然後註冊:

nids_register_ip(ip_func);

TCP數據流重組

要接收TCP流在交換的數據,必須定義如下回調函數:

void tcp_callback(struct tcp_stream * ns, void ** param)

結構體tcp_stream提供了一個TCP連接的所有信息。例如,它包含了客戶端與服務器端的half_stream (named client and server)結構。下文會對該結構的字段進行解釋。

tcp_stream結構有一個名爲nids_state的字段。此字段的數值將決定tcp_callback的操作。

  1. ns->nids_state==NIDS_JUST_EST

    ns是一個剛剛建立的連接。tcp_callback可以據此決定是否對該連接的後續數據進行檢查。所有的連接參數(ip,端口號等)都可獲得。如需要檢查,tcp_callback回調函數將通知libnids它希望接收哪些數據(如到客戶端的數據、到服務器端的數據、到客戶端的緊急數據或到服務器端的緊急數據等),然後返回。

  2. ns->nids_state==NIDS_DATA

    此時,新數據已經到達。結構體half_stream(tcp_stream的元素)包含數據buffer。

  3. 下面的nids_state狀態:

    • NIDS_CLOSE
    • NIDS_RESET
    • NIDS_TIMEOUT

    意味着連接已經關閉。若有資源佔用的話,tcp_callback需要釋放資源。

  4. ns->nids_state==NIDS_EXITING

    此時,libnids已經退出。這是程序使用保存在half_stream buffer中數據的最後一次機會。當在抓包文件中讀取而不是從網絡流讀取時,libnids可能永遠不會close, reset, or timeout。如果程序有未處理的數據(例如,調用了nids_discard()),這個狀態下允許程序去處理這些數據。

示例程序

/*http://libnids.sourceforge.net/printall.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include "nids.h"

#define int_ntoa(x) inet_ntoa(*((struct in_addr *)&x))

// struct tuple4 contains addresses and port numbers of the TCP connections
// the following auxiliary function produces a string looking like
// 10.0.0.1,1024,10.0.0.2,23
char * adres (struct tuple4 addr)
{
  static char buf[256];
  strcpy (buf, int_ntoa (addr.saddr));
  sprintf (buf + strlen (buf), ",%i,", addr.source);
  strcat (buf, int_ntoa (addr.daddr));
  sprintf (buf + strlen (buf), ",%i", addr.dest);
  return buf;
}

void tcp_callback (struct tcp_stream *a_tcp, void ** this_time_not_needed)
{
  char buf[1024];
  strcpy (buf, adres (a_tcp->addr)); // we put conn params into buf
  if (a_tcp->nids_state == NIDS_JUST_EST)
    {
    // connection described by a_tcp is established
    // here we decide, if we wish to follow this stream
    // sample condition: if (a_tcp->addr.dest!=23) return;
    // in this simple app we follow each stream, so..
      a_tcp->client.collect++; // we want data received by a client
      a_tcp->server.collect++; // and by a server, too
      a_tcp->server.collect_urg++; // we want urgent data received by a
                                   // server
#ifdef WE_WANT_URGENT_DATA_RECEIVED_BY_A_CLIENT
      a_tcp->client.collect_urg++; // if we don't increase this value,
                                   // we won't be notified of urgent data
                                   // arrival
#endif
      fprintf (stderr, "%s established\n", buf);
      return;
    }
  if (a_tcp->nids_state == NIDS_CLOSE)
    {
      // connection has been closed normally
      fprintf (stderr, "%s closing\n", buf);
      return;
    }
  if (a_tcp->nids_state == NIDS_RESET)
    {
      // connection has been closed by RST
      fprintf (stderr, "%s reset\n", buf);
      return;
    }

  if (a_tcp->nids_state == NIDS_DATA)
    {
      // new data has arrived; gotta determine in what direction
      // and if it's urgent or not

      struct half_stream *hlf;

      if (a_tcp->server.count_new_urg)
      {
        // new byte of urgent data has arrived 
        strcat(buf,"(urgent->)");
        buf[strlen(buf)+1]=0;
        buf[strlen(buf)]=a_tcp->server.urgdata;
        write(1,buf,strlen(buf));
        return;
      }
      // We don't have to check if urgent data to client has arrived,
      // because we haven't increased a_tcp->client.collect_urg variable.
      // So, we have some normal data to take care of.
      if (a_tcp->client.count_new)
    {
          // new data for the client
      hlf = &a_tcp->client; // from now on, we will deal with hlf var,
                                // which will point to client side of conn
      strcat (buf, "(<-)"); // symbolic direction of data
    }
      else
    {
      hlf = &a_tcp->server; // analogical
      strcat (buf, "(->)");
    }
    fprintf(stderr,"%s",buf); // we print the connection parameters
                              // (saddr, daddr, sport, dport) accompanied
                              // by data flow direction (-> or <-)

   write(2,hlf->data,hlf->count_new); // we print the newly arrived data

    }
  return ;
}

int main ()
{
  // here we can alter libnids params, for instance:
  // nids_params.n_hosts=256;
  if (!nids_init ())
  {
    fprintf(stderr,"%s\n",nids_errbuf);
    exit(1);
  }
  nids_register_tcp (tcp_callback);
  nids_run ();
  return 0;
}

基礎的libnids結構體和方法

正是時候系統的介紹libnids的結構體了。正如之前提到的,他們都在nids.h中聲明。

  • 四元組(源IP,源端口號,目的IP,目的端口號)
 struct tuple4 // TCP connection parameters
   {
   unsigned short source,dest; // client and server port numbers
   unsigned long saddr,daddr;  // client and server IP addresses
   };
  • half_stream
 struct half_stream // structure describing one side of a TCP connection
   {
   char state;            // socket state (ie TCP_ESTABLISHED )
   char collect;          // if >0, then data should be stored in "data" buffer; else data                                // flowing in this direction will be ignored have a look at                                 // examples/sniff.c for an example how one can use this field
   char collect_urg;      // analogically, determines if to collect urgent data
   char * data;           // buffer for normal data
   unsigned char urgdata; // one-byte buffer for urgent data
   int count;             // how many bytes has been appended to buffer "data" since the                                  // creation of a connection 
   int offset;            // offset (in data stream) of first byte stored in 
                          // the "data" buffer; additional explanations follow
   int count_new;         // how many bytes were appended to "data" buffer 
                          // last (this) time; if == 0, no new data arrived 
   char count_new_urg;    // if != 0, new data arrived

   ... // other fields are auxiliary for libnids

   };
  • tcp_stream
struct tcp_stream
   {
   struct tuple4 addr;   // connections params (saddr, daddr, sport, dport)
   char nids_state;                  // logical state of the connection
   struct half_stream client,server; // structures describing client and
                                     // server side of the connection 
   ...                               // other fields are auxiliary for libnids
   };

​ 在上面的實例程序中,回調函數tcp_callback輸出顯示hlf->data緩衝區中的數據到標準輸出設備上。這些數據在 tcp_callback函數返回後,由libnids自動釋放這些數據所佔用的內存空間。同時,hlf->offset字段將增加被丟棄數據的字 節數,而新接收到的數據則存放到”data”緩衝區的起始處。
如果在其它應用中不進行如上例的操作(例如,數據處理過程至少需要N個字節的輸入數據,而libnids只接收到的數據字節數count_new

 void nids_discard(struct tcp_stream * a_tcp, int num_bytes)

此時,當回調函數tcp_callback返回後linids將”data”緩衝區的前num_bytes字節數據,同時計算調整offset字段的數值,並將剩餘數據移動到緩衝區的起始處。

如果始終不調用nids_discard()函數(如上面實例),hlf->data緩衝區中將包含hlf->count_new字節數據。 通常情況下,在hlf->data緩衝區中的數據字節數等於hlf->count - hlf->offset。
有了nids_discard()函數,程序員就不必拷貝接收到的數據到另外的緩衝區中,hlf->data緩衝區將總是儘可能保存足夠的數據。然後,有時會有保留數據包特定數據的需要。例如,我們希望能監測到針對wu-ftpd服務器的”CWD”溢出攻擊,就需要跟蹤檢查ftp客戶端發送的 “CWD”命令。此時就需要tcp_callback回調函數具有第二個參數了。此參數是某TCP連接私有數據的指針。處理過程如下:

 void tcp_callback_2 (struct tcp_stream * a_tcp, struct conn_param **ptr)
   {
   if (a_tcp->nids_state==NIDS_JUST_EST)
   {
        struct conn_param * a_conn;
    if the connection is uninteresting, return;
        a_conn=malloc of some data structure
        init of a_conn
        *ptr=a_conn // this value will be passed to tcp_callback_2 in future
                    // calls
        increase some of "collect" fields
        return;
   }
   if (a_tcp->nids_state==NIDS_DATA)
   {
    struct conn_param *current_conn_param=*ptr;
        using current_conn_param and the newly received data from the net
        we search for attack signatures, possibly modyfying
        current_conn_param  
        return ;
   }

nids_register_tcp和nids_register_ip*函數可被任意次調用。在同一個TCP連接中使用兩種不同的回調函數是允許的。
libnids庫定義了一個全局變量結構nids_params,其聲明如下:

struct nids_prm
   {
   int n_tcp_streams; // size of the hash table used for storing structures 
                      // tcp_stream; libnis will follow no more than 
                      // 3/4 * n_tcp_streams connections simultaneously
                      // default value: 1040. If set to 0, libnids will
                      // not assemble TCP streams.
   int n_hosts;       // size of the hash table used for storing info on
                      // IP defragmentation; default value: 256
   char * filename;   // capture filename from which to read packets; 
                      // file must be in libpcap format and device must
                      // be set to NULL; default value: NULL
   char * device;     // interface on which libnids will listen for packets;
                      // default value == NULL, in which case device will
                      // be determined by call to pcap_lookupdev; special
                      // value of "all" results in libnids trying to
                      // capture packets on all interfaces (this works only
                      // with Linux kernel > 2.2.0 and libpcap >= 0.6.0); 
                      // see also doc/LINUX 
   int sk_buff_size;  // size of struct sk_buff, a structure defined by
                      // Linux kernel, used by kernel for packets queuing. If 
                      // this parameter has different value from 
                      // sizeof(struct sk_buff), libnids can be bypassed
                      // by attacking resource managing of libnis (see TEST
                      // file). If you are paranoid, check sizeof(sk_buff)
                      // on the hosts on your network, and correct this 
                      // parameter. Default value: 168
   int dev_addon;     // how many bytes in structure sk_buff is reserved for
                      // information on net interface; if dev_addon==-1, it
                      // will be corrected during nids_init() according to
                      // type of the interface libnids will listen on.
                      // Default value: -1.
   void (*syslog)();  // see description below the nids_params definition
   int syslog_level;  // if nids_params.syslog==nids_syslog, then this field
                      // determines loglevel used by reporting events by
                      // system daemon syslogd; default value: LOG_ALERT
   int scan_num_hosts;// size of hash table used for storing info on port
                      // scanning; the number of simultaneuos port
              // scan attempts libnids will detect. if set to 
              // 0, port scanning detection will be turned
              // off. Default value: 256.
   int scan_num_ports;// how many TCP ports has to be scanned from the same
                      // source. Default value: 10.
   int scan_delay;    // with no more than scan_delay milisecond pause
                      // between two ports, in order to make libnids report
                      // portscan attempt. Default value: 3000
   void (*no_mem)();  // called when libnids runs out of memory; it should
                      // terminate the current process
   int (*ip_filter)(struct ip*);  // this function is consulted when an IP
                      // packet arrives; if ip_filter returns non-zero, the
                      // packet is processed, else it is discarded. This way
                      // one can monitor traffic directed at selected hosts
                      // only, not entire subnet. Default function 
                      // (nids_ip_filter) always returns 1
   char *pcap_filter; // filter string to hand to pcap(3). Default is
              // NULL. be aware that this applies to the
              // link-layer, so filters like "tcp dst port 23"
              // will NOT correctly handle fragmented traffic; one
                      // should add "or (ip[6:2] & 0x1fff != 0)" to process
                      // all fragmented packets
   int promisc;       // if non-zero, the device(s) libnids reads packets
                      // from will be put in promiscuous mode. Default: 1
   int one_loop_less; // disabled by default; see the explanation
   int pcap_timeout;  // the "timeout" parameter to pcap_open_live
                      // 1024 (ms) by default ; change to a lower value
                      // if you want a quick reaction to traffic; this
                      // is present starting with libnids-1.20
   int multiproc;     // start ip defragmentation and tcp stream assembly in a 
                      // different thread parameter to a nonzero value and 
                      // compiling libnids in an environment where  glib-2.0 is 
                      // available enables libnids to use two different threads 
                      // - one for receiving IP fragments from libpcap, 
                      // and one, with lower priority, to process fragments, 
                      // streams and to notify callbacks. Preferrably using 
                      // nids_run() this behavior is invisible to the user.
                      // Using this functionality with nids_next() is quite
                      // useless since the thread must be started and stopped
                      // for every packet received.
                      // Also, if it is enabled, global variables (nids_last_pcap_header
                      // and nids_last_pcap_data) may not point to the
              // packet currently processed by a callback
   int queue_limit;   // limit on the number of packets to be queued;
                      // used only when multiproc=true; 20000 by default
   int tcp_workarounds; // enable (hopefully harmless) workarounds for some
                      // non-rfc-compliant TCP/IP stacks
   pcap_t *pcap_desc; // pcap descriptor 
   } nids_params;

​ nids_params的syslog字段缺省時指向nids_syslog函數,聲明如下:

void nids_syslog (int type, int errnum, struct ip *iph, void *data);

​ s_params.syslog函數用於記錄異常情況,如端口掃描企圖,無效TCP頭標誌等。該字段應指向自定義的日誌處理函數。函數nids_syslog(在libnids.c中定義)可以作爲例子闡述怎樣解碼傳遞到nids_params.syslog的數據。nids_syslog()函數向系統守護服務syslogd發送日誌消息,但是這個函數不考慮傳輸速率和磁盤剩餘空間(這也是它應該被替換的原因)。

​ 如果對UDP數據報文感興趣,應該聲明:

void udp_callback(struct tuple4 * addr, char * buf, int len, struct ip * iph);

然後註冊它:

nids_register_udp(udp_callback)

​ addr包含地址信息,buf指向UPD報文攜帶的數據,len時數據長度,iph指向攜帶UDP報文的IP報文,校驗碼是已查證的。

Misc的技巧

作爲一個很好的toy function:

void nids_killtcp(struct tcp_stream * a_tcp)

它通過發送一個RST片段a_tcp來終止tcp連接。

因爲RST片段的序列號是某一個tcp窗口提供的,包含MS05-019補丁的windows系統不會因收到這樣一條報文而終止連接,所以現在libnids發送兩條報文——附加的報文有最小的(預期的)序列號。不幸的是,它是不可靠的:如果信號擁堵,程序就會有延遲,獲得的預期序列號就是錯誤的。

通常來講,把發送RST報文作爲防禦措施是不可靠的設計,除非不部署在在線NIDS(網絡入侵偵測系統),或者NIDS(基於網絡的入侵防護系統),這就是爲什麼稱呼它toy function的原因。


使用nids_run()有一個缺點:應用程序將完全由數據包驅動(運行)。有時需要在沒有數據包到達時也能處理一些任務,作爲nids_run()函數的替代,程序員可使用如下函數:

int nids_next()

​ 此函數將調用pcap_next()函數,而不是pcap_loop()函數,也就是說,它只處理一個包。如果沒有包到來,這是進程就會sleep,nids_next()函數成功時返回1,出錯時返回0,且nids_errbuf緩衝區存放相應錯誤消息。

​ 典型地,當使用nids_next()函數時,應用程序調用I/O複用函數select()阻塞,並在read fd_set中呈現socket監聽fd。fd可通過如下函數獲得:

int nids_getfd()

​ 成功時返回一個文件描述字,出錯時返回-1,且nids_errbuf緩衝區存放相應錯誤消息。

相似的函數:

int nids_dispatch(int cnt)

是pcap_dispatch的封裝,當我們需要區分返回數據(ie 文件末尾或錯誤)時使用nids_dispatch比使用nids_next更好。


下面是跳過某些包的校驗和檢驗的幾條原因:

  1. 如今,一些NIC驅動能夠爲流出的包計算校驗和。在這種情況下,流向libpcap的包含有未計算的校驗和。所以,你可能不想檢驗這些包的校驗和。
  2. 爲了提高效率。

爲了讓libnids知道哪些包需要校驗,你應該分配一個struct nids_chksum_ctl (defined in nids.h)的數組:

struct nids_chksum_ctl
{       u_int netaddr;
        u_int mask;
        u_int action;
    /* reserved fields */
};

然後用下面的函數註冊它:

nids_register_chksum_ctl(struct nids_chksum_ctl *, int);

第二個參數表明了數組的長度。

校驗函數會對數組的元素一個接一個的校驗,如果源地址SRCIP滿足下列條件

(SRCIP&chksum_ctl_array[i].mask)==chksum_ctl_array[i].netaddr

如果”action” 是NIDS_DO_CHKSUM, 這個報文就會接受校驗; 如果”action” 是 NIDS_DONT_CHKSUM, 這個報文就不會接受校驗. 如果報文沒有匹配的到任何的數組元素,默認進行校驗。

對所有包跳過檢驗:

struct nids_chksum_ctl temp;

temp.netaddr = inet_addr("0.0.0.0");
temp.mask = inet_addr("0.0.0.0");
temp.action = NIDS_DONT_CHKSUM;
//保證(SRCIP&chksum_ctl_array[i].mask)==chksum_ctl_array[i].netaddr
nids_register_chksum_ctl(&temp,1);

使用示例可以參照samples/chksum_ctl.c


nids.h定義了constants NIDS_MAJOR (1) 和NIDS_MINOR (21), 可以在運行時指定libnids的版本. Nids.h之前也定義HAVE_NEW_PCAP 但在1.19之後被廢棄了。


Typically, data carried by a tcp stream can be divided into protocol-dependent records (say, lines of input). A tcp callback can receive an amount of data, which contains more then one record. Therefore, a tcp callback should iterate its protocol parsing routine over the whole amount of data received. This adds complexity to the code.

If

nids_params.one_loop_less

is non-zero, libnids behaviour changes slightly. If a callback consumes some (but not all) of newly arrived data, libnids calls it immediately again. Only non-processed data remain in the buffer, and

rcv->count_new

is decreased appropriately. Thus, a callback can process only one record at the time - libnids will call it again, until no new data remain or no data can be processed. Unfortunately, this behaviour introduces horrible semantics problems in case of 2+ callbacks reading the same half of a tcp stream. Therefore, if

nids_params.one_loop_less

is non-zero, you are not allowed to attach two or more callbacks to the same half of tcp stream. Unfortunately, the existing interface is unable to propagate the error to the callback - therefore, you must watch it yourself. You have been warned.


最後一個包的pcap header爲

extern struct pcap_pkthdr *nids_last_pcap_header;

可以獲得timestamp, 更好的準確性,或者保存到系統調用。


其他使用libnids的應用可以在examples中找到。

在1.21中的更新

1.21帶來了bug修復, 優化和一些新的特色,提供了更多的extern變量和函數。

nids_last_pcap_data 是最新的pcap包的數據, 類似nids_last_pcap_header 來獲取最新數據報頭。

nids_linkoffset是一個用來計算當前pcap設備鏈路層和網絡層偏移量的外部變量。It is useful to reconstruct PCAP frames from IP defragmented packets which you get in your ip_func (see [chapter on IP defragmentation](#IP defragmentation)) by copying the same amount of bytes from the beginning of nids_last_pcap_data representing the link layer, like this:

void ip_callback(struct ip *pkt, int len)
{
  u_char                        *frame;
  struct pcap_pkthdr            ph;

  frame = malloc(len + nids_linkoffset);
  memcpy(frame, nids_last_pcap_data, nids_linkoffset);
  memcpy(frame + nids_linkoffset, pkt, len);
  ph.ts = nids_last_pcap_header->ts;
  ph.caplen = ph.len = len + nids_linkoffset;
  pcap_dump(nids_params.pcap_desc, &ph, frame);
  free(frame);
}

In versions prior to 1.21 it was only possible to give libnids a device or file name and have it take total control over libpcap operations when using nids_run() or nids_next(). Now, with nids_params.pcap_desc it is possible to have your pcap_handler outside libnids and choose which frames you want to be processed by libnids (e.g. only TCP packets to keep track of TCP connections whilst this is not your only objective); all you have to do is copy your pointer to the pcap_t structure (returned by pcap_open_live(), pcap_open_dead() or pcap_open_offline()) to nids_params.pcap_desc and call nids_pcap_handler(), normally with the same parameters as your own pcap_handler (the one you registered with pcap_dispatch() or pcap_loop()) was called with. NOTE: since libnids cannot know when you are finished if you interactively pass packets to it with nids_pcap_handler(), you must tell it when to free the allocated resources by calling nids_exit().

nids_params.tcp_workarounds is a new libnids runtime option which can be used to enable extra checks for faulty implementations of TCP such as the ones which allow connections to be closed despite the fact that there should be retransmissions for lost packets first, thus violating section 3.5 of RFC 793. In those cases, and if this option is non-zero, libnids will set the NIDS_TIMED_OUT state for TCP connections that were savagely closed.

nids_find_tcp_stream() is a new external function that can be used to find the corresponding tcp_stream structure for a given pointer to a tuple4 structure.

nids_free_tcp_stream() is a new external function that can be used for example to force libnids into not following a TCP stream anymore. BEWARE! Calling nids_free_tcp_stream() from inside one of your registered tcp_callbacks on a TCP stream that is already in a closing state (NIDS_CLOSE, NIDS_TIMED_OUT, NIDS_RESET or NIDS_EXITING) will result in a double free (because libnids will call nids_free_tcp_stream() internally when your tcp_callback returns) and your program will crash.

nids_unregister_ip_frag(), nids_unregister_ip(), nids_unregister_udp() and nids_unregister_tcp() are new external functions that can be used to unregister callbacks previous registed with the corresponding nids_register_*(), at any time.

tcp_stream.user is a new field in the structure passed to TCP callbacks. It is similar to their void **param argument, except that it is global to all the TCP callbacks for the same stream, whereas param is specific to each callback.

FAQ

  • Q.1 對於某個鏈接,我的tcp回調函數只能獲取服務器發送的數據?
    A.1 You probably run a libnids app on a host that is the client side of X; and your NIC driver offloads checksums computing to the hardware. So, when libnids sees packets sent by the client, their checksum is not computed, and they are dropped. See the API.html file on the description of the nids_register_chksum_ctl(), and configure libnids app to skip checksum verification of packets sent by the host you run libnids on.

  • Q.2 如何使libnids檢測已經建立的TCP連接

    A.2 計劃有但是沒有實現; it would be unreliable, due to the fact that some crucial information (like TCP window scale) is present only in SYN packets. If you really need this functionality, you can try the included libnids-track-established.patch, prepared by Alon Bar-Lev; of course, the responsibility is yours.

運行安裝包中的示例代碼

示例代碼在安裝文件下的sample下,我的測試環境是centos7,安裝包中的sample無法正確執行,需要對Makefile文件進行更改。在命令行執行pkg-config --cflags --libs glib-2.0,根據執行結果修改Makefile中的一些參數。我修改後的Makefile。


srcdir      = .


CC      = gcc
CFLAGS      = -g -O2 -D_BSD_SOURCE
LDFLAGS     = 

PCAP_CFLAGS = -I/usr/include/pcap
PCAPLIB     = -lpcap

LNET_CFLAGS = -D_BSD_SOURCE -D__BSD_SOURCE -D__FAVOR_BSD -DHAVE_NET_ETHERNET_H
LNETLIB     = -lnet

GLIB_CFLAGS = -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include

LIBS_CFLAGS = -I../src $(PCAP_CFLAGS) $(LNET_CFLAGS) $(GLIB_CFLAGS) -fno-builtin-exit -fno-builtin-strcpy -fno-builtin-strlen -fno-builtin-strcat -fno-builtin-malloc
LIBS        = -L../src -lnids $(PCAPLIB) $(LNETLIB) -lgthread-2.0 -lnsl -pthread -lglib-2.0 -fno-builtin-exit
GLIB        = pkg-config --cflags --libs glib-2.0

.c.o:
    $(CC) -c $(CFLAGS) -I. $(LIBS_CFLAGS) $<

all: overflows printall sniff
static shared: all

overflows: overflows.o
    $(CC) -o $@ overflows.o $(LDFLAGS) $(LIBS) 

printall: printall.o
    $(CC) -o $@ printall.o $(LDFLAGS) $(LIBS)

sniff: sniff.o
    $(CC) -o $@ sniff.o $(LDFLAGS) $(LIBS)

static shared install installshared:
    @true

clean:
    rm -f *.o *~ overflows printall sniff

# EOF
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章