void OS_ReadMSG_analysisd(int m_queue) #endif { int i; char msg[OS_MAXSTR +1]; Eventinfo *lf; RuleInfo *stats_rule = NULL; /* Null to global currently pointers */ currently_rule = NULL; /* Initiating the logs */ OS_InitLog(); /* Initiating the integrity database */ SyscheckInit(); /* Initializing Rootcheck */ RootcheckInit(); /* Initializing host info */ HostinfoInit(); /* Creating the event list */ OS_CreateEventList(Config.memorysize); /* Initiating the FTS list */ if(!FTS_Init()) { ErrorExit(FTS_LIST_ERROR, ARGV0); } /* Initialize the Accumulator */ if(!Accumulate_Init()) { merror("accumulator: ERROR: Initialization failed"); exit(1); } /* Starting the active response queues */ if(Config.ar) { /* Waiting the ARQ to settle .. */ sleep(3); #ifndef LOCAL if(Config.ar & REMOTE_AR) { if((arq = StartMQ(ARQUEUE, WRITE)) < 0) { merror(ARQ_ERROR, ARGV0); /* If LOCAL_AR is set, keep it there */ if(Config.ar & LOCAL_AR) { Config.ar = 0; Config.ar|=LOCAL_AR; } else { Config.ar = 0; } } else { verbose(CONN_TO, ARGV0, ARQUEUE, "active-response"); } } #else /* Only for LOCAL_ONLY installs */ if(Config.ar & REMOTE_AR) { if(Config.ar & LOCAL_AR) { Config.ar = 0; Config.ar|=LOCAL_AR; } else { Config.ar = 0; } } #endif if(Config.ar & LOCAL_AR) { if((execdq = StartMQ(EXECQUEUE, WRITE)) < 0) { merror(ARQ_ERROR, ARGV0); /* If REMOTE_AR is set, keep it there */ if(Config.ar & REMOTE_AR) { Config.ar = 0; Config.ar|=REMOTE_AR; } else { Config.ar = 0; } } else { verbose(CONN_TO, ARGV0, EXECQUEUE, "exec"); } } } debug1("%s: DEBUG: Active response Init completed.", ARGV0); /* Getting currently time before starting */ c_time = time(NULL); /* Starting the hourly/weekly stats */ if(Start_Hour() < 0) Config.stats = 0; else { /* Initializing stats rules */ stats_rule = zerorulemember( STATS_MODULE, Config.stats, 0,0,0,0,0,0); if(!stats_rule) { ErrorExit(MEM_ERROR, ARGV0); } stats_rule->group = "stats,"; stats_rule->comment = "Excessive number of events (above normal)."; } /* Doing some cleanup */ memset(msg, '\0', OS_MAXSTR +1); /* Initializing the logs */ { lf = (Eventinfo *)calloc(1,sizeof(Eventinfo)); if(!lf) ErrorExit(MEM_ERROR, ARGV0); lf->year = prev_year; strncpy(lf->mon, prev_month, 3); lf->day = today; if(OS_GetLogLocation(lf) < 0) { ErrorExit("%s: Error allocating log files", ARGV0); } Free_Eventinfo(lf); } debug1("%s: DEBUG: Startup completed. Waiting for new messages..",ARGV0); if(Config.custom_alert_output) debug1("%s: INFO: Custom output found.!",ARGV0); /* Daemon loop */ while(1) { lf = (Eventinfo *)calloc(1,sizeof(Eventinfo)); /* This shouldn't happen .. */ if(lf == NULL) { ErrorExit(MEM_ERROR,ARGV0); } DEBUG_MSG("%s: DEBUG: Waiting for msgs - %d ", ARGV0, (int)time(0)); /* Receive message from queue */ if((i = OS_RecvUnix(m_queue, OS_MAXSTR, msg))) { RuleNode *rulenode_pt; /* Getting the time we received the event */ c_time = time(NULL); /* Default values for the log info */ Zero_Eventinfo(lf); /* Checking for a valid message. */ if(i < 4) { merror(IMSG_ERROR, ARGV0, msg); Free_Eventinfo(lf); continue; } /* Message before extracting header */ DEBUG_MSG("%s: DEBUG: Received msg: %s ", ARGV0, msg); /* Clean the msg appropriately */ if(OS_CleanMSG(msg, lf) < 0) { merror(IMSG_ERROR,ARGV0, msg); Free_Eventinfo(lf); continue; } /* Msg cleaned */ DEBUG_MSG("%s: DEBUG: Msg cleanup: %s ", ARGV0, lf->log); /* Currently rule must be null in here */ currently_rule = NULL; /** Checking the date/hour changes **/ /* Update the hour */ if(thishour != __crt_hour) { /* Search all the rules and print the number * of alerts that each one fired. */ DumpLogstats(); thishour = __crt_hour; /* Check if the date has changed */ if(today != lf->day) { if(Config.stats) { /* Update the hourly stats (done daily) */ Update_Hour(); } if(OS_GetLogLocation(lf) < 0) { ErrorExit("%s: Error allocating log files", ARGV0); } today = lf->day; strncpy(prev_month, lf->mon, 3); prev_year = lf->year; } } /* Incrementing number of events received */ hourly_events++; /*** Running decoders ***/ /* Integrity check from syscheck */ if(msg[0] == SYSCHECK_MQ) { hourly_syscheck++; if(!DecodeSyscheck(lf)) { /* We don't process syscheck events further */ goto CLMEM; } /* Getting log size */ lf->size = strlen(lf->log); } /* Rootcheck decoding */ else if(msg[0] == ROOTCHECK_MQ) { if(!DecodeRootcheck(lf)) { /* We don't process rootcheck events further */ goto CLMEM; } lf->size = strlen(lf->log); } /* Host information special decoder */ else if(msg[0] == HOSTINFO_MQ) { if(!DecodeHostinfo(lf)) { /* We don't process hostinfo events further */ goto CLMEM; } lf->size = strlen(lf->log); } /* Run the general Decoders */ else { /* Getting log size */ lf->size = strlen(lf->log); DecodeEvent(lf); } /* Run accumulator */ if( lf->decoder_info->accumulate == 1 ) { lf = Accumulate(lf); } /* Firewall event */ if(lf->decoder_info->type == FIREWALL) { /* If we could not get any information from * the log, just ignore it */ hourly_firewall++; if(Config.logfw) { if(!FW_Log(lf)) { goto CLMEM; } } } /* We only check if the last message is * duplicated on syslog. */ else if(lf->decoder_info->type == SYSLOG) { /* Checking if the message is duplicated */ if(LastMsg_Stats(lf->full_log) == 1) goto CLMEM; else LastMsg_Change(lf->full_log); } /* Stats checking */ if(Config.stats) { if(Check_Hour() == 1) { void *saved_rule = lf->generated_rule; char *saved_log; /* Saving previous log */ saved_log = lf->full_log; lf->generated_rule = stats_rule; lf->full_log = __stats_comment; /* alert for statistical analysis */ if(stats_rule->alert_opts & DO_LOGALERT) { __crt_ftell = ftell(_aflog); if(Config.custom_alert_output) { OS_CustomLog(lf,Config.custom_alert_output_format); } else { OS_Log(lf); } } /* Set lf to the old values */ lf->generated_rule = saved_rule; lf->full_log = saved_log; } } /* Checking the rules */ DEBUG_MSG("%s: DEBUG: Checking the rules - %d ", ARGV0, lf->decoder_info->type); /* Looping all the rules */ rulenode_pt = OS_GetFirstRule(); if(!rulenode_pt) { ErrorExit("%s: Rules in an inconsistent state. Exiting.", ARGV0); } do { if(lf->decoder_info->type == OSSEC_ALERT) { if(!lf->generated_rule) { goto CLMEM; } /* We go ahead in here and process the alert. */ currently_rule = lf->generated_rule; } /* The categories must match */ else if(rulenode_pt->ruleinfo->category != lf->decoder_info->type) { continue; } /* Checking each rule. */ else if((currently_rule = OS_CheckIfRuleMatch(lf, rulenode_pt)) == NULL) { continue; } /* Ignore level 0 */ if(currently_rule->level == 0) { break; } /* Checking ignore time */ if(currently_rule->ignore_time) { if(currently_rule->time_ignored == 0) { currently_rule->time_ignored = lf->time; } /* If the currently time - the time the rule was ignored * is less than the time it should be ignored, * leave (do not alert again). */ else if((lf->time - currently_rule->time_ignored) < currently_rule->ignore_time) { break; } else { currently_rule->time_ignored = lf->time; } } /* Pointer to the rule that generated it */ lf->generated_rule = currently_rule; /* Checking if we should ignore it */ if(currently_rule->ckignore && IGnore(lf)) { /* Ignoring rule */ lf->generated_rule = NULL; break; } /* Checking if we need to add to ignore list */ if(currently_rule->ignore) { AddtoIGnore(lf); } /* Log the alert if configured to ... */ if(currently_rule->alert_opts & DO_LOGALERT) { __crt_ftell = ftell(_aflog); if(Config.custom_alert_output) { OS_CustomLog(lf,Config.custom_alert_output_format); } else { OS_Log(lf); } } /* Log to prelude */ #ifdef PRELUDE if(Config.prelude) { if(Config.prelude_log_level <= currently_rule->level) { OS_PreludeLog(lf); } } #endif /* Log to zeromq */ #ifdef ZEROMQ_OUTPUT if(Config.zeromq_output) { zeromq_output_event(lf); } #endif /* Log to Picviz */ if (Config.picviz) { OS_PicvizLog(lf); } /* Execute an active response */ if(currently_rule->ar) { int do_ar; active_response **rule_ar; rule_ar = currently_rule->ar; while(*rule_ar) { do_ar = 1; if((*rule_ar)->ar_cmd->expect & USERNAME) { if(!lf->dstuser || !OS_PRegex(lf->dstuser,"^[a-zA-Z._0-9@?-]*$")) { if(lf->dstuser) merror(CRAFTED_USER, ARGV0, lf->dstuser); do_ar = 0; } } if((*rule_ar)->ar_cmd->expect & SRCIP) { if(!lf->srcip || !OS_PRegex(lf->srcip, "^[a-zA-Z.:_0-9-]*$")) { if(lf->srcip) merror(CRAFTED_IP, ARGV0, lf->srcip); do_ar = 0; } } if((*rule_ar)->ar_cmd->expect & FILENAME) { if(!lf->filename) { do_ar = 0; } } if(do_ar) { OS_Exec(&execdq, &arq, lf, *rule_ar); } rule_ar++; } } /* Copy the structure to the state memory of if_matched_sid */ if(currently_rule->sid_prev_matched) { if(!OSList_AddData(currently_rule->sid_prev_matched, lf)) { merror("%s: Unable to add data to sig list.", ARGV0); } else { lf->sid_node_to_delete = currently_rule->sid_prev_matched->last_node; } } /* Group list */ else if(currently_rule->group_prev_matched) { i = 0; while(i < currently_rule->group_prev_matched_sz) { if(!OSList_AddData( currently_rule->group_prev_matched[i], lf)) { merror("%s: Unable to add data to grp list.",ARGV0); } i++; } } OS_AddEvent(lf); break; }while((rulenode_pt = rulenode_pt->next) != NULL); /* If configured to log all, do it */ if(Config.logall) OS_Store(lf); /* Cleaning the memory */ CLMEM: /* Only clear the memory if the eventinfo was not * added to the stateful memory * -- message is free inside clean event -- */ if(lf->generated_rule == NULL) Free_Eventinfo(lf); } else { free(lf); } } return; }
/* GlobalConf v0.2: 2005/03/03 * v0.2: Changing to support the new OS_XML */ int Read_Global(XML_NODE node, void *configp, void *mailp) { int i = 0; /* White list size */ int white_size = 1; int hostname_white_size = 1; int mailto_size = 1; /* XML definitions */ char *xml_mailnotify = "email_notification"; char *xml_logall = "logall"; char *xml_integrity = "integrity_checking"; char *xml_rootcheckd = "rootkit_detection"; char *xml_hostinfo = "host_information"; char *xml_picviz = "picviz_output"; char *xml_picviz_socket = "picviz_socket"; char *xml_prelude = "prelude_output"; char *xml_prelude_profile = "prelude_profile"; char *xml_prelude_log_level = "prelude_log_level"; char *xml_zeromq_output = "zeromq_output"; char *xml_zeromq_output_uri = "zeromq_uri"; char *xml_stats = "stats"; char *xml_memorysize = "memory_size"; char *xml_white_list = "white_list"; char *xml_compress_alerts = "compress_alerts"; char *xml_custom_alert_output = "custom_alert_output"; char *xml_emailto = "email_to"; char *xml_emailfrom = "email_from"; char *xml_emailidsname = "email_idsname"; char *xml_smtpserver = "smtp_server"; char *xml_mailmaxperhour = "email_maxperhour"; #ifdef GEOIP /* GeoIP */ char *xml_geoip_db_path = "geoip_db_path"; char *xml_geoip6_db_path = "geoip6_db_path"; #endif _Config *Config; MailConfig *Mail; Config = (_Config *)configp; Mail = (MailConfig *)mailp; /* Getting right white_size */ if(Config && Config->white_list) { os_ip **ww; ww = Config->white_list; while(*ww != NULL) { white_size++; ww++; } } /* Getting right white_size */ if(Config && Config->hostname_white_list) { OSMatch **ww; ww = Config->hostname_white_list; while(*ww != NULL) { hostname_white_size++; ww++; } } /* Getting mail_to size */ if(Mail && Mail->to) { char **ww; ww = Mail->to; while(*ww != NULL) { mailto_size++; ww++; } } while(node[i]) { if(!node[i]->element) { merror(XML_ELEMNULL, ARGV0); return(OS_INVALID); } else if(!node[i]->content) { merror(XML_VALUENULL, ARGV0, node[i]->element); return(OS_INVALID); } else if(strcmp(node[i]->element, xml_custom_alert_output) == 0) { if(Config) { Config->custom_alert_output= 1; os_strdup(node[i]->content, Config->custom_alert_output_format); } } /* Mail notification */ else if(strcmp(node[i]->element, xml_mailnotify) == 0) { if(strcmp(node[i]->content, "yes") == 0) { if(Config) Config->mailnotify = 1; if(Mail) Mail->mn = 1; } else if(strcmp(node[i]->content, "no") == 0) { if(Config) Config->mailnotify = 0; if(Mail) Mail->mn = 0; } else { merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); return(OS_INVALID); } } /* Picviz support */ else if(strcmp(node[i]->element, xml_picviz) == 0) { if(strcmp(node[i]->content, "yes") == 0) { if(Config) Config->picviz = 1; } else if(strcmp(node[i]->content, "no") == 0) { if(Config) Config->picviz = 0; } else { merror(XML_VALUEERR,ARGV0,node[i]->element, node[i]->content); return(OS_INVALID); } } else if(strcmp(node[i]->element, xml_picviz_socket) == 0) { if(Config) { os_strdup(node[i]->content, Config->picviz_socket); } } /* Prelude support */ else if(strcmp(node[i]->element, xml_prelude) == 0) { if(strcmp(node[i]->content, "yes") == 0) { if(Config) Config->prelude = 1; } else if(strcmp(node[i]->content, "no") == 0) { if(Config) Config->prelude = 0; } else { merror(XML_VALUEERR,ARGV0,node[i]->element, node[i]->content); return(OS_INVALID); } } else if(strcmp(node[i]->element, xml_prelude_profile) == 0) { if(Config) { Config->prelude_profile = strdup(node[i]->content); } } else if(strcmp(node[i]->element, xml_prelude_log_level) == 0) { if(!OS_StrIsNum(node[i]->content)) { merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); return(OS_INVALID); } if(Config) { Config->prelude_log_level = atoi(node[i]->content); } } /* ZeroMQ output */ else if(strcmp(node[i]->element, xml_zeromq_output) == 0) { if(strcmp(node[i]->content, "yes") == 0) { if(Config) Config->zeromq_output = 1; } else if(strcmp(node[i]->content, "no") == 0) { if(Config) Config->zeromq_output = 0; } else { merror(XML_VALUEERR,ARGV0,node[i]->element, node[i]->content); return(OS_INVALID); } } else if(strcmp(node[i]->element, xml_zeromq_output_uri) == 0) { if(Config) { Config->zeromq_output_uri = strdup(node[i]->content); } } /* Log all */ else if(strcmp(node[i]->element, xml_logall) == 0) { if(strcmp(node[i]->content, "yes") == 0) { if(Config) Config->logall = 1;} else if(strcmp(node[i]->content, "no") == 0) {if(Config) Config->logall = 0;} else { merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); return(OS_INVALID); } } /* compress alerts */ else if(strcmp(node[i]->element, xml_compress_alerts) == 0) { /* removed from here -- compatility issues only */ } /* Integrity */ else if(strcmp(node[i]->element, xml_integrity) == 0) { if(!OS_StrIsNum(node[i]->content)) { merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); return(OS_INVALID); } if(Config) { Config->integrity = atoi(node[i]->content); } } /* rootcheck */ else if(strcmp(node[i]->element, xml_rootcheckd) == 0) { if(!OS_StrIsNum(node[i]->content)) { merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); return(OS_INVALID); } if(Config) { Config->rootcheck = atoi(node[i]->content); } } /* hostinfo */ else if(strcmp(node[i]->element, xml_hostinfo) == 0) { if(!OS_StrIsNum(node[i]->content)) { merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); return(OS_INVALID); } if(Config) { Config->hostinfo = atoi(node[i]->content); } } /* stats */ else if(strcmp(node[i]->element, xml_stats) == 0) { if(!OS_StrIsNum(node[i]->content)) { merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); return(OS_INVALID); } if(Config) { Config->stats = atoi(node[i]->content); } } else if(strcmp(node[i]->element, xml_memorysize) == 0) { if(!OS_StrIsNum(node[i]->content)) { merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); return(OS_INVALID); } if(Config) { Config->memorysize = atoi(node[i]->content); } } /* whitelist */ else if(strcmp(node[i]->element, xml_white_list) == 0) { /* Windows do not need it */ #ifndef WIN32 char *ip_address_regex = "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}/?" "([0-9]{0,2}|[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})$"; if(Config && OS_PRegex(node[i]->content, ip_address_regex)) { white_size++; Config->white_list = realloc(Config->white_list, sizeof(os_ip *)*white_size); if(!Config->white_list) { merror(MEM_ERROR, ARGV0); return(OS_INVALID); } os_calloc(1, sizeof(os_ip), Config->white_list[white_size -2]); Config->white_list[white_size -1] = NULL; if(!OS_IsValidIP(node[i]->content, Config->white_list[white_size -2])) { merror(INVALID_IP, ARGV0, node[i]->content); return(OS_INVALID); } } /* Adding hostname */ else if(Config) { hostname_white_size++; Config->hostname_white_list = realloc(Config->hostname_white_list, sizeof(OSMatch *)*hostname_white_size); if(!Config->hostname_white_list) { merror(MEM_ERROR, ARGV0); return(OS_INVALID); } os_calloc(1, sizeof(OSMatch), Config->hostname_white_list[hostname_white_size -2]); Config->hostname_white_list[hostname_white_size -1] = NULL; if(!OSMatch_Compile( node[i]->content, Config->hostname_white_list[hostname_white_size -2], 0)) { merror(REGEX_COMPILE, ARGV0, node[i]->content, Config->hostname_white_list [hostname_white_size -2]->error); return(-1); } } #endif } /* For the email now * email_to, email_from, idsname, smtp_Server and maxperhour. * We will use a separate structure for that. */ else if(strcmp(node[i]->element, xml_emailto) == 0) { #ifndef WIN32 if(!OS_PRegex(node[i]->content, "[a-zA-Z0-9\\._-]+@[a-zA-Z0-9\\._-]")) { merror("%s: ERROR: Invalid Email address: %s.", ARGV0, node[i]->content); return(OS_INVALID); } #endif if(Mail) { mailto_size++; Mail->to = realloc(Mail->to, sizeof(char *)*mailto_size); if(!Mail->to) { merror(MEM_ERROR, ARGV0); return(OS_INVALID); } os_strdup(node[i]->content, Mail->to[mailto_size - 2]); Mail->to[mailto_size - 1] = NULL; } } else if(strcmp(node[i]->element, xml_emailfrom) == 0) { if(Mail) { if(Mail->from) { free(Mail->from); } os_strdup(node[i]->content, Mail->from); } } else if(strcmp(node[i]->element, xml_emailidsname) == 0) { if(Mail) { if(Mail->idsname) { free(Mail->idsname); } os_strdup(node[i]->content, Mail->idsname); } } else if(strcmp(node[i]->element, xml_smtpserver) == 0) { #ifndef WIN32 if(Mail && (Mail->mn)) { Mail->smtpserver = OS_GetHost(node[i]->content, 5); if(!Mail->smtpserver) { merror(INVALID_SMTP, ARGV0, node[i]->content); return(OS_INVALID); } } #endif } else if(strcmp(node[i]->element, xml_mailmaxperhour) == 0) { if(Mail) { if(!OS_StrIsNum(node[i]->content)) { merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); return(OS_INVALID); } Mail->maxperhour = atoi(node[i]->content); if((Mail->maxperhour <= 0) || (Mail->maxperhour > 9999)) { merror(XML_VALUEERR,ARGV0,node[i]->element,node[i]->content); return(OS_INVALID); } } } #ifdef GEOIP /* GeoIP v4 DB location */ else if(strcmp(node[i]->element, xml_geoip_db_path) == 0) { if(Config) { os_strdup(node[i]->content, Config->geoip_db_path); } } /* GeoIP v6 DB location */ else if(strcmp(node[i]->element, xml_geoip6_db_path) == 0) { if(Config) { os_strdup(node[i]->content, Config->geoip6_db_path); } } #endif else { merror(XML_INVELEM, ARGV0, node[i]->element); return(OS_INVALID); } i++; } return(0); }
/* os_strings: List the strings of a binary and * check if the regex given is there. */ int os_string(char *file, char *regex) { int ch, cnt; unsigned char *C; unsigned char *bfr; char line[OS_SIZE_1024 +1]; char *buf; EXEC *head; os_strings oss; /* Return didn't match */ if(!file || !regex) { return(0); } /* Allocating for the buffer */ bfr = calloc(STR_MINLEN + 2, sizeof(char *)); if (!bfr) { merror(MEM_ERROR, ARGV0); return(0); } /* Opening the file */ oss.fp = fopen(file, "r"); if(!oss.fp) { free(bfr); return(0); } /* cleaning the line */ memset(line, '\0', OS_SIZE_1024 +1); /* starting .. (from old strings.c) */ oss.foff = 0; oss.head_len = 0; oss.read_len = -1; head = (EXEC *)oss.hbfr; if ((oss.head_len = read(fileno(oss.fp), head, sizeof(EXEC))) == -1) { oss.head_len = 0; oss.read_len = -1; } else if (oss.head_len == sizeof(EXEC) && !N_BADMAG(*head)) { oss.foff = N_TXTOFF(*head); if (fseek(stdin, oss.foff, SEEK_SET) == -1) { oss.read_len = -1; } else { #ifdef AIX oss.read_len = head->tsize + head->dsize; #else oss.read_len = head->a_text + head->a_data; #endif } oss.head_len = 0; } else { oss.hcnt = 0; } /* Read the file and perform the regex comparison */ for (cnt = 0; (ch = os_getch(&oss)) != EOF;) { if (ISSTR(ch)) { if (!cnt) C = bfr; *C++ = ch; if (++cnt < STR_MINLEN) continue; strncpy(line, (char *)bfr, STR_MINLEN +1); buf = line; buf+=strlen(line); while ((ch = os_getch(&oss)) != EOF && ISSTR(ch)) { if(cnt < OS_SIZE_1024) { *buf = (char)ch; buf++; } else { *buf = '\0'; break; } cnt++; } *buf = '\0'; if(OS_PRegex(line, regex)) { if(oss.fp) fclose(oss.fp); free(bfr); return(1); } } cnt = 0; } if(oss.fp) fclose(oss.fp); free(bfr); return(0); }
/** int OS_IsValidIP(char *ip) * Validates if an ip address is in the right * format. * Returns 0 if doesn't match or 1 if it is an ip or 2 an ip with cidr. * ** On success this function may modify the value of ip_address */ int OS_IsValidIP(const char *ip_address, os_ip *final_ip) { unsigned int nmask = 0; char *tmp_str; /* Can't be null */ if(!ip_address) { return(0); } /* Assigning the ip address */ if(final_ip) { os_strdup(ip_address, final_ip->ip); } if(*ip_address == '!') { ip_address++; } #ifndef WIN32 /* checking against the basic regex */ if(!OS_PRegex(ip_address, ip_address_regex)) { if(strcmp(ip_address, "any") != 0) { return(0); } } #else if(strcmp(ip_address, "any") != 0) { const char *tmp_ip; int dots = 0; tmp_ip = ip_address; while(*tmp_ip != '\0') { if((*tmp_ip < '0' || *tmp_ip > '9') && *tmp_ip != '.' && *tmp_ip != '/') { /* Invalid ip */ return(0); } if(*tmp_ip == '.') dots++; tmp_ip++; } if(dots < 3 || dots > 6) return(0); } #endif /* Getting the cidr/netmask if available */ tmp_str = strchr(ip_address,'/'); if(tmp_str) { int cidr; struct in_addr net; *tmp_str = '\0'; tmp_str++; /* Cidr */ if(strlen(tmp_str) <= 2) { cidr = atoi(tmp_str); if((cidr >= 0) && (cidr <= 32)) { if(!_mask_inited) _init_masks(); nmask = _netmasks[cidr]; nmask = htonl(nmask); } else { return(0); } } /* Full netmask */ else { /* Init the masks */ if(!_mask_inited) _init_masks(); if(strcmp(tmp_str, "255.255.255.255") == 0) { nmask = htonl(_netmasks[32]); } else { if((nmask = inet_addr(ip_address)) <= 0) { return(0); } } } if((net.s_addr = inet_addr(ip_address)) <= 0) { if(strcmp("0.0.0.0", ip_address) == 0) { net.s_addr = 0; } else { return(0); } } if(final_ip) { final_ip->ip_address = net.s_addr & nmask; final_ip->netmask = nmask; } tmp_str--; *tmp_str = '/'; return(2); } /* No cidr available */ else { struct in_addr net; nmask = 32; if(strcmp("any", ip_address) == 0) { net.s_addr = 0; nmask = 0; } else if((net.s_addr = inet_addr(ip_address)) <= 0) { return(0); } if(final_ip) { final_ip->ip_address = net.s_addr; if(!_mask_inited) _init_masks(); final_ip->netmask = htonl(_netmasks[nmask]); } /* Ip without cidr */ if(nmask) { return(1); } return(2); } /* Should never reach here */ //return(0); }