diff --git a/security/wazuh-agent/Makefile b/security/wazuh-agent/Makefile index c93ec2b45402..40268cb0adb2 100644 --- a/security/wazuh-agent/Makefile +++ b/security/wazuh-agent/Makefile @@ -1,226 +1,227 @@ PORTNAME= wazuh DISTVERSION= 4.14.1 DISTVERSIONPREFIX= v +PORTREVISION= 1 CATEGORIES= security MASTER_SITES= https://packages.wazuh.com/deps/47/libraries/sources/:wazuh_sources PKGNAMESUFFIX= -agent DISTFILES= ${EXTERNAL_DISTFILES} DIST_SUBDIR= ${PORTNAME}-${DISTVERSION} EXTRACT_ONLY= ${DISTNAME}${EXTRACT_SUFX} MAINTAINER= acm@FreeBSD.org COMMENT= Security tool to monitor and check logs and intrusions (agent) WWW= https://github.com/wazuh/wazuh LICENSE= GPLv2 LICENSE_FILE= ${WRKSRC}/LICENSE LIB_DEPENDS= libnghttp2.so:www/libnghttp2 USES= cmake:indirect cpe gmake perl5 readline shebangfix sqlite:3 uidfix USE_GITHUB= yes GH_TUPLE= alonsobsd:wazuh-freebsd:${WAZUH_EXTRAFILE_TAGNAME}:wazuh USE_RC_SUBR= ${PORTNAME}${PKGNAMESUFFIX} MAKE_ARGS+= TARGET=agent WAZUH_EXTRAFILE= alonsobsd-${PORTNAME}-freebsd-${WAZUH_EXTRAFILE_TAGNAME}_GH0${EXTRACT_SUFX} WAZUH_EXTRAFILE_TAGNAME=2f1307c EXTERNAL_DISTFILES= cJSON.tar.gz:wazuh_sources \ curl.tar.gz:wazuh_sources \ libdb.tar.gz:wazuh_sources \ libffi.tar.gz:wazuh_sources \ libyaml.tar.gz:wazuh_sources \ openssl.tar.gz:wazuh_sources \ procps.tar.gz:wazuh_sources \ sqlite.tar.gz:wazuh_sources \ zlib.tar.gz:wazuh_sources \ audit-userspace.tar.gz:wazuh_sources \ msgpack.tar.gz:wazuh_sources \ bzip2.tar.gz:wazuh_sources \ nlohmann.tar.gz:wazuh_sources \ googletest.tar.gz:wazuh_sources \ libpcre2.tar.gz:wazuh_sources \ libplist.tar.gz:wazuh_sources \ libarchive.tar.gz:wazuh_sources \ popt.tar.gz:wazuh_sources OPTIONS_DEFAULT= INOTIFY OPTIONS_DEFINE= INOTIFY PRELUDE ZEROMQ INOTIFY_LIB_DEPENDS= libinotify.so:devel/libinotify PRELUDE_LIB_DEPENDS= libprelude.so:security/libprelude ZEROMQ_LIB_DEPENDS= libczmq.so:net/czmq INOTIFY_DESC= Kevent based real time monitoring PRELUDE_DESC= Sensor support from Prelude SIEM ZEROMQ_DESC= ZeroMQ support ZEROMQ_MAKE_ENV= USE_ZEROMQ=yes PRELUDE_MAKE_ENV= USE_PRELUDE=yes INOTIFY_MAKE_ENV= USE_INOTIFY=yes INOTIFY_USES= pkgconfig WAZUH_USER= wazuh WAZUH_GROUP= wazuh USERS= ${WAZUH_USER} GROUPS= ${WAZUH_GROUP} CONFLICTS= ossec-* wazuh-manager SUB_FILES= pkg-message WZBIN_FILES= agent-auth manage_agents wazuh-agentd wazuh-execd wazuh-logcollector \ wazuh-modulesd WZARBIN_FILES= default-firewall-drop pf npf ipfw firewalld-drop disable-account \ host-deny ip-customblock restart-wazuh route-null kaspersky wazuh-slack WAZUHMOD750= / /logs/wazuh /bin /lib /queue /queue/diff /queue/logcollector \ /queue/syscollector /queue/syscollector/db /ruleset /ruleset/sca /wodles \ /active-response /active-response/bin /agentless /var /backup \ /wodles/aws /wodles/azure /wodles/docker /wodles/gcloud \ /wodles/gcloud/buckets /wodles/gcloud/pubsub WAZUHMOD770= /etc/shared/default /logs /queue/alerts /queue/fim \ /queue/fim/db /queue/rids /queue/sockets /etc /etc/shared \ /var/run /var/upgrade /var/selinux /var/wodles /var/incoming WAZUHPREFIX= /var/ossec .include .if ${ARCH} == powerpc64 MAKE_ENV+= OSSL_TARGET=BSD-ppc64 .elif ${ARCH} == powerpc64le MAKE_ENV+= OSSL_TARGET=BSD-ppc64le .elif ${ARCH} == riscv64 MAKE_ENV+= OSSL_TARGET=BSD-riscv64 .endif .include .if ${OSVERSION} >= 1300139 && ${OSVERSION} < 1400000 FBSD_MAJOR_VERSION=13 .elif ${OSVERSION} >= 1400000 && ${OSVERSION} < 1500000 FBSD_MAJOR_VERSION=14 .elif ${OSVERSION} >= 1500000 && ${OSVERSION} < 1600000 FBSD_MAJOR_VERSION=15 .elif ${OSVERSION} >= 1600000 FBSD_MAJOR_VERSION=16 .else IGNORE= FreeBSD ${OSVERSION} ${ARCH} is not supported .endif post-extract: .for FILE in ${EXTERNAL_DISTFILES} @cd ${WRKSRC}/src/external && ${EXTRACT_CMD} ${EXTRACT_BEFORE_ARGS} ${_DISTDIR}/${FILE:S/:wazuh_sources//} ${EXTRACT_AFTER_ARGS} .endfor @${MKDIR} ${WRKSRC}/ruleset/sca/freebsd @cd ${WRKDIR} && ${EXTRACT_CMD} ${EXTRACT_BEFORE_ARGS} ${_DISTDIR}/${WAZUH_EXTRAFILE} ${EXTRACT_AFTER_ARGS} @${MV} ${WRKDIR}/${PORTNAME}-freebsd-${WAZUH_EXTRAFILE_TAGNAME} ${WRKDIR}/wazuh-freebsd @cd ${WRKDIR}/wazuh-freebsd/var/ossec/ruleset/sca && ${CP} *.yml ${WRKSRC}/ruleset/sca/freebsd/ post-patch: ${REINPLACE_CMD} -e 's|CC=|CC?=|g' -e 's|AR=|AR?=|g' ${WRKSRC}/src/external/bzip2/Makefile ${REINPLACE_CMD} -e 's|%%FBSD_MAJOR_VERSION%%|${FBSD_MAJOR_VERSION}|g' ${WRKSRC}/etc/ossec-agent.conf do-build: cd ${WRKSRC}/src/ && ${SETENV} ${MAKE_ENV} STAGEDIR=${STAGEDIR} \ ${MAKE_CMD} ${MAKE_ARGS} do-install: ${MKDIR} ${STAGEDIR}${WAZUHPREFIX}/bin ${MKDIR} ${STAGEDIR}${WAZUHPREFIX}/lib ${MKDIR} ${STAGEDIR}${WAZUHPREFIX}/tmp .for DIRE in ${WAZUHMOD750} ${MKDIR} -m 0750 ${STAGEDIR}${WAZUHPREFIX}${DIRE} .endfor .for DIRE in ${WAZUHMOD770} ${MKDIR} -m 0770 ${STAGEDIR}${WAZUHPREFIX}${DIRE} .endfor .for FILE in ${WZBIN_FILES} ${INSTALL_PROGRAM} ${WRKSRC}/src/${FILE} ${STAGEDIR}${WAZUHPREFIX}/bin .endfor ${INSTALL_PROGRAM} ${WRKSRC}/src/syscheckd/build/bin/wazuh-syscheckd ${STAGEDIR}${WAZUHPREFIX}/bin ${INSTALL_SCRIPT} ${WRKSRC}/src/init/wazuh-client.sh ${STAGEDIR}${WAZUHPREFIX}/bin/wazuh-control ${TOUCH} ${STAGEDIR}${WAZUHPREFIX}/etc/localtime ${INSTALL_DATA} ${WRKSRC}/etc/internal_options.conf ${STAGEDIR}${WAZUHPREFIX}/etc ${INSTALL_DATA} ${WRKSRC}/src/wazuh_modules/syscollector/norm_config.json ${STAGEDIR}${WAZUHPREFIX}/queue/syscollector ${INSTALL_DATA} ${WRKSRC}/etc/local_internal_options.conf ${STAGEDIR}${WAZUHPREFIX}/etc/local_internal_options.conf.sample ${INSTALL_DATA} /dev/null ${STAGEDIR}${WAZUHPREFIX}/etc/client.keys.sample ${INSTALL_DATA} ${WRKSRC}/etc/wpk_root.pem ${STAGEDIR}${WAZUHPREFIX}/etc/ ${INSTALL_DATA} ${WRKSRC}/etc/ossec-agent.conf ${STAGEDIR}${WAZUHPREFIX}/etc/ossec.conf.sample ${INSTALL_SCRIPT} ${WRKSRC}/src/agentlessd/scripts/* ${STAGEDIR}${WAZUHPREFIX}/agentless/ .for FILE in ${WZARBIN_FILES} ${INSTALL_PROGRAM} ${WRKSRC}/src/${FILE} ${STAGEDIR}${WAZUHPREFIX}/active-response/bin .endfor ${INSTALL_PROGRAM} ${WRKSRC}/src/wazuh-slack ${STAGEDIR}${WAZUHPREFIX}/active-response/bin ${INSTALL_SCRIPT} ${WRKSRC}/src/active-response/*.sh ${STAGEDIR}${WAZUHPREFIX}/active-response/bin ${INSTALL_SCRIPT} ${WRKSRC}/src/active-response/*.py ${STAGEDIR}${WAZUHPREFIX}/active-response/bin ${INSTALL_PROGRAM} ${WRKSRC}/src/default-firewall-drop ${STAGEDIR}${WAZUHPREFIX}/active-response/bin/firewall-drop ${INSTALL_DATA} ${WRKSRC}/ruleset/rootcheck/db/*.txt ${STAGEDIR}${WAZUHPREFIX}/etc/shared ${INSTALL_DATA} ${WRKSRC}/ruleset/rootcheck/db/*.txt ${STAGEDIR}${WAZUHPREFIX}/etc/shared/default ${INSTALL_SCRIPT} ${WRKSRC}/wodles/__init__.py ${STAGEDIR}${WAZUHPREFIX}/wodles/__init__.py ${INSTALL_SCRIPT} ${WRKSRC}/wodles/utils.py ${STAGEDIR}${WAZUHPREFIX}/wodles/utils.py ${INSTALL_SCRIPT} ${WRKSRC}/wodles/aws/aws_s3.py ${STAGEDIR}${WAZUHPREFIX}/wodles/aws/aws-s3.py ${INSTALL_SCRIPT} ${WRKSRC}/framework/wrappers/generic_wrapper.sh ${STAGEDIR}${WAZUHPREFIX}/wodles/aws/aws-s3 ${INSTALL_SCRIPT} ${WRKSRC}/wodles/gcloud/exceptions.py ${STAGEDIR}${WAZUHPREFIX}/wodles/gcloud/exceptions.py ${INSTALL_SCRIPT} ${WRKSRC}/wodles/gcloud/gcloud.py ${STAGEDIR}${WAZUHPREFIX}/wodles/gcloud/gcloud.py ${INSTALL_SCRIPT} ${WRKSRC}/wodles/gcloud/integration.py ${STAGEDIR}${WAZUHPREFIX}/wodles/gcloud/integration.py ${INSTALL_SCRIPT} ${WRKSRC}/wodles/gcloud/tools.py ${STAGEDIR}${WAZUHPREFIX}/wodles/gcloud/tools.py ${INSTALL_SCRIPT} ${WRKSRC}/wodles/gcloud/buckets/bucket.py ${STAGEDIR}${WAZUHPREFIX}/wodles/gcloud/buckets/bucket.py ${INSTALL_SCRIPT} ${WRKSRC}/wodles/gcloud/buckets/access_logs.py ${STAGEDIR}${WAZUHPREFIX}/wodles/gcloud/buckets/access_logs.py ${INSTALL_SCRIPT} ${WRKSRC}/wodles/gcloud/pubsub/subscriber.py ${STAGEDIR}${WAZUHPREFIX}/wodles/gcloud/pubsub/subscriber.py ${INSTALL_SCRIPT} ${WRKSRC}/framework/wrappers/generic_wrapper.sh ${STAGEDIR}${WAZUHPREFIX}/wodles/gcloud/gcloud ${INSTALL_SCRIPT} ${WRKSRC}/wodles/docker-listener/DockerListener.py ${STAGEDIR}${WAZUHPREFIX}/wodles/docker/DockerListener.py ${INSTALL_SCRIPT} ${WRKSRC}/framework/wrappers/generic_wrapper.sh ${STAGEDIR}${WAZUHPREFIX}/wodles/docker/DockerListener ${INSTALL_SCRIPT} ${WRKSRC}/wodles/azure/azure-logs.py ${STAGEDIR}${WAZUHPREFIX}/wodles/azure/azure-logs.py ${INSTALL_SCRIPT} ${WRKSRC}/framework/wrappers/generic_wrapper.sh ${STAGEDIR}${WAZUHPREFIX}/wodles/azure/azure-logs ${INSTALL_DATA} ${WRKSRC}/ruleset/sca/generic/sca_distro_independent_linux.yml ${STAGEDIR}${WAZUHPREFIX}/ruleset/sca/ ${INSTALL_LIB} ${WRKSRC}/src/libwazuhext.so ${STAGEDIR}${WAZUHPREFIX}/lib ${INSTALL_LIB} ${WRKSRC}/src/libwazuhshared.so ${STAGEDIR}${WAZUHPREFIX}/lib ${INSTALL_LIB} ${WRKSRC}/src/shared_modules/dbsync/build/lib/libdbsync.so ${STAGEDIR}${WAZUHPREFIX}/lib ${INSTALL_LIB} ${WRKSRC}/src/shared_modules/rsync/build/lib/librsync.so ${STAGEDIR}${WAZUHPREFIX}/lib ${INSTALL_LIB} ${WRKSRC}/src/syscheckd/build/lib/libfimdb.so ${STAGEDIR}${WAZUHPREFIX}/lib ${INSTALL_LIB} ${WRKSRC}/src/wazuh_modules/syscollector/build/lib/libsyscollector.so ${STAGEDIR}${WAZUHPREFIX}/lib ${INSTALL_LIB} ${WRKSRC}/src/data_provider/build/lib/libsysinfo.so ${STAGEDIR}${WAZUHPREFIX}/lib ${MKDIR} ${STAGEDIR}${WAZUHPREFIX}/packages_files/agent_installation_scripts/etc/templates ${MKDIR} ${STAGEDIR}${WAZUHPREFIX}/packages_files/agent_installation_scripts/src cd ${WRKSRC}/etc/templates && ${COPYTREE_SHARE} config \ ${STAGEDIR}${WAZUHPREFIX}/packages_files/agent_installation_scripts/etc/templates/ cd ${WRKSRC}/ruleset && ${COPYTREE_SHARE} sca \ ${STAGEDIR}${WAZUHPREFIX}/packages_files/agent_installation_scripts/ cd ${WRKSRC}/src && ${COPYTREE_SHARE} init \ ${STAGEDIR}${WAZUHPREFIX}/packages_files/agent_installation_scripts/src/ ${INSTALL_SCRIPT} ${WRKSRC}/gen_ossec.sh ${STAGEDIR}${WAZUHPREFIX}/packages_files/agent_installation_scripts/ ${INSTALL_SCRIPT} ${WRKSRC}/add_localfiles.sh ${STAGEDIR}${WAZUHPREFIX}/packages_files/agent_installation_scripts/ ${INSTALL_DATA} ${WRKSRC}/VERSION.json ${STAGEDIR}${WAZUHPREFIX} .include diff --git a/security/wazuh-agent/files/patch-src-data_provider-src_sysInfoFreeBSD.cpp b/security/wazuh-agent/files/patch-src-data_provider-src_sysInfoFreeBSD.cpp index 929fef4ec8c1..7765db26eb93 100644 --- a/security/wazuh-agent/files/patch-src-data_provider-src_sysInfoFreeBSD.cpp +++ b/security/wazuh-agent/files/patch-src-data_provider-src_sysInfoFreeBSD.cpp @@ -1,335 +1,389 @@ ---- src/data_provider/src/sysInfoFreeBSD.cpp 2025-09-23 06:59:40.000000000 -0700 -+++ src/data_provider/src/sysInfoFreeBSD.cpp 2025-10-16 15:42:56.638994000 -0700 -@@ -11,20 +11,23 @@ +--- src/data_provider/src/sysInfoFreeBSD.cpp.orig 2025-12-29 18:29:38.128837000 -0400 ++++ src/data_provider/src/sysInfoFreeBSD.cpp 2025-12-30 01:04:57.828191000 -0400 +@@ -11,20 +11,28 @@ #include "sysInfo.hpp" #include "cmdHelper.h" #include "stringHelper.h" +#include "timeHelper.h" #include "osinfo/sysOsParsers.h" ++#include "sqliteWrapperTemp.h" ++#include "filesystemHelper.h" #include #include #include #include "sharedDefs.h" +#include ++const std::string PKG_DB_PATHNAME {"/var/db/pkg/local.sqlite"}; ++const std::string PKG_QUERY {"SELECT p.name, p.maintainer, p.version, p.arch, p.comment, p.flatsize, p.time, v.annotation AS repository,p.origin FROM packages p LEFT JOIN (SELECT pa.package_id, pa.value_id FROM pkg_annotation pa JOIN annotation t ON t.annotation_id = pa.tag_id AND t.annotation = 'repository') pr ON pr.package_id = p.id LEFT JOIN annotation v ON v.annotation_id = pr.value_id;"}; ++ static void getMemory(nlohmann::json& info) { + constexpr auto vmFree{"vm.stats.vm.v_free_count"}; + constexpr auto vmInactive{"vm.stats.vm.v_inactive_count"}; constexpr auto vmPageSize{"vm.stats.vm.v_page_size"}; - constexpr auto vmTotal{"vm.vmtotal"}; + constexpr auto vmTotal{"hw.physmem"}; uint64_t ram{0}; - const std::vector mib{CTL_HW, HW_PHYSMEM}; size_t len{sizeof(ram)}; - auto ret{sysctl(const_cast(mib.data()), mib.size(), &ram, &len, nullptr, 0)}; + auto ret{sysctlbyname(vmTotal, &ram, &len, nullptr, 0)}; if (ret) { -@@ -52,11 +55,23 @@ +@@ -52,11 +60,23 @@ }; } - struct vmtotal vmt {}; + uint64_t freeMem{0}; + len = sizeof(freeMem); + ret = sysctlbyname(vmFree, &freeMem, &len, nullptr, 0); - len = sizeof(vmt); + if (ret) + { + throw std::system_error + { + ret, + std::system_category(), + "Error reading free memory size." + }; + } - ret = sysctlbyname(vmTotal, &vmt, &len, nullptr, 0); + uint64_t inactiveMem{0}; + len = sizeof(inactiveMem); + ret = sysctlbyname(vmInactive, &inactiveMem, &len, nullptr, 0); if (ret) { -@@ -64,11 +79,11 @@ +@@ -64,11 +84,11 @@ { ret, std::system_category(), - "Error reading total memory." + "Error reading inactive memory size." }; } - const auto ramFree{(vmt.t_free * pageSize) / KByte}; + const auto ramFree{(freeMem + inactiveMem) * pageSize / KByte}; info["ram_free"] = ramFree; info["ram_usage"] = 100 - (100 * ramFree / ramTotal); } -@@ -184,8 +199,12 @@ +@@ -184,8 +204,12 @@ nlohmann::json SysInfo::getProcessesInfo() const { - // Currently not supported for this OS - return nlohmann::json {}; + nlohmann::json ret; + getProcessesInfo([&ret](nlohmann::json & data) + { + ret.push_back(data); + }); + return ret; } nlohmann::json SysInfo::getOsInfo() const -@@ -196,11 +215,12 @@ +@@ -196,11 +220,12 @@ if (!spParser->parseUname(Utils::exec("uname -r"), ret)) { - ret["os_name"] = "BSD"; ret["os_platform"] = "bsd"; ret["os_version"] = UNKNOWN_VALUE; } + ret["os_name"] = "FreeBSD"; + if (uname(&uts) >= 0) { ret["sysname"] = uts.sysname; -@@ -215,18 +235,200 @@ +@@ -215,44 +240,257 @@ nlohmann::json SysInfo::getPorts() const { - // Currently not supported for this OS. - return nlohmann::json {}; +-} + nlohmann::json ports {}; + + /* USER COMMAND PID FD PROTO LOCAL_ADDRESS FOREIGN_ADDRESS PATH_STATE CONN_STATE */ + +#if __FreeBSD_version > 1500045 + const auto query{exec(R"(sockstat -46qs --libxo json)")}; -+ + +-void SysInfo::getProcessesInfo(std::function /*callback*/) const +-{ +- // Currently not supported for this OS. +-} + if (!query.empty()) + { + nlohmann::json portsjson; + portsjson = nlohmann::json::parse(query); + auto &portsResult = portsjson["sockstat"]["socket"]; -+ + +-void SysInfo::getPackages(std::function callback) const +-{ +- const auto query{Utils::exec(R"(pkg query -a "%n|%m|%v|%q|%c")")}; + for(auto &port : portsResult) { + std::string localip = ""; + std::string localport = ""; + std::string remoteip = ""; + std::string remoteport = ""; + std::string statedata = ""; -+ + + if (port["pid"] != nullptr) { + + localip = port["local"]["address"]; + remoteip = port["foreign"]["address"]; + statedata = port["conn-state"] != nullptr ? (port["conn-state"] == "LISTEN" ? "listening" : Utils::toLowerCase(port["conn-state"])) : statedata; + + if (port["local"]["address"] == "*") { + if ((port["proto"] == "udp4") || (port["proto"] == "tcp4")) { + localip = "0.0.0.0"; + } else { + localip = "::"; + } + } + + localport = port["local"]["port"]; + + if (port["foreign"]["address"] == "*") { + if ((port["proto"] == "udp4") || (port["proto"] == "tcp4")) { + remoteip = 0.0.0.0; + } else { + remoteip = "::"; + } + } + + remoteport = port["foreign"]["port"]; + + nlohmann::json portRecord {}; + + portRecord["protocol"] = port["proto"]; + portRecord["local_ip"] = localip; + portRecord["local_port"] = localport == "*" ? "0" : localport; + portRecord["remote_ip"] = remoteip; + portRecord["remote_port"] = remoteport == "*" ? "0" : remoteport; + portRecord["tx_queue"] = 0; + portRecord["rx_queue"] = 0; + portRecord["inode"] = port["fd"]; + portRecord["state"] = statedata == "??" ? "" : statedata; + portRecord["pid"] = port["pid"]; + portRecord["process"] = port["command"]; + + ports.push_back(portRecord); + } + } + } +#else + const auto query{Utils::exec(R"(sockstat -46qs)")}; + -+ if (!query.empty()) -+ { + if (!query.empty()) + { +- const auto lines{Utils::split(query, '\n')}; + const auto lines{Utils::split(Utils::trimToOneSpace(query), '\n')}; -+ + + std::regex expression(R"(^(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s*(\S+)\s+(\S+)\s+(\S+)(?:\s+(\S+))?\s*$)"); + -+ for (const auto& line : lines) -+ { + for (const auto& line : lines) + { +- const auto data{Utils::split(line, '|')}; +- nlohmann::json package; + std::smatch data; -+ + +- package["name"] = data[0]; +- package["vendor"] = data[1]; +- package["version"] = data[2]; +- package["install_time"] = UNKNOWN_VALUE; +- package["location"] = UNKNOWN_VALUE; +- package["architecture"] = data[3]; +- package["groups"] = UNKNOWN_VALUE; +- package["description"] = data[4]; +- package["size"] = 0; +- package["priority"] = UNKNOWN_VALUE; +- package["source"] = UNKNOWN_VALUE; +- package["format"] = "pkg"; +- // The multiarch field won't have a default value + if (std::regex_search(line, data, expression)) + { + std::string localip = ""; + std::string localport = ""; + std::string remoteip = ""; + std::string remoteport = ""; + std::string statedata = ""; -+ + +- callback(package); + auto localdata{Utils::split(data[6], ':')}; + auto remotedata{Utils::split(data[7], ':')}; + + if (data[8].matched ) { + statedata = data[8] == "LISTEN" ? "listening" : Utils::toLowerCase(data[8]); + } + + localport = localdata[localdata.size() - 1]; + localdata.pop_back(); + localip = Utils::join(localdata, ":"); + remoteport = remotedata[remotedata.size() - 1]; + remotedata.pop_back(); + remoteip = Utils::join(remotedata, ":"); + + if(localip == "*") { + if((data[5] == "tcp4") || (data[5] == "udp4")) { + localip = "0.0.0.0"; + } else { + localip = "::"; + } + } + + if(remoteip == "*") { + if((data[5] == "tcp4") || (data[5] == "udp4")) { + remoteip = "0.0.0.0"; + } else { + remoteip = "::"; + } + } + + if(data[0] != "?") { + nlohmann::json port {}; + + port["protocol"] = data[5]; + port["local_ip"] = localip; + port["local_port"] = localport == "*" ? "0" : localport; + port["remote_ip"] = remoteip; + port["remote_port"] = remoteport == "*" ? "0" : remoteport; + port["tx_queue"] = 0; + port["rx_queue"] = 0; + port["inode"] = data[4]; + port["state"] = statedata == "??" ? "" : statedata; + port["pid"] = data[3]; + port["process"] = data[2]; + + ports.push_back(port); + } + } + } + } +#endif + return ports; - } - --void SysInfo::getProcessesInfo(std::function /*callback*/) const ++} ++ +void SysInfo::getProcessesInfo(std::function callback) const - { -- // Currently not supported for this OS. ++{ + const auto query{Utils::exec(R"(ps -ax -w -o pid,comm,state,ppid,usertime,systime,user,ruser,svuid,group,rgroup,svgid,pri,nice,ssiz,vsz,rss,pmem,etimes,sid,pgid,tpgid,tty,cpu,nlwp,args --libxo json)")}; + + if (!query.empty()) + { + nlohmann::json psjson; + psjson = nlohmann::json::parse(query); + auto &processes = psjson["process-information"]["process"]; + + for(auto &process : processes) { + std::string user_time{""}; + std::string system_time{""}; + + user_time = process["user-time"].get(); + system_time = process["system-time"].get(); + + nlohmann::json jsProcessInfo{}; + jsProcessInfo["pid"] = process["pid"].get(); + jsProcessInfo["name"] = process["command"].get(); + jsProcessInfo["state"] = process["state"].get(); + jsProcessInfo["ppid"] = process["ppid"].get(); + jsProcessInfo["utime"] = Utils::timeToSeconds(user_time); + jsProcessInfo["stime"] = Utils::timeToSeconds(system_time); + jsProcessInfo["cmd"] = process["command"].get(); + jsProcessInfo["argvs"] = process["arguments"].get(); + jsProcessInfo["euser"] = process["user"].get(); + jsProcessInfo["ruser"] = process["real-user"].get(); + jsProcessInfo["suser"] = process["saved-uid"].get(); + jsProcessInfo["egroup"] = process["group"].get(); + jsProcessInfo["rgroup"] = process["real-group"].get(); + jsProcessInfo["sgroup"] = process["saved-gid"].get(); + jsProcessInfo["fgroup"] = process["group"].get(); + jsProcessInfo["priority"] = process["priority"].get(); + jsProcessInfo["nice"] = process["nice"].get(); + jsProcessInfo["size"] = process["stack-size"].get(); + jsProcessInfo["vm_size"] = process["virtual-size"].get(); + jsProcessInfo["resident"] = process["rss"].get(); + //jsProcessInfo["share"] = process["percent-memory"].get(); + jsProcessInfo["start_time"] = process["elapsed-times"].get() == "-" ? "0" : process["elapsed-times"].get(); + jsProcessInfo["pgrp"] = process["process-group"].get(); + jsProcessInfo["session"] = process["sid"].get(); + jsProcessInfo["tgid"] = process["terminal-process-gid"].get(); + //jsProcessInfo["tty"] = process["tty"].get(); // this field should be TEXT into local.db + jsProcessInfo["processor"] = process["on-cpu"].get(); + jsProcessInfo["nlwp"] = process["threads"].get(); + + callback(jsProcessInfo); + } + } ++} ++ ++void SysInfo::getPackages(std::function callback) const ++{ ++ if (Utils::existsRegular(PKG_DB_PATHNAME)) ++ { ++ try ++ { ++ std::shared_ptr sqliteConnection = std::make_shared(PKG_DB_PATHNAME); ++ ++ SQLite::Statement stmt ++ { ++ sqliteConnection, ++ PKG_QUERY ++ }; ++ ++ while (SQLITE_ROW == stmt.step()) ++ { ++ try ++ { ++ auto pkg_name{ stmt.column(0) }; ++ auto pkg_maintainer{ stmt.column(1) }; ++ auto pkg_version{ stmt.column(2) }; ++ auto pkg_arch{ stmt.column(3) }; ++ auto pkg_comment{ stmt.column(4) }; ++ auto pkg_flatsize{ stmt.column(5) }; ++ auto pkg_time{ stmt.column(6) }; ++ auto pkg_repository{ stmt.column(7) }; ++ auto pkg_origin{ stmt.column(8) }; ++ ++ const auto archdata{Utils::split(pkg_arch->value(std::string{}), ':')}; ++ const auto sectiondata{Utils::split(pkg_origin->value(std::string{}), '/')}; ++ ++ nlohmann::json package; ++ ++ package["name"] = pkg_name->value(std::string{}); ++ package["vendor"] = pkg_maintainer->value(std::string{}); ++ package["version"] = pkg_version->value(std::string{}); ++ package["install_time"] = pkg_time->value(std::string{}); ++ package["location"] = UNKNOWN_VALUE; ++ package["architecture"] = archdata[2]; ++ package["groups"] = UNKNOWN_VALUE; ++ package["description"] = pkg_comment->value(std::string{}); ++ package["size"] = pkg_flatsize->value(uint64_t{}); ++ package["priority"] = UNKNOWN_VALUE; ++ package["source"] = pkg_repository->value(std::string{}); ++ package["section"] = sectiondata[0]; ++ package["format"] = "pkg"; ++ // The multiarch field won't have a default value ++ ++ callback(package); ++ } ++ catch (const std::exception& e) ++ { ++ std::cerr << e.what() << std::endl; ++ } ++ } + } ++ catch (const std::exception& e) ++ { ++ std::cerr << e.what() << std::endl; ++ } + } } - void SysInfo::getPackages(std::function callback) const - { -- const auto query{Utils::exec(R"(pkg query -a "%n|%m|%v|%q|%c")")}; -+ const auto query{Utils::exec(R"(pkg query -a "%n|%m|%v|%q|%c|%sb|%t|%R|%o")")}; - - if (!query.empty()) - { -@@ -235,6 +437,9 @@ - for (const auto& line : lines) - { - const auto data{Utils::split(line, '|')}; -+ const auto archdata{Utils::split(data[3], ':')}; -+ const auto sectiondata{Utils::split(data[8], '/')}; -+ - nlohmann::json package; - std::string vendor { UNKNOWN_VALUE }; - std::string email { UNKNOWN_VALUE }; -@@ -244,14 +449,15 @@ - package["name"] = data[0]; - package["vendor"] = vendor; - package["version"] = data[2]; -- package["install_time"] = UNKNOWN_VALUE; -+ package["install_time"] = data[6]; - package["location"] = UNKNOWN_VALUE; -- package["architecture"] = data[3]; -+ package["architecture"] = archdata[2]; - package["groups"] = UNKNOWN_VALUE; - package["description"] = data[4]; -- package["size"] = 0; -+ package["size"] = data[5]; - package["priority"] = UNKNOWN_VALUE; -- package["source"] = UNKNOWN_VALUE; -+ package["source"] = data[7]; -+ package["section"] = sectiondata[0]; - package["format"] = "pkg"; - // The multiarch field won't have a default value -