/* ** Copyright (C) 2004-2007 by Carnegie Mellon University. ** ** @OPENSOURCE_HEADER_START@ ** ** Use of the SILK system and related source code is subject to the terms ** of the following licenses: ** ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013 ** ** NO WARRANTY ** ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE ** DELIVERABLES UNDER THIS LICENSE. ** ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie ** Mellon University, its trustees, officers, employees, and agents from ** all claims or demands made against them (and any related losses, ** expenses, or attorney's fees) arising out of, or relating to Licensee's ** and/or its sub licensees' negligent use or willful misuse of or ** negligent conduct or willful misconduct regarding the Software, ** facilities, or other rights or assistance granted by Carnegie Mellon ** University under this License, including, but not limited to, any ** claims of product liability, personal injury, death, damage to ** property, or violation of any laws or regulations. ** ** Carnegie Mellon University Software Engineering Institute authored ** documents are sponsored by the U.S. Department of Defense under ** Contract F19628-00-C-0003. Carnegie Mellon University retains ** copyrights in all material produced under this contract. The U.S. ** Government retains a non-exclusive, royalty-free license to publish or ** reproduce these documents, or allow others to do so, for U.S. ** Government purposes only pursuant to the copyright license under the ** contract clause at 252.227.7013. ** ** @OPENSOURCE_HEADER_END@ */ #include "silk.h" RCSIDENT("$SiLK: probeconf.c 7800 2007-07-06 15:32:43Z mthomas $"); #include "probeconf_priv.h" /* LOCAL DEFINES AND TYPEDEFS */ /* Maximum valid value for a port 2^16 - 1 */ #define PORT_VALID_MAX 0xFFFF /* Set ports to this invalid value initially */ #define PORT_NOT_SET 0xFFFFFFFF /* Value to use for remaining IPs to say that it hasn't been set */ #define REMAINDER_NOT_SET INT8_MAX /* a map between probe types and printable names */ static struct { const char *name; probe_enum_t value; } probe_type_name_map[PROBE_TYPE_COUNT] = { {"netflow", PROBE_ENUM_NETFLOW}, {"ipfix", PROBE_ENUM_IPFIX}, {"silk", PROBE_ENUM_SILK} }; /* a map between protocols and printable names */ static struct { const char *name; probe_proto_t value; } probe_protocol_name_map[PROBE_PROTOCOL_COUNT] = { {"sctp", PROBE_PROTO_SCTP}, {"tcp", PROBE_PROTO_TCP}, {"udp", PROBE_PROTO_UDP} }; /* LOCAL FUNCTIONS */ static void probeConfProbeDestroyAll(void); static void probeUpdateUniqueName(probe_def_t *probe); static int skProbeVerify(probe_def_t *probe); /* LOCAL VARIABLES */ /* The probes that have been created and verified */ static sk_vector_t *probe_vec = NULL; /* * ***** Flow Type ************************************************** * * * The probe is used to determine the flow-type---index into the * outFInfo[] array in silk_site_*.h---of a flow record (rwRec) read * from that probe. * * The skProbeDetermineFlowtype() function is defined in the * probeconf-<$SILK_SITE>.c file. * */ /* * ***** Probe configuration ************************************** */ /* setup the probes */ int probeConfSetup(void) { assert(PROBE_ENUM_INVALID == PROBE_TYPE_COUNT); assert(PROBE_PROTO_UNSET == PROBE_PROTOCOL_COUNT); if (NULL == probe_vec) { probe_vec = skVectorNew(sizeof(probe_def_t*)); if (NULL == probe_vec) { return -1; } } if (probeConfSiteSetup()) { return -1; } /* Confirm that number of flowtypes not greater than the size of * the sksite_filetypeFormats[] array. */ if (sksite_filetypeFormatCount <= sksiteFlowtypeGetMaxID()) { skAppPrintErr(("File formats not specified for some flowtypes.\n" "\tModify sksite_filetypeFormats[] in %s,\n" "\trecompile and try running again."), SILK_SITE_HEADER_NAME); abort(); } else if (sksite_filetypeFormatCount != 1u+sksiteFlowtypeGetMaxID()) { skAppPrintErr(("Warning: Number of flowtypes does not equal number\n" "\tof file formats in sksite_filetypeFormats[] in %s"), SILK_SITE_HEADER_NAME); } return 0; } /* destroy everything */ void probeConfTeardown(void) { /* clean up the parser */ probeConfParseTeardown(); /* destroy all probes */ probeConfProbeDestroyAll(); /* clean up any site-specific memory */ probeConfSiteTeardown(); } /* return a count of verified probes */ size_t probeConfProbeCount(void) { assert(probe_vec); return skVectorGetCount(probe_vec); } /* Verify that the probe is valid, and if it is, add it to the config * file list. */ int probeConfProbeVerify(probe_def_t *probe) { assert(probe); assert(probe_vec); if (0 != skProbeVerify(probe)) { return -1; } return skVectorAppendValue(probe_vec, &probe); } /* get a probe by position */ const probe_def_t *probeConfProbeGetByPosition(size_t probe_idx) { probe_def_t *p; assert(probe_vec); if (0 != skVectorGetValue(&p, probe_vec, probe_idx)) { return NULL; } return p; } /* return number of probes for the given sensor id. fill if out_vec * if provided. */ int probeConfGetProbesForSensor(sk_vector_t *out_vec, sensorID_t sid) { const probe_def_t *probe; int match_sid = 0; /* return value */ size_t count; size_t i; assert(probe_vec); /* check input */ if (sid == SK_INVALID_SENSOR) { return -1; } if (out_vec != NULL) { if (skVectorGetElementSize(out_vec) != sizeof(probe_def_t*)) { return -1; } } count = skVectorGetCount(probe_vec); for (i = 0; i < count; ++i) { skVectorGetValue(&probe, probe_vec, i); if (probe->sensor_id == sid) { ++match_sid; if (out_vec != NULL) { if (0 != skVectorAppendValue(out_vec, &probe)) { return -1; } } } } return match_sid; } /* return a probe having the given sensor-name and probe-name. */ const probe_def_t *probeConfGetProbeByName( const char *sensor_name, const char *probe_name) { const probe_def_t *probe; sensorID_t sid; size_t count; size_t i; assert(probe_vec); /* check input */ if (sensor_name == NULL || probe_name == NULL) { return NULL; } /* get the sensor id for named sensor */ sid = sksiteSensorLookup(sensor_name); if (sid == SK_INVALID_SENSOR) { return NULL; } /* loop over all probes until we find one with given name */ count = skVectorGetCount(probe_vec); for (i = 0; i < count; ++i) { skVectorGetValue(&probe, probe_vec, i); if (probe->sensor_id == sid) { if (0 == strcmp(probe_name, probe->probe_name)) { return probe; } } } return NULL; } /* * probeConfProbeDestroyAll(); * * Free all memory used to store the local probe list. */ static void probeConfProbeDestroyAll(void) { size_t i, count; probe_def_t *probe; if (NULL == probe_vec) { return; } /* Free all the probes */ count = skVectorGetCount(probe_vec); for (i = 0; i < count; ++i) { skVectorGetValue(&probe, probe_vec, i); skProbeDestroy(&probe); } /* destroy the vector itself */ skVectorDestroy(probe_vec); probe_vec = NULL; } /* * ***** Probes ***************************************************** */ /* Create a probe */ int skProbeCreate(probe_def_t **probe) { int i; assert(probe); (*probe) = calloc(1, sizeof(struct _probe_def)); if (NULL == (*probe)) { return -1; } for (i = 0; i < NUM_IFMAPS; ++i) { if (skBitmapCreate(&((*probe)->if_map[i]), SK_SNMP_INDEX_LIMIT)) { skProbeDestroy(probe); return -1; } } (*probe)->accept_from_addr = INADDR_ANY; (*probe)->listen_as_addr = INADDR_ANY; (*probe)->listen_on_port = PORT_NOT_SET; (*probe)->sensor_id = SK_INVALID_SENSOR; (*probe)->probe_type = PROBE_ENUM_NETFLOW; (*probe)->protocol = PROBE_PROTO_UNSET; (*probe)->priority = PROBE_MIN_PRIORITY; (*probe)->if_remaining_ips = REMAINDER_NOT_SET; (*probe)->log_flags = SOURCE_LOG_ALL; return 0; } /* Destroy a probe and free all memory associated with it */ void skProbeDestroy(probe_def_t **probe) { int i, j; skOctetMap_t **omap_list; assert(*probe); if ( !(*probe)) { return; } for (i = 0; i < NUM_IFMAPS; ++i) { if ((*probe)->if_map[i]) { skBitmapDestroy( &((*probe)->if_map[i])); } if ((*probe)->if_ipblock[i]) { omap_list = (*probe)->if_ipblock[i]; if ((*probe)->if_remaining_ips == i) { /* the interface that holds the remaining IPs holds * references to existing IPs, so it should not free * them; we will just set them all to NULL */ for (j = 0; omap_list[j]; ++j) { omap_list[j] = NULL; } } else { for (j = 0; omap_list[j]; ++j) { free(omap_list[j]); omap_list[j] = NULL; } } free(omap_list); (*probe)->if_ipblock[i] = NULL; } } if ((*probe)->isp_ip_count) { free((*probe)->isp_ip_list); (*probe)->isp_ip_list = NULL; (*probe)->isp_ip_count = 0; } if ((*probe)->accept_from_name) { free((*probe)->accept_from_name); } if ((*probe)->unix_domain_path) { free((*probe)->unix_domain_path); } if ((*probe)->file_source) { free((*probe)->file_source); } if ((*probe)->poll_directory) { free((*probe)->poll_directory); } free(*probe); *probe = NULL; } /* Set and get the sensor that this probe belongs to. */ int skProbeSetSensor(probe_def_t *probe, sensorID_t sensor_id) { assert(probe); if ( !sksiteSensorExists(sensor_id) ) { return -1; } sksiteSensorGetName(probe->sensor_name, sizeof(probe->sensor_name), sensor_id); probe->sensor_id = sensor_id; probeUpdateUniqueName(probe); return 0; } sensorID_t skProbeGetSensorID(const probe_def_t *probe) { assert(probe); return probe->sensor_id; } const char *skProbeGetSensorName(const probe_def_t *probe) { assert(probe); return probe->sensor_name; } /* Set and get the name of probe */ int skProbeSetName(probe_def_t *probe, const char *name) { int rv; assert(probe); rv = sksiteSensorNameIsLegal(name); if (rv != 0) { return rv; } strncpy(probe->probe_name, name, sizeof(probe->probe_name)); probeUpdateUniqueName(probe); return 0; } const char *skProbeGetName(const probe_def_t *probe) { assert(probe); return probe->probe_name; } static void probeUpdateUniqueName(probe_def_t *probe) { assert(probe); /* use sensor_name/probe_name if both are set and have different values */ if (probe->sensor_name && probe->probe_name && (0 != strcmp(probe->sensor_name, probe->probe_name))) { snprintf(probe->probe_uniq_name, sizeof(probe->probe_uniq_name), "%s/%s", probe->sensor_name, probe->probe_name); } else if (probe->sensor_name) { strncpy(probe->probe_uniq_name, probe->sensor_name, sizeof(probe->probe_uniq_name)); } else if (probe->probe_name) { strncpy(probe->probe_uniq_name, probe->probe_name, sizeof(probe->probe_uniq_name)); } else { probe->probe_uniq_name[0] = '\0'; } } const char *skProbeGetUniqueName(const probe_def_t *probe) { assert(probe); return probe->probe_uniq_name; } /* set and get probe priority */ int skProbeSetPriority( probe_def_t *probe, probe_priority_t priority) { assert(probe); if (priority < PROBE_MIN_PRIORITY || priority > PROBE_MAX_PRIORITY) { return -1; } probe->priority = priority; return 0; } probe_priority_t skProbeGetPriority(const probe_def_t *probe) { assert(probe); return probe->priority; } /* set and get the probe type */ int skProbeSetType( probe_def_t *probe, probe_enum_t probe_type) { assert(probe); if (probe_type == PROBE_ENUM_INVALID || probe_type > PROBE_TYPE_COUNT) { return -1; } probe->probe_type = probe_type; return 0; } probe_enum_t skProbeGetType(const probe_def_t *probe) { assert(probe); return probe->probe_type; } /* set and get the probe's protocol */ int skProbeSetProtocol( probe_def_t *probe, probe_proto_t probe_protocol) { assert(probe); if (probe_protocol == PROBE_PROTO_UNSET || probe_protocol > PROBE_PROTOCOL_COUNT) { return -1; } probe->protocol = probe_protocol; return 0; } probe_proto_t skProbeGetProtocol(const probe_def_t *probe) { assert(probe); return probe->protocol; } /* set and get probe log-flags */ int skProbeSetLogFlags( probe_def_t *probe, uint32_t log_flags) { assert(probe); if (log_flags > SOURCE_LOG_ALL) { return -1; } probe->log_flags = (uint8_t)(log_flags & 0xFF); return 0; } uint8_t skProbeGetLogFlags(const probe_def_t *probe) { assert(probe); return probe->log_flags; } /* Set and get the list of IPs of the ISP */ int skProbeSetIspIps( probe_def_t *probe, const sk_vector_t *isp_ip_vec) { size_t count; assert(probe); if (isp_ip_vec == NULL) { return -1; } count = skVectorGetCount(isp_ip_vec); if (count == 0) { return -1; } if (probe->isp_ip_count) { free(probe->isp_ip_list); } probe->isp_ip_list = malloc(count * skVectorGetElementSize(isp_ip_vec)); if (!probe->isp_ip_list) { return -1; } skVectorToArray(probe->isp_ip_list, isp_ip_vec); probe->isp_ip_count = count; return 0; } uint32_t skProbeGetIspIps( const uint32_t **out_ip_list, const probe_def_t *probe) { assert(probe); if (probe->isp_ip_count > 0) { if (out_ip_list != NULL) { *out_ip_list = probe->isp_ip_list; } } return probe->isp_ip_count; } /* Set and get the list of IP blocks that represent an interface */ int skProbeSetIpBlock( probe_def_t *probe, const sk_vector_t *ipblock_vec, int is_negatated, ifmap_group_id_t if_group_id) { size_t count, i; skOctetMap_t **omap_list; assert(probe); if (ipblock_vec == NULL) { return -1; } count = skVectorGetCount(ipblock_vec); if ((count == 0) || (skVectorGetElementSize(ipblock_vec) != sizeof(skOctetMap_t*))) { return -1; } if (skBitmapGetHighCount(probe->if_map[if_group_id])) { skAppPrintErr(("Error setting IP block on probe %s:\n" "\tCannot set %s IP-block because index already set"), probe->probe_uniq_name, ifmap_group_id_name[if_group_id]); return -1; } omap_list = probe->if_ipblock[if_group_id]; if (NULL == omap_list) { /* must allocate new memory */ omap_list = malloc((count+1) * sizeof(skOctetMap_t*)); if (NULL == omap_list) { return -1; } } else { /* de-allocate any existing octet-maps, unless this was * previously the catch-all for the remaining IPs */ if (probe->if_remaining_ips == if_group_id) { probe->if_remaining_ips = REMAINDER_NOT_SET; for (i = 0; omap_list[i]; ++i) { /* empty */ } } else { for (i = 0; omap_list[i]; ++i) { free(omap_list[i]); } } /* reallocate if we need more space */ if (count > i) { skOctetMap_t **old_list = omap_list; omap_list = realloc(omap_list, (count+1) * sizeof(skOctetMap_t*)); if (omap_list == NULL) { free(old_list); probe->if_ipblock[if_group_id] = NULL; return -1; } } } probe->if_ipblock[if_group_id] = omap_list; /* convert vector to an array */ skVectorToArray(omap_list, ipblock_vec); omap_list[count] = NULL; probe->if_ip_negated[if_group_id] = (is_negatated ? 1 : 0); probe->has_ipblocks = 1; return 0; } uint32_t skProbeGetIpBlock( sk_vector_t *out_ipblock_vec, int *out_is_negatated, const probe_def_t *probe, ifmap_group_id_t if_group_id) { uint32_t i; skOctetMap_t **omap_list; assert(probe); assert(out_ipblock_vec); assert(out_is_negatated); omap_list = probe->if_ipblock[if_group_id]; if (omap_list == NULL) { return 0; } *out_is_negatated = probe->if_ip_negated[if_group_id]; for (i = 0; omap_list[i]; ++i) { if (skVectorAppendValue(out_ipblock_vec, omap_list[i])) { return 0; } } return i; } /* Set the specified interface to all IPs not covered by other interfaces */ int skProbeSetIpBlockRemainingIps( probe_def_t *probe, ifmap_group_id_t if_group_id) { size_t count; size_t i, j; skOctetMap_t **omap_list; skOctetMap_t **oml; assert(probe); /* do some error checking */ if (skBitmapGetHighCount(probe->if_map[if_group_id])) { skAppPrintErr(("Error setting IP block on probe %s:\n" "\tCannot set %s IP-block because index already set"), probe->probe_uniq_name, ifmap_group_id_name[if_group_id]); return -1; } if (probe->if_remaining_ips != REMAINDER_NOT_SET) { skAppPrintErr(("Error setting IP block to \"remainder\" on probe %s:\n" "\tCannot set %s IP block to remainding IPs because\n" "\tthe %s IP block has already claimed them"), probe->probe_uniq_name, ifmap_group_id_name[if_group_id], ifmap_group_id_name[probe->if_remaining_ips]); return -1; } if (probe->has_ipblocks == 0) { skAppPrintErr(("Error setting IP block to \"remainder\" on probe %s:\n" "\tCannot set %s IP block to remaining IP because\n" "\tno other interfaces hold IP blocks"), probe->probe_uniq_name, ifmap_group_id_name[if_group_id]); return -1; } /* count the number of IP blocks we need to accommodate */ count = 0; for (i = 0; i < NUM_IFMAPS; ++i) { if (i == if_group_id) { continue; } oml = probe->if_ipblock[i]; if (NULL == oml) { continue; } for (j = 0; oml[j]; ++j) { ++count; } } /* this case should have been caught above, but check again */ if (count == 0) { skAppPrintErr(("Error setting IP block to \"remainder\" on probe %s:\n" "\tCannot set %s IP block to remaining IP because\n" "\tno other interfaces hold IP blocks"), probe->probe_uniq_name, ifmap_group_id_name[if_group_id]); return -1; } /* create an array to hold references to all the octet-maps */ omap_list = probe->if_ipblock[if_group_id]; if (NULL == omap_list) { /* must allocate new memory */ omap_list = malloc((count+1) * sizeof(skOctetMap_t*)); if (NULL == omap_list) { return -1; } } else { /* de-allocate any existing octet-maps */ for (i = 0; omap_list[i]; ++i) { free(omap_list[i]); } /* reallocate if we need more space */ if (count > i) { skOctetMap_t **old_list = omap_list; omap_list = realloc(omap_list, (count+1) * sizeof(skOctetMap_t*)); if (omap_list == NULL) { free(old_list); probe->if_ipblock[if_group_id] = NULL; return -1; } } } probe->if_ipblock[if_group_id] = omap_list; /* for every ipblock list on all other interfaces, add a reference * to it on this interface */ count = 0; for (i = 0; i < NUM_IFMAPS; ++i) { if (i == if_group_id) { continue; } oml = probe->if_ipblock[i]; if (NULL == oml) { continue; } for (j = 0; oml[j]; ++j) { omap_list[count] = oml[j]; ++count; } } omap_list[count] = NULL; probe->if_ip_negated[if_group_id] = 1; probe->if_remaining_ips = if_group_id; return 0; } /* Set and get the list of external SNMP interfaces */ int skProbeSetInterfaces( probe_def_t *probe, const sk_vector_t *if_vec, ifmap_group_id_t if_group_id) { size_t count, i; uint32_t val; assert(probe); if (if_vec == NULL) { return -1; } count = skVectorGetCount(if_vec); if ((count == 0) || (skVectorGetElementSize(if_vec) != sizeof(uint32_t))) { return -1; } if (NULL != probe->if_ipblock[if_group_id]) { skAppPrintErr(("Error setting interfaces on probe %s:\n" "\tCannot set %s indexes because IP-block already set"), probe->probe_uniq_name, ifmap_group_id_name[if_group_id]); return -1; } skBitmapClearAllBits(probe->if_map[if_group_id]); for (i = 0; i < count; ++i) { skVectorGetValue(&val, if_vec, i); skBitmapSetBit(probe->if_map[if_group_id], val); } assert(skBitmapGetHighCount(probe->if_map[if_group_id]) <= count); if (skBitmapGetHighCount(probe->if_map[if_group_id]) < count) { skAppPrintErr(("Warning setting interfaces on probe %s:\n" "\tRepeated value(s) found in %s indexes list"), probe->probe_uniq_name, ifmap_group_id_name[if_group_id]); } return 0; } uint32_t skProbeGetInterfaces( const sk_bitmap_t **out_if_map, const probe_def_t *probe, ifmap_group_id_t if_group_id) { assert(probe); if (out_if_map != NULL) { /* don't modify out_if_map when no interfaces are set */ if (skBitmapGetHighCount(probe->if_map[if_group_id]) > 0) { *out_if_map = probe->if_map[if_group_id]; } } return skBitmapGetHighCount(probe->if_map[if_group_id]); } /* Set the SNMP interface list on 'if_group_id' to all interfaces not * mentioned in other lists. */ int skProbeSetInterfaceToRemainder( probe_def_t *probe, ifmap_group_id_t if_group_id) { size_t i, j; int set_bit; assert(probe); /* do some error checking */ if (NULL != probe->if_ipblock[if_group_id]) { skAppPrintErr(("Error setting interfaces on probe %s:\n" "\tCannot set %s indexes because IP-block already set"), probe->probe_uniq_name, ifmap_group_id_name[if_group_id]); return -1; } set_bit = 1; for (i = 0; i < SK_SNMP_INDEX_LIMIT; ++i) { /* loop over all interface-map lists */ for (j = 0; j < NUM_IFMAPS; ++j) { /* but skip myself */ if (j == if_group_id) { continue; } if (skBitmapGetBit(probe->if_map[j], i)) { set_bit = 0; break; } } if (set_bit) { skBitmapSetBit(probe->if_map[if_group_id], i); } else { set_bit = 1; } } return 0; } /* set and get host:port to listen on. */ int skProbeSetListenAsAddr( probe_def_t *probe, in_addr_t addr) { assert(probe); if (addr == 0) { return -1; } probe->listen_as_addr = addr; return 0; } int skProbeSetListenOnPort( probe_def_t *probe, uint32_t port) { assert(probe); if (port > PORT_VALID_MAX) { return -1; } probe->listen_on_port = port; return 0; } int skProbeGetListenAsHost( in_addr_t *out_addr, uint16_t *out_port, const probe_def_t *probe) { assert(probe); if (probe->listen_on_port == PORT_NOT_SET) { return -1; } if (out_addr) { *out_addr = probe->listen_as_addr; } if (out_port) { *out_port = (uint16_t)probe->listen_on_port; } return 0; } /* set and get the unix domain socket on which to listen. */ int skProbeSetListenOnUnixDomainSocket( probe_def_t *probe, const char * u_socket) { assert(probe); if (u_socket == NULL || u_socket[0] == '\0') { return -1; } if (probe->unix_domain_path) { free(probe->unix_domain_path); } probe->unix_domain_path = strdup(u_socket); return 0; } const char *skProbeGetListenOnUnixDomainSocket(const probe_def_t *probe) { assert(probe); return probe->unix_domain_path; } /* set and get the file name to read data from */ int skProbeSetFileSource( probe_def_t *probe, const char *pathname) { assert(probe); if (pathname == NULL) { return -1; } if (probe->file_source) { free(probe->file_source); } probe->file_source = strdup(pathname); if (!probe->file_source) { return -1; } return 0; } const char *skProbeGetFileSource(const probe_def_t *probe) { assert (probe); return probe->file_source; } /* set and get the name of the directory to poll for new files */ int skProbeSetPollDirectory( probe_def_t *probe, const char *pathname) { assert(probe); if (pathname == NULL) { return -1; } if (probe->poll_directory) { free(probe->poll_directory); } probe->poll_directory = strdup(pathname); if (!probe->poll_directory) { return -1; } return 0; } const char *skProbeGetPollDirectory(const probe_def_t *probe) { assert (probe); return probe->poll_directory; } /* set and get host to accept connections from */ int skProbeSetAcceptFromHost( probe_def_t *probe, const char *host_name, in_addr_t host_addr) { assert(probe); if (host_addr == 0) { return -1; } if (probe->accept_from_name) { free(probe->accept_from_name); } if (host_name) { probe->accept_from_name = strdup(host_name); } probe->accept_from_addr = host_addr; return 0; } const char *skProbeGetAcceptFromHost( in_addr_t *out_addr, const probe_def_t *probe) { assert(probe); if (out_addr) { *out_addr = probe->accept_from_addr; } return probe->accept_from_name; } /* * is_valid = skProbeVerifyIPFIX(p); * * Verify that probe has everything required to collect IPFIX data. */ int skProbeVerifyIPFIX(probe_def_t *probe) { #ifndef HAVE_FIXBUF_PUBLIC_H skAppPrintErr(("Error verifying probe %s:\n" "\tIPFIX support was not included at compile time"), probe->probe_uniq_name); return -1; #else /* IPFIX does not support reading from files */ if (probe->file_source != NULL) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes do not support" " reading data from files"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } /* IPFIX does not support unix sockets */ if (probe->unix_domain_path != NULL) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes do not support" "listening on a UNIX domain socket"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } /* IPFIX does not support directory polling */ if (probe->poll_directory != NULL) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes do not support" " polling a directory for files"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } /* IPFIX requires a port to listen upon */ if (probe->listen_on_port == PORT_NOT_SET) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' require a port upon which" " to listen for IPFIX connections"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } /* Our IPFIX support only allows UDP and TCP and has no default */ switch (probe->protocol) { case PROBE_PROTO_UDP: case PROBE_PROTO_TCP: break; case PROBE_PROTO_UNSET: skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes must set" " the protocol to 'tcp' or 'udp'"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; default: skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes only support" " the UDP or TCP protocol"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } /* IPFIX does not support interface indexes */ if (skProbeCountNetflowInterfaces(probe, 1) != 0) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes may not have any" " SNMP interface values"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } return 0; #endif /* HAVE_FIXBUF_PUBLIC_H */ } /* * is_valid = skProbeVerifyNetflow(p); * * Verify that probe has everything required to collect netflow * data. */ int skProbeVerifyNetflow(probe_def_t *probe) { /* Netflow does not support unix sockets */ if (probe->unix_domain_path != NULL) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes do not support" "listening on a UNIX domain socket for PDUs"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } /* Netflow does not yet support directory polling */ if (probe->poll_directory != NULL) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes do not support" " polling a directory for PDU files"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } /* Netflow only supports the UDP protocol */ if (probe->listen_on_port != PORT_NOT_SET) { switch (probe->protocol) { case PROBE_PROTO_UDP: break; case PROBE_PROTO_UNSET: probe->protocol = PROBE_PROTO_UDP; break; default: skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes only support" " the UDP protocol"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } } /* Specify the default "null" interface if not provided */ if ((skBitmapGetHighCount(probe->if_map[IFMAP_NULL]) == 0) && (probe->if_ipblock[IFMAP_NULL] == NULL) && (skProbeCountNetflowInterfaces(probe, 1) < SK_SNMP_INDEX_LIMIT)) { /* default is 0 from Cisco */ skBitmapSetBit(probe->if_map[IFMAP_NULL], 0); } return 0; } /* * is_valid = skProbeVerifySilk(p); * * Verify that probe has everything required to re-pack SiLK flow * files. */ int skProbeVerifySilk(probe_def_t *probe) { size_t i; /* When re-packing SiLK Flow files, we only support single files * or a directory to poll. */ if (probe->unix_domain_path != NULL) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes do not support" " listening on UNIX sockets for SiLK Flows"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } if (probe->listen_on_port != PORT_NOT_SET) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes do not support" " listening on a TCP socket for SiLK Flows"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } /* Currently, our "repacking" is strictly appending; we ignore any * SNMP values that may be in the flow records, and we cannot * re-pack by IP address. */ if (skProbeCountNetflowInterfaces(probe, 1) != 0) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes may not have any" " SNMP interface values"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } for (i = 0; i < NUM_IFMAPS; ++i) { if (probe->if_ipblock[i]) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes may not have any" " ipblock values"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } } /* The ISP IP has been lost; so specifying it is an error. */ if (probe->isp_ip_count != 0) { skAppPrintErr(("Error verifying probe %s:\n" "\tType '%s' probes may not have any ISP IPs"), probe->probe_uniq_name, skProbetypeEnumtoName(probe->probe_type)); return -1; } return 0; } /* * count = skProbeCountNetflowInterfaces(probe, include_null); * * Count the number of SNMP interfaces that have been mapped to a * flowtype on the 'probe'. Will exclude the IFMAP_NULL group * unless the value 'include_null' is non-zero. */ uint32_t skProbeCountNetflowInterfaces( const probe_def_t *probe, int include_null) { uint32_t ifcount = 0; int i; for (i = 0; i < NUM_IFMAPS; ++i) { ifcount += skBitmapGetHighCount(probe->if_map[i]); } /* Subtract IFMAP_NULL if include_null is zero */ if (0 == include_null) { ifcount -= skBitmapGetHighCount(probe->if_map[IFMAP_NULL]); } return ifcount; } /* * is_valid = skProbeVerify(p); * * Verify that 'p' is a valid probe. */ static int skProbeVerify(probe_def_t *probe) { size_t count, i; int ipblock_seen, map_seen; assert(probe); assert(probe_vec); /* check name */ if ('\0' == probe->probe_name[0]) { skAppPrintErr("Error verifying probe:\n\tProbe has no name."); return -1; } /* check sensor id; get sensor name */ if (probe->sensor_id == SK_INVALID_SENSOR) { skAppPrintErr(("Error verifying probe '%s'\n" "\tProbe's sensor_id is not set."), probe->probe_name); return -1; } /* set probe's unique name */ probeUpdateUniqueName(probe); /* check for duplicate probe names for this sensor */ count = skVectorGetCount(probe_vec); for (i = 0; i < count; ++i) { const probe_def_t *valid_probe; skVectorGetValue(&valid_probe, probe_vec, i); if ((probe->sensor_id == valid_probe->sensor_id) && (0 == strcmp(probe->probe_name, valid_probe->probe_name))) { skAppPrintErr(("Error verifying probe '%s'\n" "\tA probe '%s' already exists for sensor %s"), probe->probe_uniq_name, probe->probe_name, probe->sensor_name); return -1; } } /* verify type is not invalid */ if (probe->probe_type == PROBE_ENUM_INVALID) { skAppPrintErr(("Error verifying probe %s:\n" "\tProbe's type is INVALID."), probe->probe_uniq_name); return -1; } /* this type is not yet supported */ if (probe->probe_type == PROBE_ENUM_SILK) { skAppPrintErr(("Error verifying probe %s:\n" "\tThere is no support for 'silk' probes yet."), probe->probe_uniq_name); return -1; } /* check that one and only one of port, unix socket, * file-source, and poll-directory were given */ count = 0; if (probe->listen_on_port != PORT_NOT_SET) { ++count; } if (probe->unix_domain_path != NULL) { ++count; } if (probe->file_source != NULL) { ++count; } if (probe->poll_directory != NULL) { ++count; } if (count != 1) { if (count == 0) { skAppPrintErr(("Error verifying probe %s:\n" "\tProbe needs a collection source. Must give one" " of listen-on-port,\n\tread-from-file," " listen-on-unix-socket, or poll-directory."), probe->probe_uniq_name); } else { skAppPrintErr(("Error verifying probe %s:\n" "\tMultiple collection sources. Must give only one" " of listen-on-port,\n\tread-from-file," " listen-on-unix-socket, or poll-directory."), probe->probe_uniq_name); } return -1; } /* either 'if_ipblock' or 'if_map' can be specified, but not * both. */ ipblock_seen = map_seen = NUM_IFMAPS; for (i = 0; i < NUM_IFMAPS; ++i) { if ((ipblock_seen == NUM_IFMAPS) && (probe->if_ipblock[i] != NULL)) { ipblock_seen = i; } if ((map_seen == NUM_IFMAPS) && (skBitmapGetHighCount(probe->if_map[i]) != 0)) { map_seen = i; } } if (map_seen != NUM_IFMAPS && ipblock_seen != NUM_IFMAPS) { skAppPrintErr(("Error verifying probe %s:\n" "\tCannot specify both ipblocks (%s)" " and interfaces (%s)\n\ton a single proble."), probe->probe_uniq_name, ifmap_group_id_name[ipblock_seen], ifmap_group_id_name[map_seen]); return -1; } /* verifying the probe by its class */ if (0 != skProbeVerifyClass(probe)) { return -1; } /* verify the probe by its type */ switch (probe->probe_type) { case PROBE_ENUM_NETFLOW: if (0 != skProbeVerifyNetflow(probe)) { return -1; } break; case PROBE_ENUM_IPFIX: if (0 != skProbeVerifyIPFIX(probe)) { return -1; } break; case PROBE_ENUM_SILK: if (0 != skProbeVerifySilk(probe)) { return -1; } break; case PROBE_ENUM_INVALID: /* should have caught this above */ assert(0); abort(); } return 0; } /* Test rwrec against the interfaces (either SNMP or IP block) on the * probe. */ int skProbeTestFlowInterfaces( const probe_def_t *probe, const rwRec *rwrec, ifmap_group_id_t if_group_id, rec_direction_t rec_dir) { uint32_t ip; uint16_t snmp_index; int i; int found = 0; assert(probe); assert(rwrec); if (rec_dir == REC_DIR_FROM) { /* look where the record is coming from: its source IP or * input SNMP interface */ ip = rwrec->sIP.ipnum; snmp_index = rwrec->input; } else { /* look where the record is going to: dIP or output SNMP */ assert(rec_dir == REC_DIR_TO); ip = rwrec->dIP.ipnum; snmp_index = rwrec->output; } /* check to see whether we should test the record against an IP * block or an SNMP interface list. If neither is set for this * if_group_id, we fall out of this if() and return 0. */ if (probe->if_ipblock[if_group_id]) { /* An IP block was set for the if_group_id. Test the record's * IP against it. */ found = probe->if_ip_negated[if_group_id]; for (i = 0; probe->if_ipblock[if_group_id][i]; ++i) { if (skOctetMapGetIp(probe->if_ipblock[if_group_id][i], ip)) { found = !found; break; } } return ((found == 0) ? -1 : 1); } else if (skBitmapGetHighCount(probe->if_map[if_group_id])) { /* An SNMP interface list was set for the if_group_id. Test * the recordd's SNMP value against it. */ if (skBitmapGetBit(probe->if_map[if_group_id], snmp_index)) { return 1; } return -1; } return 0; } /* * ***** Probes Types ***************************************************** */ /* return an enum value given a probe type name */ probe_enum_t skProbetypeNameToEnum(const char *name) { int i; if (NULL != name) { for (i = 0; i < PROBE_TYPE_COUNT; ++i) { if (0 == strcmp(name, probe_type_name_map[i].name)) { return probe_type_name_map[i].value; } } } return PROBE_ENUM_INVALID; } /* return the name given a probe type number */ const char *skProbetypeEnumtoName(probe_enum_t type) { int i; for (i = 0; i < PROBE_TYPE_COUNT; ++i) { if (type == probe_type_name_map[i].value) { return probe_type_name_map[i].name; } } return NULL; } /* * ***** Probes Protocols ************************************************* */ /* return an protocol enum value given a probe protocol name */ probe_proto_t skProbeNameToProtocol(const char *name) { int i; if (NULL != name) { for (i = 0; i < PROBE_PROTOCOL_COUNT; ++i) { if (0 == strcmp(name, probe_protocol_name_map[i].name)) { return probe_protocol_name_map[i].value; } } } return PROBE_PROTO_UNSET; } /* return a name given a probe protocol enum */ const char *skProbeProtocolToName(probe_proto_t protocol) { int i; for (i = 0; i < PROBE_PROTOCOL_COUNT; ++i) { if (protocol == probe_protocol_name_map[i].value) { return probe_protocol_name_map[i].name; } } return NULL; } /* ** Local Variables: ** mode:c ** indent-tabs-mode:nil ** c-basic-offset:4 ** End: */