IUserPacket::IUserPacket(LPCTSTR xUserId, LPCTSTR xPass) : IPacket( ICP_USER ) { MD5 ctx; BYTE xMD5Hash[16]; ctx.update( (LPBYTE)xPass, _tcslen(xPass) ); ctx.finalize(); ctx.raw_digest( xMD5Hash ); CopyMemory( UserId, xUserId, 21 ); ctx.tostring( (LPBYTE)MD5Hashing ); }
int CalcHashBytes(LPTSTR xHashing, LPCTSTR xString) { MD5 ctx; BYTE pHash[16]; ctx.update( (LPBYTE)xString, _tcslen(xString) ); ctx.finalize(); ctx.raw_digest( pHash ); ctx.tostring( (LPBYTE)xHashing ); return 32; }
void FileCodeWriter::WriteBuffer() { const static unsigned char MICROSOFT_BOM[3] = { 0xEF, 0xBB, 0xBF }; // Compare buffer with existing file (if any) to determine if // writing the file is necessary bool shouldWrite = true; std::ifstream fileIn(m_filename.mb_str(wxConvFile), std::ios::binary | std::ios::in); std::string buf; if (fileIn) { MD5 diskHash(fileIn); unsigned char* diskDigest = diskHash.raw_digest(); MD5 bufferHash; if (m_useMicrosoftBOM) { bufferHash.update(MICROSOFT_BOM, 3); } const std::string& data = m_useUtf8 ? _STDSTR( m_buffer ) : _ANSISTR( m_buffer ); if (!m_useUtf8) buf = data; bufferHash.update( reinterpret_cast< const unsigned char* >( data.c_str() ), data.size() ); bufferHash.finalize(); unsigned char* bufferDigest = bufferHash.raw_digest(); shouldWrite = ( 0 != std::memcmp( diskDigest, bufferDigest, 16 ) ); delete [] diskDigest; delete [] bufferDigest; } if ( shouldWrite ) { wxFile fileOut; if (!fileOut.Create(m_filename, true)) { wxLogError( _("Unable to create file: %s"), m_filename.c_str() ); return; } if (m_useMicrosoftBOM) { fileOut.Write(MICROSOFT_BOM, 3); } if (!m_useUtf8) fileOut.Write(buf.c_str(), buf.length()); else fileOut.Write(m_buffer); } }
/** * Generate BMP router HASH * * \param [in,out] client Reference to client info used to generate the hash. * * \return client.hash_id will be updated with the generated hash */ void BMPListener::hashRouter(ClientInfo &client) { string c_hash_str; MsgBusInterface::hash_toStr(cfg->c_hash_id, c_hash_str); MD5 hash; hash.update((unsigned char *)client.c_ip, strlen(client.c_ip)); hash.update((unsigned char *)c_hash_str.c_str(), c_hash_str.length()); hash.finalize(); // Save the hash unsigned char *hash_bin = hash.raw_digest(); memcpy(client.hash_id, hash_bin, 16); delete[] hash_bin; }
/** * Run Server loop * * \param [in] cfg Reference to the config options */ void runServer(Cfg_Options &cfg) { msgBus_kafka *kafka; int active_connections = 0; // Number of active connections/threads time_t last_heartbeat_time = 0; LOG_INFO("Initializing server"); try { // Define the collector hash MD5 hash; hash.update((unsigned char *)cfg.admin_id, strlen(cfg.admin_id)); hash.finalize(); // Save the hash unsigned char *hash_raw = hash.raw_digest(); memcpy(cfg.c_hash_id, hash_raw, 16); delete[] hash_raw; // Kafka connection kafka = new msgBus_kafka(logger, cfg.kafka_brokers, cfg.c_hash_id); // allocate and start a new bmp server BMPListener *bmp_svr = new BMPListener(logger, &cfg); BMPListener::ClientInfo client; collector_update_msg(kafka, cfg, client, MsgBusInterface::COLLECTOR_ACTION_STARTED); last_heartbeat_time = time(NULL); LOG_INFO("Ready. Waiting for connections"); // Loop to accept new connections while (run) { /* * Check for any stale threads/connections */ for (size_t i=0; i < thr_list.size(); i++) { // If thread is not running, it means it terminated, so close it out if (!thr_list.at(i)->running) { // Join the thread to clean up pthread_join(thr_list.at(i)->thr, NULL); --active_connections; collector_update_msg(kafka, cfg, thr_list.at(i)->client, MsgBusInterface::COLLECTOR_ACTION_CHANGE); // free the vector entry delete thr_list.at(i); thr_list.erase(thr_list.begin() + i); } //TODO: Add code to check for a socket that is open, but not really connected/half open } /* * Create a new client thread if we aren't at the max number of active sessions */ if (active_connections <= MAX_THREADS) { ThreadMgmt *thr = new ThreadMgmt; thr->cfg = &cfg; thr->log = logger; // wait for a new connection and accept if (bmp_svr->wait_and_accept_connection(thr->client, 500)) { // Bump the current thread count ++active_connections; LOG_INFO("Accepted new connection; active connections = %d", active_connections); /* * Start a new thread for every new router connection */ LOG_INFO("Client Connected => %s:%s, sock = %d", thr->client.c_ip, thr->client.c_port, thr->client.c_sock); pthread_attr_t thr_attr; // thread attribute pthread_attr_init(&thr_attr); //pthread_attr_setdetachstate(&thr.thr_attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&thr_attr, PTHREAD_CREATE_JOINABLE); thr->running = 1; // Start the thread to handle the client connection pthread_create(&thr->thr, &thr_attr, ClientThread, thr); // Add thread to vector thr_list.insert(thr_list.end(), thr); // Free attribute pthread_attr_destroy(&thr_attr); collector_update_msg(kafka, cfg, thr->client, MsgBusInterface::COLLECTOR_ACTION_CHANGE); last_heartbeat_time = time(NULL); } else { delete thr; // Send heartbeat if needed if ( (time(NULL) - last_heartbeat_time) >= cfg.heartbeat_interval) { BMPListener::ClientInfo client; collector_update_msg(kafka, cfg, client, MsgBusInterface::COLLECTOR_ACTION_HEARTBEAT); last_heartbeat_time = time(NULL); } usleep(10000); } } else { LOG_WARN("Reached max number of threads, cannot accept new BMP connections at this time."); sleep (1); } } collector_update_msg(kafka, cfg, client, MsgBusInterface::COLLECTOR_ACTION_STOPPED); delete kafka; } catch (char const *str) { LOG_WARN(str); } }
/** * Parses the BGP attributes in the update * * \details * Parses all attributes. Decoded values are updated in 'parsed_data' * * \param [in] data Pointer to the start of the prefixes to be parsed * \param [in] len Length of the data in bytes to be read * \param [out] parsed_update Reference to parsed_update; will be updated with all parsed data */ void parseBgpLib::parseBgpAttr(u_char *data, uint16_t len, parsed_update &update) { /* * Per RFC4271 Section 4.3, flag indicates if the length is 1 or 2 octets */ u_char attr_flags; u_char attr_type; uint16_t attr_len; if (len == 0) return; else if (len < 3) { LOG_WARN("%sCannot parse the attributes due to the data being too short, error in update message. len=%d", debug_prepend_string.c_str(), len); return; } // Generate the hash MD5 hash; /* * Iterate through all attributes and parse them */ for (int read_size = 0; read_size < len; read_size += 2) { attr_flags = *data++; attr_type = *data++; // Check if the length field is 1 or two bytes if (ATTR_FLAG_EXTENDED(attr_flags)) { SELF_DEBUG("%sExtended length path attribute bit set for an entry", debug_prepend_string.c_str()); memcpy(&attr_len, data, 2); data += 2; read_size += 2; parse_bgp_lib::SWAP_BYTES(&attr_len); } else attr_len = *data++; read_size++; // Get the attribute data, if we have any; making sure to not overrun buffer if (attr_len > 0 and (read_size + attr_len) <= len) { // Data pointer is currently at the data position of the attribute /* * Parse data based on attribute type */ parseAttrData(attr_type, attr_len, data, update, hash); data += attr_len; read_size += attr_len; SELF_DEBUG("%sParsed attr Type=%d, size=%hu", debug_prepend_string.c_str(), attr_type, attr_len); } else if (attr_len) { LOG_NOTICE("%sAttribute data len of %hu is larger than available data in update message of %hu", debug_prepend_string.c_str(), attr_len, (len - read_size)); return; } } //Now save the generate hash hash.finalize(); // Save the hash unsigned char *hash_raw = hash.raw_digest(); update.attrs[LIB_ATTR_BASE_ATTR_HASH].name = parse_bgp_lib::parse_bgp_lib_attr_names[LIB_ATTR_BASE_ATTR_HASH]; update.attrs[LIB_ATTR_BASE_ATTR_HASH].value.push_back(parse_bgp_lib::hash_toStr(hash_raw)); delete[] hash_raw; }
/** * Parses the BGP prefixes (advertised and withdrawn) in the update * * \details * Parses all attributes. Decoded values are updated in 'parsed_data' * * \param [in] data Pointer to the start of the prefixes to be parsed * \param [in] len Length of the data in bytes to be read * \param [in] nlri_list Reference to parsed_update_data nlri list; */ void parseBgpLib::parseBgpNlri_v4(u_char *data, uint16_t len, std::list<parse_bgp_lib_nlri> &nlri_list) { u_char ipv4_raw[4]; char ipv4_char[16]; u_char addr_bytes; uint32_t path_id; u_char prefix_len; std::ostringstream numString; if (len <= 0 or data == NULL) return; // Loop through all prefixes for (size_t read_size = 0; read_size < len; read_size++) { parse_bgp_lib_nlri nlri; nlri.afi = parse_bgp_lib::BGP_AFI_IPV4; nlri.safi = parse_bgp_lib::BGP_SAFI_UNICAST; nlri.type = parse_bgp_lib::LIB_NLRI_TYPE_NONE; // Generate the hash MD5 hash; bzero(ipv4_raw, sizeof(ipv4_raw)); // Parse add-paths if enabled bool peer_info_addpath = p_info and p_info->add_path_capability.isAddPathEnabled(bgp::BGP_AFI_IPV4, bgp::BGP_SAFI_UNICAST); if ((peer_info_addpath or addPathCap[BGP_AFI_IPV4_INTERNAL][BGP_SAFI_UNICAST_INTERNAL]) and (len - read_size) >= 4) { memcpy(&path_id, data, 4); parse_bgp_lib::SWAP_BYTES(&path_id); data += 4; read_size += 4; } else path_id = 0; numString.str(std::string()); numString << path_id; nlri.nlri[LIB_NLRI_PATH_ID].name = parse_bgp_lib::parse_bgp_lib_nlri_names[LIB_NLRI_PATH_ID]; nlri.nlri[LIB_NLRI_PATH_ID].value.push_back(numString.str()); if (path_id > 0) update_hash(&nlri.nlri[LIB_NLRI_PATH_ID].value, &hash); // set the address in bits length prefix_len = *data++; numString.str(std::string()); numString << static_cast<unsigned>(prefix_len); nlri.nlri[LIB_NLRI_PREFIX_LENGTH].name = parse_bgp_lib::parse_bgp_lib_nlri_names[LIB_NLRI_PREFIX_LENGTH]; nlri.nlri[LIB_NLRI_PREFIX_LENGTH].value.push_back(numString.str()); update_hash(&nlri.nlri[LIB_NLRI_PREFIX_LENGTH].value, &hash); // Figure out how many bytes the bits requires addr_bytes = prefix_len / 8; if (prefix_len % 8) ++addr_bytes; SELF_DEBUG("%sReading NLRI data prefix bits=%d bytes=%d", debug_prepend_string.c_str(), prefix_len, addr_bytes); if (addr_bytes <= 4) { memcpy(ipv4_raw, data, addr_bytes); read_size += addr_bytes; data += addr_bytes; // Convert the IP to string printed format inet_ntop(AF_INET, ipv4_raw, ipv4_char, sizeof(ipv4_char)); nlri.nlri[LIB_NLRI_PREFIX].name = parse_bgp_lib::parse_bgp_lib_nlri_names[LIB_NLRI_PREFIX]; nlri.nlri[LIB_NLRI_PREFIX].value.push_back(ipv4_char); update_hash(&nlri.nlri[LIB_NLRI_PREFIX].value, &hash); SELF_DEBUG("%sAdding prefix %s len %d", debug_prepend_string.c_str(), ipv4_char, prefix_len); // set the raw/binary address nlri.nlri[LIB_NLRI_PREFIX_BIN].name = parse_bgp_lib::parse_bgp_lib_nlri_names[LIB_NLRI_PREFIX_BIN]; nlri.nlri[LIB_NLRI_PREFIX_BIN].value.push_back(std::string(ipv4_raw, ipv4_raw + 4)); //Update hash to include peer hash id if (p_info) hash.update((unsigned char *) p_info->peer_hash_str.c_str(), p_info->peer_hash_str.length()); hash.finalize(); // Save the hash unsigned char *hash_raw = hash.raw_digest(); nlri.nlri[LIB_NLRI_HASH].name = parse_bgp_lib::parse_bgp_lib_nlri_names[LIB_NLRI_HASH]; nlri.nlri[LIB_NLRI_HASH].value.push_back(parse_bgp_lib::hash_toStr(hash_raw)); delete[] hash_raw; nlri.nlri[LIB_NLRI_IS_IPV4].name =parse_bgp_lib_nlri_names[LIB_NLRI_IS_IPV4]; nlri.nlri[LIB_NLRI_IS_IPV4].value.push_back(string("1")); // Add tuple to prefix list nlri_list.push_back(nlri); } else if (addr_bytes > 4) { LOG_NOTICE("%sNRLI v4 address is larger than 4 bytes bytes=%d len=%d", debug_prepend_string.c_str(), addr_bytes, prefix_len); } } }
/** * Abstract method Implementation - See DbInterface.hpp for details */ void mysqlBMP::add_PathAttrs(tbl_path_attr &path_entry) { try { char buf[64000]; // Misc working buffer char buf2[24000]; // Second working buffer size_t buf_len; // size of the query buff // Setup the initial MySQL query buf_len = sprintf(buf, "INSERT into %s (%s) values ", TBL_NAME_PATH_ATTRS, "hash_id,peer_hash_id,origin,as_path,next_hop,med,local_pref,isAtomicAgg,aggregator,community_list,ext_community_list,cluster_list,originator_id,origin_as,as_path_count,timestamp"); /* * Generate router table hash from the following fields * peer_hash_id, as_path, next_hop, aggregator, * origin, med, local_pref * */ MD5 hash; // Generate the hash hash.update(path_entry.peer_hash_id, HASH_SIZE); hash.update((unsigned char *) path_entry.as_path, strlen(path_entry.as_path)); hash.update((unsigned char *) path_entry.next_hop, strlen(path_entry.next_hop)); hash.update((unsigned char *) path_entry.aggregator, strlen(path_entry.aggregator)); hash.update((unsigned char *) path_entry.origin, strlen(path_entry.origin)); hash.update((unsigned char *) &path_entry.med, sizeof(path_entry.med)); hash.update((unsigned char *) &path_entry.local_pref, sizeof(path_entry.local_pref)); hash.finalize(); // Save the hash unsigned char *hash_raw = hash.raw_digest(); memcpy(path_entry.hash_id, hash_raw, 16); delete[] hash_raw; // Build the query string path_hash_str; string p_hash_str; hash_toStr(path_entry.hash_id, path_hash_str); hash_toStr(path_entry.peer_hash_id, p_hash_str); buf_len += snprintf(buf2, sizeof(buf2), "('%s','%s','%s','%s','%s', %u,%u,%d,'%s','%s','%s','%s','%s','%"PRIu32"','%hu', from_unixtime(%u)),", path_hash_str.c_str(), p_hash_str.c_str(), path_entry.origin, path_entry.as_path, path_entry.next_hop, path_entry.med, path_entry.local_pref, path_entry.atomic_agg, path_entry.aggregator, path_entry.community_list, path_entry.ext_community_list, path_entry.cluster_list, path_entry.originator_id, path_entry.origin_as, path_entry.as_path_count, path_entry.timestamp_secs); // Cat the string to our query buffer if (buf_len < sizeof(buf)) strcat(buf, buf2); // Remove the last comma since we don't need it buf[buf_len - 1] = 0; // Add the on duplicate statement snprintf(buf2, sizeof(buf2), " ON DUPLICATE KEY UPDATE timestamp=values(timestamp) "); strcat(buf, buf2); SELF_DEBUG("QUERY=%s\n", buf); // Run the query to add the record stmt = con->createStatement(); stmt->execute(buf); // Free the query statement delete stmt; } catch (sql::SQLException &e) { LOG_ERR("mysql error: %s, error Code = %d, state = %s", e.what(), e.getErrorCode(), e.getSQLState().c_str() ); } }
/** * Abstract method Implementation - See DbInterface.hpp for details */ void mysqlBMP::add_Rib(vector<tbl_rib> &rib_entry) { char *buf = new char[800000]; // Misc working buffer char buf2[4096]; // Second working buffer size_t buf_len = 0; // query buffer length try { // Build the initial part of the query //buf_len = sprintf(buf, "REPLACE into %s (%s) values ", TBL_NAME_RIB, // "hash_id,path_attr_hash_id,peer_hash_id,prefix, prefix_len"); buf_len = sprintf(buf, "INSERT into %s (%s) values ", TBL_NAME_RIB, "hash_id,path_attr_hash_id,peer_hash_id,prefix, prefix_len,timestamp"); string rib_hash_str; string path_hash_str; string p_hash_str; // Loop through the vector array of rib entries for (size_t i = 0; i < rib_entry.size(); i++) { /* * Generate router table hash from the following fields * rib_entry.peer_hash_id, rib_entry.prefix, rib_entry.prefix_len * */ MD5 hash; // Generate the hash hash.update(rib_entry[i].peer_hash_id, HASH_SIZE); hash.update((unsigned char *) rib_entry[i].prefix, strlen(rib_entry[i].prefix)); hash.update(&rib_entry[i].prefix_len, sizeof(rib_entry[i].prefix_len)); hash.finalize(); // Save the hash unsigned char *hash_raw = hash.raw_digest(); memcpy(rib_entry[i].hash_id, hash_raw, 16); delete[] hash_raw; // Build the query hash_toStr(rib_entry[i].hash_id, rib_hash_str); hash_toStr(rib_entry[i].path_attr_hash_id, path_hash_str); hash_toStr(rib_entry[i].peer_hash_id, p_hash_str); buf_len += snprintf(buf2, sizeof(buf2), " ('%s','%s','%s','%s', %d, from_unixtime(%u)),", rib_hash_str.c_str(), path_hash_str.c_str(), p_hash_str.c_str(), rib_entry[i].prefix, rib_entry[i].prefix_len, rib_entry[i].timestamp_secs); // Cat the entry to the query buff if (buf_len < 800000 /* size of buf */) strcat(buf, buf2); } // Remove the last comma since we don't need it buf[buf_len - 1] = 0; // Add the on duplicate statement snprintf(buf2, sizeof(buf2), " ON DUPLICATE KEY UPDATE timestamp=values(timestamp),path_attr_hash_id=values(path_attr_hash_id),db_timestamp=current_timestamp"); strcat(buf, buf2); SELF_DEBUG("QUERY=%s", buf); // Run the query to add the record stmt = con->createStatement(); stmt->execute(buf); // Free the query statement delete stmt; } catch (sql::SQLException &e) { LOG_ERR("mysql error: %s, error Code = %d, state = %s", e.what(), e.getErrorCode(), e.getSQLState().c_str() ); } // Free the large buffer delete[] buf; }
/** * Abstract method Implementation - See DbInterface.hpp for details */ void mysqlBMP::add_Router(tbl_router &r_entry) { try { char buf[4096]; // Misc working buffer /* * Generate router table hash from the following fields * r_entry.name, r_entry.src_addr * */ MD5 hash; // Generate the hash //hash.update (r_entry.name, strlen((char *)r_entry.name)); hash.update(r_entry.src_addr, strlen((char *) r_entry.src_addr)); hash.finalize(); // Save the hash unsigned char *hash_raw = hash.raw_digest(); memcpy(r_entry.hash_id, hash_raw, 16); delete [] hash_raw; // Convert binary hash to string string r_hash_str; hash_toStr(r_entry.hash_id, r_hash_str); // Check if we have already processed this entry, if so update it an return if (router_list.find(r_hash_str) != router_list.end()) { router_list[r_hash_str] = time(NULL); return; } // Insert/Update map entry router_list[r_hash_str] = time(NULL); // Convert the init data to string for storage string initData(r_entry.initiate_data); std::replace(initData.begin(), initData.end(), '\'', '"'); // Build the query snprintf(buf, sizeof(buf), "INSERT into %s (%s) values ('%s', '%s', '%s','%s','%s')", TBL_NAME_ROUTERS, "hash_id,name,description,ip_address,init_data", r_hash_str.c_str(), r_entry.name, r_entry.descr, r_entry.src_addr, initData.c_str()); // Add the on duplicate statement strcat(buf, " ON DUPLICATE KEY UPDATE timestamp=current_timestamp,isConnected=1,name=values(name),description=values(description),init_data=values(init_data)"); // Run the query to add the record stmt = con->createStatement(); stmt->execute(buf); // Update all peers to indicate peers are not up - till proven other wise snprintf(buf, sizeof(buf), "UPDATE %s SET state=0 where router_hash_id='%s'", TBL_NAME_BGP_PEERS, r_hash_str.c_str()); stmt->execute(buf); // Free the query statement delete stmt; } catch (sql::SQLException &e) { LOG_ERR("mysql error: %s, error Code = %d, state = %s", e.what(), e.getErrorCode(), e.getSQLState().c_str() ); } }
/** * Abstract method Implementation - See DbInterface.hpp for details */ void mysqlBMP::add_Peer(tbl_bgp_peer &p_entry) { try { char buf[4096]; // Misc working buffer /* * Generate peer table hash from the following fields * p_entry.router_hash_id, p_entry.peer_rd, p_entry.peer_addr, * p_entry.peer_bgp_id * */ MD5 hash; // Generate the hash hash.update(p_entry.router_hash_id, HASH_SIZE); hash.update((unsigned char *) p_entry.peer_rd, strlen(p_entry.peer_rd)); hash.update((unsigned char *) p_entry.peer_addr, strlen(p_entry.peer_addr)); hash.update((unsigned char *) p_entry.peer_bgp_id, strlen(p_entry.peer_bgp_id)); hash.finalize(); // Save the hash unsigned char *hash_raw = hash.raw_digest(); memcpy(p_entry.hash_id, hash_raw, 16); delete[] hash_raw; // Convert binary hash to string string p_hash_str; hash_toStr(p_entry.hash_id, p_hash_str); string r_hash_str; hash_toStr(p_entry.router_hash_id, r_hash_str); // Check if we have already processed this entry, if so update it an return if (peer_list.find(p_hash_str) != peer_list.end()) { peer_list[p_hash_str] = time(NULL); return; } // Insert/Update map entry peer_list[p_hash_str] = time(NULL); // Build the query snprintf(buf, sizeof(buf), "REPLACE into %s (%s) values ('%s','%s','%s',%d, '%s', '%s', %u, %d, %d, current_timestamp,1)", TBL_NAME_BGP_PEERS, "hash_id,router_hash_id, peer_rd,isIPv4,peer_addr,peer_bgp_id,peer_as,isL3VPNpeer,isPrePolicy,timestamp,state", p_hash_str.c_str(), r_hash_str.c_str(), p_entry.peer_rd, p_entry.isIPv4, p_entry.peer_addr, p_entry.peer_bgp_id, p_entry.peer_as, p_entry.isL3VPN, p_entry.isPrePolicy); SELF_DEBUG("QUERY=%s", buf); // Run the query to add the record stmt = con->createStatement(); stmt->execute(buf); // Free the query statement delete stmt; } catch (sql::SQLException &e) { LOG_ERR("mysql error: %s, error Code = %d, state = %s", e.what(), e.getErrorCode(), e.getSQLState().c_str() ); } }