我是靠谱客的博主 爱笑秋天,最近开发中收集的这篇文章主要介绍网络安全工具开发函数库介绍之三——libnids,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

网络安全工具开发函数库介绍之三——libnids
 
 发布日期: 2000-7-18 
 内容:
 --------------------------------------------------------------------------------
  
 网络安全工具开发函数库介绍之三——libnids
 
 作者:backend <backend@nsfocus.com>
               <http://www.nsfocus.com>
               
 日期:2000-07-16
 
 
 <<< 续前 >>>
 
 ---[[ libnids ]]------------------------------------------
 
 
 一、简介
 
     libnids 的英文意思是 Network Intrusion Detect System library,即网络入侵监测系统函数库。它是在前面介绍的两种C函 数接口库libnet和libpcap的基础上开发的,封装了开发NIDS所需的许多通用型函数。linids提供的接口函数监视流经本地的所有网络通 信,检查数据包等。除此之外,还具有重组TCP数据段、处理IP分片包和监测TCP端口扫描的功能。利用libnids接口函数库,NIDS开发者不需要 再编写底层的网络处理代码,只需专注于NIDS本身功能的实现即可。
     libnids支持Linux、Solaris和*BSD系统平台,目前最新版本为1.13。
 
 
 二、IP分片数据包
 
     为了使libnids能接收所有的IP数据包(包括分片包、畸形包等),程序员需要定义如下的回调函数:
 
         void ip_frag_func(struct ip * a_packet)
 
 在调用nids_init()函数初始化后,使用nids的函数进行注册:
 
         nids_register_ip_frag(ip_frag_func);
 
 这样回调函数ip_frag_func会在适当的时候由libnids调用,参数a_packet指针将指向接收到的数据报。
     类似地,如果仅接收目标主机会接受的数据包(如非碎片包、重组包或头部校验正确的数据包等),需要定义如下回调函数:
 
         void ip_func(struct ip * a_packet)
 
 然后注册:
 
         nids_register_ip(ip_func);
 
 
 三、TCP数据流重组
 
     要接收TCP流在交换的数据,必须定义如下回调函数:
 
         void tcp_callback(struct tcp_stream * ns, void ** param)
 
 tcp_stream结构提供了一个TCP连接的所有信息。例如,它包含了客户端与服务器端的half_stream结构。下文会对该结构的字段进行解释。
     tcp_stream结构有一个名为nids_state的字段。此字段的数值将决定tcp_callback的操作。
     
     (a) ns->nids_state==NIDS_JUST_EST时,ns表示一个刚刚建立的连接。
         tcp_callback可以据此决定是否对该连接的后续数据进行检查。如
         需要检查,tcp_callback回调函数将通知libnids它希望接收哪些
         数据(如到客户端的数据、到服务器端的数据、到客户端的紧急数
         据或到服务器端的紧急数据等),然后返回。
     (b) ns->nids_state==NIDS_DATA时,表示ns连接接收到新的数据。
         half_stream结构中的缓冲区用于存放这些数据。
     (c) nids_state字段为其它数值(NIDS_CLOSE、NIDS_RESET、
         NIDS_TIMEOUT)时,表示该连接已经关闭了。tcp_callback函数应
         释放相关资源。
 
 
 四、一个简单的实例
 
     下面的源代码是一个非常简单的程序,它将libnids捕获的所有TCP连接交换的数据输出显示到标准输出设备上。
 
 -----------------------BEGINING OF CODE--------------------------------
 
 #include "nids.h"
 #include <string.h>
 #include <stdio.h>
 
 extern char * inet_ntoa(unsigned long);
 
 // tuple4结构包含了TCP连接两端的IP地址和端口,以下函数将它们转换为字符串
 // 格式,如10.0.0.1,1024, 10.0.0.2,23
 char *
 adres (struct tuple4 addr)
 {
   static char buf[256];
   strcpy (buf, inet_ntoa (addr.saddr));
   sprintf (buf + strlen (buf), ",%i,", addr.source);
   strcat (buf, inet_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)
     {
     // a_tcp所定义的连接已经建立。此处可视程序需要添加额外
     // 的判断处理。如if (a_tcp->addr.dest != 23) return;表
     // 示不处理目标端口为23的数据包。
     // 本例需要处理(显示)所有数据包,故:
       a_tcp->client.collect++; // 需要处理客户端接收的数据
       a_tcp->server.collect++; // 和服务器端接收的数据
       a_tcp->server.collect_urg++; // 需要处理服务器端接收的紧急数据
 #ifdef WE_WANT_URGENT_DATA_RECEIVED_BY_A_CLIENT
       a_tcp->client.collect_urg++; // 需要处理客户端接收的紧急数据
                                    // (打开编译选项才有效)
 #endif
       fprintf (stderr, "%s established/n", buf);
       return;
     }
   if (a_tcp->nids_state == NIDS_CLOSE)
     {
       // TCP连接正常关闭
       fprintf (stderr, "%s closing/n", buf);
       return;
     }
   if (a_tcp->nids_state == NIDS_RESET)
     {
       // TCP连接因RST数据包而关闭
       fprintf (stderr, "%s reset/n", buf);
       return;
     }
 
   if (a_tcp->nids_state == NIDS_DATA)
     {
       // 接收到新数据,下面判断决定是否显示
 
       struct half_stream *hlf;
 
       if (a_tcp->server.count_new_urg)
       {
         // 服务器端接收的紧急数据 
         strcat(buf,"(urgent->)");
         buf[strlen(buf)+1]=0;
         buf[strlen(buf)]=a_tcp->server.urgdata;
         write(1,buf,strlen(buf));
         return;
       }
 
 #ifdef WE_WANT_URGENT_DATA_RECEIVED_BY_A_CLIENT
       if (a_tcp->client.count_new_urg)
       {
         // 客户端接收的紧急数据 
         strcat(buf,"(urgent->)");
         buf[strlen(buf)+1]=0;
         buf[strlen(buf)]=a_tcp->server.urgdata;
         write(1,buf,strlen(buf));
         return;
       }
 #endif
 
       if (a_tcp->client.count_new)
         {
           // 客户端接收的数据
           hlf = &a_tcp->client; // 准备显示客户端接收的数据
           strcat (buf, "(<-)"); // 指示数据流方向
         }
       else
         {
           hlf = &a_tcp->server; // 准备显示服务器端接收的数据
           strcat (buf, "(->)"); // 指示数据流方向
         }
     fprintf(stderr,"%s",buf); // 首先输出显示连接双方的IP地址、端口
                               // 和数据流方向
 
    write(2,hlf->data,hlf->count_new); // 输出显示接收到的新数据
       
     }
   return ;
 }
 
 int 
 main ()
 {
   // 此处可自定义libnids的全局变量,如:
   // nids_params.n_hosts=256;
   if (!nids_init () )
   {
         fprintf(stderr,"%s/n",nids_errbuf);
         exit(1);
   }
   nids_register_tcp (tcp_callback);
   nids_run ();
   // NOT REACHED
   return 0;
 }
 
 ---------------------------END OF CODE------------------------------------  
 
 
 五、libnids的数据结构及接口函数
 
     libnids库的所有数据结构及接口函数都在"nids.h"头文件中声明。
 
    struct tuple4 // TCP连接参数
    {
    unsigned short source,dest; // 客户端和服务器端的端口号
    unsigned long saddr,daddr;  // 客户端和服务器端的IP地址
    };
 
 
    struct half_stream // TCP连接一端的数据结构
    {
    char state;            // 套接字状态(如TCP_ESTABLISHED)
    char collect;          // 如果大于0,则保存其数据到缓冲区中,否则忽略
    char collect_urg;      // 如果大于0,则保存紧急数据,否则忽略
    char * data;           // 正常数据的缓冲区
    unsigned char urgdata; // 紧急数据缓冲区
    int count;             // 自从连接建立以来保存到"data"缓冲区的数据字节
                           // 数总和
    int offset;            // 保存到"data"缓冲区的首字节数据偏移量
    int count_new;         // 最近一次接收到的数据字节数;如果为0,则无数
                           // 到达
    char count_new_urg;    // 如果非0,表示有新的紧急数据到达
 
    ... // libnids库使用的辅助字段
 
    };
 
 
    struct tcp_stream
    {
    struct tuple4 addr;   // TCP连接参数(saddr, daddr, sport, dport)
    char nids_state;                  // TCP连接的逻辑状态
    struct half_stream client,server; // 描述客户端与服务器端的数据结构
    ...                               // libnids库使用的辅助字段
    };
 
     在 上面的实例程序中,回调函数tcp_callback输出显示hlf->data缓冲区中的数据到标准输出设备上。这些数据在 tcp_callback函数返回后,由libnids自动释放这些数据所占用的内存空间。同时,hlf->offset字段将增加被丢弃数据的字 节数,而新接收到的数据则存放到"data"缓冲区的起始处。
     如果在其它应用中不进行如上例的操作(例如,数据处理过程至少需要N个字节的输入数据,而libnids只接收到的数据字节数count_new<N),则需要在tcp_callback函数返回前调用如下函数:
 
         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; // 存放tcp_stream结构的hash表大小。
                       // 缺省值:1024
    int n_hosts;       // 存放IP分片信息的hash表大小
                       // 缺省值:256
    char * device;     // libnids监听的接口设备名
                       // 缺省值 == NULL,即由pcap_lookupdev函数确定
    int sk_buff_size;  // (Linux内核)sk_buff结构大小
                       // 缺省值:168
    int dev_addon;     // sk_buff为网络接口保留的字节数
                       // 如果dev_addon==-1,则由nids_init函数确定
                       // 缺省值:-1
    void (*syslog)();  // 日志函数指针
    int syslog_level;  // 如果nids_params.syslog==nids_syslog,则此字段值
                       // 将确定日志等级loglevel
                       // 缺省值:LOG_ALERT
    int scan_num_hosts;// 存放端口扫描信息的hash表大小。
                       // 如果为0,则关闭端口扫描监测功能。
                       // 缺省值:256
    int scan_num_ports;// 来自同一IP地址所扫描的TCP端口数上限
                       // 缺省值:10
    int scan_delay;    // 在两次端口扫描中的间隔时间上限(毫秒)
                       // 缺省值:3000
    void (*no_mem)();  // 内存不足时被调用,此时应终止当前进程
    int (*ip_filter)(struct ip*);  // 当接收到一个IP数据包时调用。如返回值
                                   // 非零,则处理该数据包,否则忽略。
                                   // 缺省为(nids_ip_filter)且总返回1
    char *pcap_filter; // 传递给pcap过滤器的字符串。
                       // 缺省值:NULL
    } nids_params;
 
     nids_params的syslog字段缺省时指向nids_syslog函数,声明如下:
 
         void nids_syslog (int type, int errnum, struct ip *iph, void *data);
 
     nids_params.syslog函数用于记录异常情况,如端口扫描企图,无效TCP头标志等。该字段应指向自定义的日志处理函数。nids_syslog()仅作为一个例子。nids_syslog()函数向系统守护服务syslogd发送日志消息。
 
     使用nids_run有一个缺陷:应用程序将完全由数据包驱动(运行)。有时需要在没有数据包到达时也能处理一些任务,则作为nids_run()函数的替代,程序员可使用如下函数:
 
         int nids_next()
 
 此函数将调用pcap_next()函数(而不是pcap_loop()函数)。(详细资料请参阅《网络安全工具开发函数库介绍之二 ——libpcap》。) nids_next()函数成功时返回1,出错时返回0,且nids_errbuf缓冲区存放相应错误消息。
     典型地,当使用nids_next()函数时,应用程序调用I/O复用函数select()阻塞,监听套接字fd在“读”描述字集合fd_set中设置。该套接字可通过如下函数获得:
 
         int nids_getfd()
 
 成功时返回一个文件描述字,出错时返回-1,且nids_errbuf缓冲区存放相应错误消息。
 
 
 ---[[ libnids应用实例 ]]----------------------------------
 
 1、nids_next()函数的应用
 
 ============================ cut here ============================
 
 /*
 This is an example how one can use nids_getfd() and nids_next() functions.
 You can replace printall.c‘s function main with this file.
 */
 
 #include <sys/time.h>
 #include <sys/types.h>
 #include <unistd.h>
 
 int
 main ()
 {
   // here we can alter libnids params, for instance:
   // nids_params.n_hosts=256;
   int fd;
   int time = 0;
   fd_set rset;
   struct timeval tv;
 
   if (!nids_init ())
   {
         fprintf(stderr,"%s/n",nids_errbuf);
         exit(1);
   }
   nids_register_tcp (tcp_callback);
   fd = nids_getfd ();
   for (;;)
     {
       tv.tv_sec = 1;
       tv.tv_usec = 0;
       FD_ZERO (&rset);
       FD_SET (fd, &rset);
       // add any other fd we need to take care of
       if (select (fd + 1, &rset, 0, 0, &tv))
         {
                 if (FD_ISSET(fd,&rset)  // need to test it if there are other
                                         // fd in rset
                         if (!nids_next ()) break;
         }
       else
         fprintf (stderr, "%i ", time++);
     }
   return 0;
 }
 
 ============================ cut here ============================
 
 2、Simple sniffer
 
 ============================ cut here ============================
 
 /*
    Copyright (c) 1999 Rafal Wojtczuk <nergal@avet.com.pl>. All rights reserved.
    See the file COPYING for license details.
 */
 
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <arpa/inet.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include "nids.h"
 
 #define LOG_MAX 100
 #define SZLACZEK "/n--------------------------------------------------/n"
 
 #define int_ntoa(x)     inet_ntoa(*((struct in_addr *)&x))
 
 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;
 }
 
 int logfd;
 void
 do_log (char *adres_txt, char *data, int ile)
 {
   write (logfd, adres_txt, strlen (adres_txt));
   write (logfd, data, ile);
   write (logfd, SZLACZEK, strlen (SZLACZEK));
 }
 
 void
 sniff_callback (struct tcp_stream *a_tcp, void **this_time_not_needed)
 {
   int dest;
   if (a_tcp->nids_state == NIDS_JUST_EST)
     {
       dest = a_tcp->addr.dest;
       if (dest == 21 || dest == 23 || dest == 110 || dest == 143 || dest == 513)
         a_tcp->server.collect++;
       return;
     }
   if (a_tcp->nids_state != NIDS_DATA)
     {
       // seems the stream is closing, log as much as possible
       do_log (adres (a_tcp->addr), a_tcp->server.data,
               a_tcp->server.count - a_tcp->server.offset);
       return;
     }
   if (a_tcp->server.count - a_tcp->server.offset < LOG_MAX)
     {
       // we haven‘t got enough data yet; keep all of it
       nids_discard (a_tcp, 0);
       return;
     }
     
   // enough data  
   do_log (adres (a_tcp->addr), a_tcp->server.data, LOG_MAX);
 
   // Now procedure sniff_callback doesn‘t want to see this stream anymore.
   // So, we decrease all the "collect" fields we have previously increased.
   // If there were other callbacks following a_tcp stream, they would still
   // receive data
   a_tcp->server.collect--;
 }
 
 
 int
 main ()
 {
   logfd = open ("./logfile", O_WRONLY | O_CREAT | O_TRUNC, 0600);
   if (logfd < 0)
     {
       perror ("opening ./logfile:");
       exit (1);
     }
   if (!nids_init ())
     {
       fprintf (stderr, "%s/n", nids_errbuf);
       exit (1);
     }
   nids_register_tcp (sniff_callback);
   nids_run ();
   return 0;
 }
 
 ============================ cut here ============================
 
 3、Wu-FTPd overflow attack detector
 
 ============================ cut here ============================
 
 /*
 Copyright (c) 1999 Rafal Wojtczuk <nergal@avet.com.pl>. All rights reserved.
 See the file COPYING for license details.
 */
 
 /* 
 This code attempts to detect attack against imapd (AUTHENTICATE hole) and
 wuftpd (creation of deep directory). This code is to ilustrate use of libnids;
 in order to improve readability, some simplifications were made, which enables
 an attacker to bypass this code (note, the below routines should be improved, 
 not libnids)
 */  
 
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <arpa/inet.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
 #include "nids.h"
 
 #define int_ntoa(x)     inet_ntoa(*((struct in_addr *)&x))
 
 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;
 }
 
 
 /*
 if we find a pattern AUTHENTICATE {an_int} in data stream sent to an imap 
 server, where an_int >1024, it means an buffer overflow attempt. We kill the 
 connection.
 */
 
 #define PATTERN "AUTHENTICATE {"
 #define PATLEN strlen(PATTERN)
 void
 detect_imap (struct tcp_stream *a_tcp)
 {
   char numbuf[30];
   int i, j, datalen, numberlen;
   struct half_stream *hlf;
   if (a_tcp->nids_state == NIDS_JUST_EST)
     {
       if (a_tcp->addr.dest == 143)
         {
           a_tcp->server.collect++;
           return;
         }
       else
         return;
     }
   if (a_tcp->nids_state != NIDS_DATA)
     return;
   hlf = &a_tcp->server;
   datalen = hlf->count - hlf->offset;
   if (datalen < PATLEN)
     {
       // we have too small amount of data to work on. Keep all data in buffer.
       nids_discard (a_tcp, 0);
       return;
     }
   for (i = 0; i <= datalen - PATLEN; i++)
     if (!memcmp (PATTERN, hlf->data + i, PATLEN)) //searching for a pattern
       break;
   if (i > datalen - PATLEN)
     {
       // retain PATLEN bytes in buffer
       nids_discard (a_tcp, datalen - PATLEN);
       return;
     }
   for (j = i + PATLEN; j < datalen; j++) // searching for a closing ‘}‘
     if (*(hlf->data + j) == ‘}‘)
       break;
   if (j > datalen)
     {
       if (datalen > 20)
         {
           //number too long, perhaps we should log it, too
         }
       return;
     }
   numberlen = j - i - PATLEN;
   memcpy (numbuf, hlf->data + i + PATLEN, numberlen); //numbuf contains
                                                       // AUTH argument
   numbuf[numberlen] = 0;
   if (atoi (numbuf) > 1024)
     {
       // notify admin
       syslog(nids_params.syslog_level,
       "Imapd exploit attempt, connection %s/n",adres(a_tcp->addr));
       // kill the connection
       nids_killtcp (a_tcp);
     }
   nids_discard (a_tcp, datalen - PATLEN);
   return;
 }
 
 // auxiliary structure, needed to keep current dir of ftpd daemon 
 struct supp
 {
   char *currdir;
   int last_newline;
 };
 
 // the below function adds "elem" string to "path" string, taking care of
 // ".." and multiple ‘/‘. If the resulting path is longer than 768, 
 // return value is 1, otherwise 0 
 int 
 add_to_path (char *path, char *elem, int len)
 {
 int plen;
 char * ptr;
   if (len > 768)
     return 1;
   if (len == 2 && elem[0] == ‘.‘ && elem[1] == ‘.‘)
     {
       ptr = rindex (path, ‘/‘);
       if (ptr != path)
         *ptr = 0;
     }
   else if (len > 0)
     {
       plen = strlen (path);
       if (plen + len + 1 > 768)
         return 1;
         if (plen==1)
         {
         strncpy(path+1,elem,len);
         path[1+len]=0;
         }
         else
         {
       path[plen] = ‘/‘;
       strncpy (path + plen + 1, elem, len);
       path[plen + 1 + len] = 0;
         }
     }
 return 0;
 }
 
 void
 do_detect_ftp (struct tcp_stream *a_tcp, struct supp **param_ptr)
 {
   struct supp *p = *param_ptr;
   int index = p->last_newline + 1;
   char *buf = a_tcp->server.data;
   int offset = a_tcp->server.offset;
   int n_bytes = a_tcp->server.count - offset;
   int path_index, pi2, index2, remcaret;
   for (;;)
     {
       index2 = index;
       while (index2 - offset < n_bytes && buf[index2 - offset] != ‘/n‘)
         index2++;
       if (index2 - offset >= n_bytes)
         break;
       if (!strncasecmp (buf + index - offset, "cwd ", 4))
         {
           path_index = index + 4;
           if (buf[path_index - offset] == ‘/‘)
             {
               strcpy (p->currdir, "/");
               path_index++;
             }
           for (;;)
             {
               pi2 = path_index;
               while (buf[pi2 - offset] != ‘/n‘ && buf[pi2 - offset] != ‘/‘)
                 pi2++;
                 if (buf[pi2-offset]==‘/n‘ && buf[pi2-offset-1]==‘/r‘)
                 remcaret=1;
                 else remcaret=0;
               if (add_to_path (p->currdir, buf + path_index-offset, pi2 - path_index-remcaret))
                 {
                   // notify admin
                   syslog(nids_params.syslog_level,
                   "Ftpd exploit attempt, connection %s/n",adres(a_tcp->addr)); 
                   nids_killtcp (a_tcp);
                   return;
                 }
               if (buf[pi2 - offset] == ‘/n‘)
                 break;
               path_index = pi2 + 1;
             }
         }
       index = index2 + 1;
     }
   p->last_newline = index - 1;
   nids_discard (a_tcp, index - offset);
 }
 
 void
 detect_ftpd (struct tcp_stream *a_tcp, struct supp **param)
 {
   if (a_tcp->nids_state == NIDS_JUST_EST)
     {
       if (a_tcp->addr.dest == 21)
         {
           struct supp *one_for_conn;
           a_tcp->server.collect++;
           one_for_conn = (struct supp *) malloc (sizeof (struct supp));
           one_for_conn->currdir = malloc (1024);
           strcpy (one_for_conn->currdir, "/");
           one_for_conn->last_newline = 0;
           *param=one_for_conn;
         }
       return;
     }
   if (a_tcp->nids_state != NIDS_DATA)
     {
       free ((*param)->currdir);
       free (*param);
       return;
     }
   do_detect_ftp (a_tcp, param);
 }
 
 int
 main ()
 {
   if (!nids_init ())
   {
         fprintf(stderr,"%s/n",nids_errbuf);
         exit(1);
   }
   nids_register_tcp (detect_imap);
   nids_register_tcp (detect_ftpd);
   nids_run ();
   return 0;
 }
 
 ============================ cut here ============================
 
 
 
 <<< 待续 >>>

最后

以上就是爱笑秋天为你收集整理的网络安全工具开发函数库介绍之三——libnids的全部内容,希望文章能够帮你解决网络安全工具开发函数库介绍之三——libnids所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部