bool tok_ip_cidr(const char *s, char *ip, int *cidr) {
    static const char    *delim_ = "/";
    char                 *ip_cidr_ = NULL;
    char                 *tmp_ = NULL;
    char                 *block_ = NULL;
    size_t               block_size_ = 0;
    int                  i_ = 0;
    bool                 ret_ = false;

    // 没有 CIDR 标识的网络地址,比如 8.8.8.8,使用默认 CIDR
    // 8.8.8.8 == 8.8.8.8/32
    if (validate_ipv4_address(s)) {
        strcpy(ip, s);
        *cidr = DEFAULT_CIDR;
        return true;
    }

    ip_cidr_ = (char*) kmalloc(strlen(s) + NULL_BYTE_SIZE, GFP_ATOMIC);
    strcpy(ip_cidr_, s);
    tmp_ = ip_cidr_;

    // strsep 会将第一个参数指向 NULL,导致内存无法释放。所以,使用临时指针
    while (NULL != (block_ = strsep(&tmp_, delim_))) {
        ++i_;
        block_size_ = strlen(block_);

        if (i_ == 1) {
            if (!validate_ipv4_address(block_))
                break;

            strcpy(ip, block_);
            continue;
        }

        if (i_ == 2) {
            sscanf(block_, "%d", &(*cidr));
            ret_ = validate_cidr(*cidr);
            break;
        }
    }  // end of while

    kfree(ip_cidr_);
    return ret_;
}
/*
   Function: parse_command_line_args
   Purpose : Validates command line arguments.
   Input   : argc, argv, capture interface, server ip and filter file strings.
   Return  : returns -1 on error, mode of operation on success.
*/
int parse_command_line_args(int argc, char *argv[], char *capture_device, char *event_filename, char *server_ip_address, char *filter_file)
{
   int retval = 0;
   char timestr[100];
   int tlen;

   tlen = get_time_string(timestr, 99);

   memset(capture_device, 0, FL_PATH_MAX_LENGTH);
   memset(event_filename, 0, FL_PATH_MAX_LENGTH);
   memset(server_ip_address, 0, FL_PATH_MAX_LENGTH);
   memset(filter_file, 0, FL_PATH_MAX_LENGTH);
   strncpy(event_filename, EVENT_FILE, strlen(EVENT_FILE)); /* the default event file name */
   strncpy(capture_device, "eth0", 4);
   strncpy(server_ip_address, "127.0.0.1", 9); /* Default server on the local machine */

   if (tlen > 0) /* Build the default event filename, fineline-events-YYYYMMDD-HHMMSS.fle */
   {
      strncat(event_filename, timestr, tlen);
   }
   else
   {
      print_log_entry("parse_command_line_args() <WARNING> Invalid time string.\n");
   }
   strncat(event_filename, EVENT_FILE_EXT, 4);

   if (argc < 2)
   {
	   print_log_entry("parse_command_line_args(): invalid arguments < 2\n");
      return(-1);
   }
   else
   {
      int i;
      for (i = 1; i < argc; i++)
      {
         if (strncmp(argv[i], "-c", 2) == 0)
         {
            retval = retval | FL_CAPTURE_INPUT; /* Capture packets on a network interface */
         }
         if (strncmp(argv[i], "-t", 2) == 0)
         {
            retval = retval | FL_UNIFIED2_INPUT; /* Tail Unified2 log files */
         }
         else if (strncmp(argv[i], "-w", 2) == 0)
         {
            retval = retval | FL_FILE_OUT; /* Create FineLine event file */
         }
         else if (strncmp(argv[i], "-g", 2) == 0)
         {
            retval = retval | FL_GUI_OUT; /* Send event records to Fineline server */
         }
         else if (strncmp(argv[i], "-b", 2) == 0)
         {
            retval = retval | FL_FILE_OUT | FL_GUI_OUT; /* Create FineLine event file and send events to server */
         }
         else if (strncmp(argv[i], "-o", 2) == 0)
         {
            /* Optional FineLine event file name to use for output of event records */
            if ((i+1) < argc)
            {
               printf("parse_command_line_args() <INFO> FineLine event file: %s\n", argv[i+1]);
               strncpy(event_filename, argv[i+1], strlen(argv[i+1]));
            }
            else
            {
               print_log_entry("parse_command_line_args() <ERROR> Missing event file name.\n");
               return(-1);
            }
         }
         else if (strncmp(argv[i], "-i", 2) == 0)
         {
            /* Network interface for packet capture */
            if ((i+1) < argc)
            {
               printf("parse_command_line_args() <INFO> Network interface: %s\n", argv[i+1]);
               strncpy(capture_device, argv[i+1], strlen(argv[i+1]));
            }
            else
            {
               print_log_entry("parse_command_line_args() <ERROR> Missing network interface.\n");
               return(-1);
            }
         }
		   else if (strncmp(argv[i], "-a", 2) == 0)
		   {
			   if ((i+1) < argc)
			   {
			      /* IP address of the Fineline NST Server. */
			      printf("parse_command_line_args() <INFO> Server IP address: %s\n", argv[i+1]);
               strncpy(server_ip_address, argv[i+1], strlen(argv[i+1]));
			      if (validate_ipv4_address(server_ip_address) < 0)
			      {
				      print_log_entry("parse_command_line_args() <ERROR> Invalid Ifl4 address.\n");
                  return(-1);
			      }
			   }
			   else
			   {
			      print_log_entry("parse_command_line_args() <ERROR> Missing Ifl4 address.\n");
               return(-1);
			   }
		   }
         else if (strncmp(argv[i], "-f", 2) == 0)
         {
            /* Filter file name  */
            if ((i+1) < argc)
            {
               printf("parse_command_line_args() <INFO> Filter file: %s\n", argv[i+1]);
               strncpy(filter_file, argv[i+1], strlen(argv[i+1]));
			      retval = retval | FL_FILTER_ON;
            }
            else
            {
               print_log_entry("parse_command_line_args() <ERROR> Missing filter file name.\n");
               return(-1);
            }
         }
      }
   }

   print_log_entry("parse_command_line_args() <INFO> Finished processing command line arguments.\n");

   return(retval);
}
/*
   Function: parse_command_line_args
   Purpose : Validates command line arguments.
   Input   : argc, argv, log file and db file handles.
   Return  : mode of operation and database file handle if required.
*/
int parse_command_line_args(int argc, char *argv[], char *fl_event_filename, char *in_file, char *gui_ip_address, char *filter_file)
{
   int retval = 0;
   int input_file_specified = 0;
   char timestr[100];
   int tlen;

   tlen = get_time_string(timestr, 99);

   memset(fl_event_filename, 0, FL_PATH_MAX);
   memset(in_file, 0, FL_PATH_MAX);
   memset(filter_file, 0, FL_PATH_MAX);
   strncpy(fl_event_filename, EVENT_FILE, strlen(EVENT_FILE)); /* the default event filename */

   if (tlen > 0)
   {
      strncat(fl_event_filename, timestr, tlen);
   }
   else
   {
      print_log_entry("parse_command_line_args() <WARNING> Invalid time string.\n");
   }
   strncat(fl_event_filename, EVENT_FILE_EXT, 4);

   if (argc < 2)
   {
	  print_log_entry("parse_command_line_args(): invalid arguments < 2\n");
      return(-1);
   }
   else
   {
      int i;
      for (i = 1; i < argc; i++)
      {
         if (strncmp(argv[i], "-w", 2) == 0)
         {
            retval = retval | FL_FILE_OUT; /* Create FineLine event file */
         }
         else if (strncmp(argv[i], "-s", 2) == 0)
         {
            retval = retval | FL_GUI_OUT; /* Send event records to GUI */
         }
         else if (strncmp(argv[i], "-b", 2) == 0)
         {
            retval = retval | FL_FILE_OUT | FL_GUI_OUT; /* Create FineLine event file and send to GUI */
         }
         else if (strncmp(argv[i], "-o", 2) == 0)
         {
            /* FineLine event file name to use for output of event records */
            if ((i+1) < argc)
            {
               printf("parse_command_line_args() <INFO> FineLine event file: %s\n", argv[i+1]);
               strncpy(fl_event_filename, argv[i+1], strlen(argv[i+1]));
            }
            else
            {
               print_log_entry("parse_command_line_args() <ERROR> Missing event file name.\n");
               return(-1);
            }
         }
         else if (strncmp(argv[i], "-i", 2) == 0)
         {
            /* Windows event file name to use for input */
            if ((i+1) < argc)
            {
               printf("parse_command_line_args() <INFO> Windows event file: %s\n", argv[i+1]);
               strncpy(in_file, argv[i+1], strlen(argv[i+1]));
			      input_file_specified = 1;
			      if (strstr(in_file, ".evtx"))
			      {
				      retval = retval | FL_EVTX_IN;
			      }
			      else if (strstr(in_file, ".evt"))
			      {
				      retval = retval | FL_EVT_IN;
			      }
               else
               {
                  print_log_entry("parse_command_line_args() <ERROR> Unknown event file type.\n");
                  return(-1);
               }
            }
            else
            {
               print_log_entry("parse_command_line_args() <ERROR> Missing Windows event file name.\n");
               return(-1);
            }
         }
		   else if (strncmp(argv[i], "-a", 2) == 0)
		   {
			   if ((i+1) < argc)
			   {
			      printf("parse_command_line_args() <INFO> GUI IP address: %s\n", argv[i+1]);
               strncpy(gui_ip_address, argv[i+1], strlen(argv[i+1]));
			      if (validate_ipv4_address(gui_ip_address) < 0)
			      {
				      print_log_entry("parse_command_line_args() <ERROR> Invalid IPv4 address.\n");
                  return(-1);
			      }
			   }
			   else
			   {
			      print_log_entry("parse_command_line_args() <ERROR> Missing IPv4 address.\n");
               return(-1);
			   }
		   }
         else if (strncmp(argv[i], "-f", 2) == 0)
         {
            /* Filter event file name */
            if ((i+1) < argc)
            {
               printf("parse_command_line_args() <INFO> Filter file: %s\n", argv[i+1]);
               strncpy(filter_file, argv[i+1], strlen(argv[i+1]));
			      retval = retval | FL_FILTER_ON;
            }
            else
            {
               print_log_entry("parse_command_line_args() <ERROR> Missing filter file name.\n");
               return(-1);
            }
         }
      }
   }

   /* Check for input file on command line, if none then do the live system log. */
   if (input_file_specified == 0)
   {
	   strncpy(in_file, EVENT_LOG_PATH, strlen(EVENT_LOG_PATH));
	   strncat(in_file, PATH_SEPARATOR, strlen(PATH_SEPARATOR));
	   strncat(in_file, SECURITY_LOG_FILE, strlen(SECURITY_LOG_FILE));
	   retval = retval | FL_EVTX_IN;
	   print_log_entry("parse_command_line_args() <INFO> Default input file = Security.evtx\n");
   }

   print_log_entry("parse_command_line_args() <INFO> Finished processing command line arguments.\n");

   return(retval);
}