Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions libenv/unix_iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <ip_address.h>
#include <file_lib.h>
#include <cleanup.h>
#include <unix.h> /* GetRelocatedProcdirRoot() and GetProcdirPid() */

#ifdef HAVE_SYS_JAIL_H
# include <sys/jail.h>
Expand Down Expand Up @@ -1283,6 +1284,10 @@ static JsonElement* GetNetworkingStatsInfo(const char *filename)

fclose(fin);
}
else
{
Log(LOG_LEVEL_VERBOSE, "netstat file not found at '%s'", filename);
}

return stats;
}
Expand Down Expand Up @@ -1390,20 +1395,21 @@ JsonElement* GetProcFileInfo(EvalContext *ctx, const char* filename, const char*
void GetNetworkingInfo(EvalContext *ctx)
{
const char *procdir_root = GetRelocatedProcdirRoot();
int promiser_pid = GetProcdirPid();

Buffer *pbuf = BufferNew();

JsonElement *inet = JsonObjectCreate(2);

BufferPrintf(pbuf, "%s/proc/net/netstat", procdir_root);
BufferPrintf(pbuf, "%s/proc/%d/net/netstat", procdir_root, promiser_pid);
JsonElement *inet_stats = GetNetworkingStatsInfo(BufferData(pbuf));

if (inet_stats != NULL)
{
JsonObjectAppendElement(inet, "stats", inet_stats);
}

BufferPrintf(pbuf, "%s/proc/net/route", procdir_root);
BufferPrintf(pbuf, "%s/proc/%d/net/route", procdir_root, promiser_pid);
JsonElement *routes = GetProcFileInfo(ctx, BufferData(pbuf), NULL, NULL, &NetworkingRoutesPostProcessInfo, NULL,
// format: Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
// eth0 00000000 0102A8C0 0003 0 0 1024 00000000 0 0 0
Expand Down Expand Up @@ -1451,7 +1457,7 @@ void GetNetworkingInfo(EvalContext *ctx)

JsonElement *inet6 = JsonObjectCreate(3);

BufferPrintf(pbuf, "%s/proc/net/snmp6", procdir_root);
BufferPrintf(pbuf, "%s/proc/%d/net/snmp6", procdir_root, promiser_pid);
JsonElement *inet6_stats = GetProcFileInfo(ctx, BufferData(pbuf), NULL, NULL, NULL, NULL,
"^\\s*(?<key>\\S+)\\s+(?<value>\\d+)");

Expand All @@ -1477,7 +1483,7 @@ void GetNetworkingInfo(EvalContext *ctx)
JsonDestroy(inet6_stats);
}

BufferPrintf(pbuf, "%s/proc/net/ipv6_route", procdir_root);
BufferPrintf(pbuf, "%s/proc/%d/net/ipv6_route", procdir_root, promiser_pid);
JsonElement *inet6_routes = GetProcFileInfo(ctx, BufferData(pbuf), NULL, NULL, &NetworkingIPv6RoutesPostProcessInfo, NULL,
// format: dest dest_prefix source source_prefix next_hop metric refcnt use flags interface
// fe800000000000000000000000000000 40 00000000000000000000000000000000 00 00000000000000000000000000000000 00000100 00000000 00000000 00000001 eth0
Expand All @@ -1492,7 +1498,7 @@ void GetNetworkingInfo(EvalContext *ctx)
JsonObjectAppendElement(inet6, "routes", inet6_routes);
}

BufferPrintf(pbuf, "%s/proc/net/if_inet6", procdir_root);
BufferPrintf(pbuf, "%s/proc/%d/net/if_inet6", procdir_root, promiser_pid);
JsonElement *inet6_addresses = GetProcFileInfo(ctx, BufferData(pbuf), NULL, "interface", &NetworkingIPv6AddressesPostProcessInfo, &NetworkingIPv6AddressesTiebreaker,
// format: address device_number prefix_length scope flags interface_name
// 00000000000000000000000000000001 01 80 10 80 lo
Expand All @@ -1515,7 +1521,7 @@ void GetNetworkingInfo(EvalContext *ctx)
// face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
// eth0: 74850544807 75236137 0 0 0 0 0 1108775 63111535625 74696758 0 0 0 0 0 0

BufferPrintf(pbuf, "%s/proc/net/dev", procdir_root);
BufferPrintf(pbuf, "%s/proc/%d/net/dev", procdir_root, promiser_pid);
JsonElement *interfaces_data =
GetProcFileInfo(ctx, BufferData(pbuf), "interfaces_data", "device", NULL, NULL,
"^\\s*(?<device>[^:]+)\\s*:\\s*"
Expand Down Expand Up @@ -1543,34 +1549,35 @@ void GetNetworkingInfo(EvalContext *ctx)
JsonElement* GetNetworkingConnections(EvalContext *ctx)
{
const char *procdir_root = GetRelocatedProcdirRoot();
int promiser_pid = GetProcdirPid();
JsonElement *json = JsonObjectCreate(5);
const char* ports_regex = "^\\s*\\d+:\\s+(?<raw_local>[0-9A-F:]+)\\s+(?<raw_remote>[0-9A-F:]+)\\s+(?<raw_state>[0-9]+)";

JsonElement *data = NULL;
Buffer *pbuf = BufferNew();

BufferPrintf(pbuf, "%s/proc/net/tcp", procdir_root);
BufferPrintf(pbuf, "%s/proc/%d/net/tcp", procdir_root, promiser_pid);
data = GetProcFileInfo(ctx, BufferData(pbuf), NULL, NULL, &NetworkingPortsPostProcessInfo, NULL, ports_regex);
if (data != NULL)
{
JsonObjectAppendElement(json, "tcp", data);
}

BufferPrintf(pbuf, "%s/proc/net/tcp6", procdir_root);
BufferPrintf(pbuf, "%s/proc/%d/net/tcp6", procdir_root, promiser_pid);
data = GetProcFileInfo(ctx, BufferData(pbuf), NULL, NULL, &NetworkingPortsPostProcessInfo, NULL, ports_regex);
if (data != NULL)
{
JsonObjectAppendElement(json, "tcp6", data);
}

BufferPrintf(pbuf, "%s/proc/net/udp", procdir_root);
BufferPrintf(pbuf, "%s/proc/%d/net/udp", procdir_root, promiser_pid);
data = GetProcFileInfo(ctx, BufferData(pbuf), NULL, NULL, &NetworkingPortsPostProcessInfo, NULL, ports_regex);
if (data != NULL)
{
JsonObjectAppendElement(json, "udp", data);
}

BufferPrintf(pbuf, "%s/proc/net/udp6", procdir_root);
BufferPrintf(pbuf, "%s/proc/%d/net/udp6", procdir_root, promiser_pid);
data = GetProcFileInfo(ctx, BufferData(pbuf), NULL, NULL, &NetworkingPortsPostProcessInfo, NULL, ports_regex);
if (data != NULL)
{
Expand Down
42 changes: 42 additions & 0 deletions libpromises/unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <unix.h>
#include <exec_tools.h>
#include <file_lib.h>
#include <string_lib.h> /* StringToInt64() */

#ifdef HAVE_SYS_UIO_H
# include <sys/uio.h>
Expand Down Expand Up @@ -527,4 +528,45 @@ bool GetGroupID(const char *group_name, gid_t *gid, LogLevel error_log_level)
return true;
}

const char* GetRelocatedProcdirRoot()
{
const char *procdir = getenv("CFENGINE_TEST_OVERRIDE_PROCDIR");
if (procdir == NULL)
{
procdir = "";
}
else
{
Log(LOG_LEVEL_VERBOSE, "Overriding /proc location to be %s", procdir);
}

return procdir;
}

/**
* With the addition of using the current PID when examining the proc filesystem for details
* we need a test-override option for acceptance tests.
*/
int GetProcdirPid()
{
const char *procpid = getenv("CFENGINE_TEST_OVERRIDE_PROCPID");
if (procpid != NULL)
{
int64_t pid_int;
int rc;
rc = StringToInt64(procpid, &pid_int);
if (rc != 0)
{
Log(LOG_LEVEL_ERR, "Could not parse CFENGINE_TEST_OVERRIDE_PROCPID '%s' as integer: '%s'", procpid, strerror(errno));
}
else
{
Log(LOG_LEVEL_VERBOSE, "Overriding proc pid from env var CFENGINE_TEST_OVERRIDE_PROCPID with value %jd", (intmax_t) pid_int);
return (int) pid_int;
}
}
return (int) getpid();
}


#endif /* !__MINGW32__ */
11 changes: 11 additions & 0 deletions libpromises/unix.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ void ProcessSignalTerminate(pid_t pid);
bool GetCurrentUserName(char *userName, int userNameLen);

#ifndef __MINGW32__
/**
* @brief For testing things against /proc, uses env var CFENGINE_TEST_OVERRIDE_PROCDIR
* @return the extra directory to add BEFORE /proc in the path
*/
const char* GetRelocatedProcdirRoot();
/**
* @brief For testing things against /proc, use env var CFENGINE_TEST_OVERRIDE_PROCPID
* @return the fake pid to use in proc paths
*/
int GetProcdirPid();

/**
* Get user name for the user with UID #uid
*
Expand Down
26 changes: 25 additions & 1 deletion tests/acceptance/00_basics/environment/proc-net-functions.cf
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,35 @@ body common control

###########################################################

bundle agent init
{
vars:
"pid_for_testing" int => "11";

methods:
"" usebundle => dir_sync(
"$(this.promise_dirname)/proc",
"$(G.testdir)/proc"
);

commands:
"
cd $(G.testdir)/proc/proc
mkdir $(pid_for_testing)
mv net $(pid_for_testing)/
ln -s $(pid_for_testing) self
ln -s self/net net
"
comment => "Create a semi-real structure with symlinks and a pid dir",
contain => in_shell;
}


bundle agent test
{
meta:
"test_skip_unsupported" string => "!linux";

commands:
"$(G.env) CFENGINE_TEST_OVERRIDE_PROCDIR=$(this.promise_dirname)/proc $(sys.cf_agent) -DAUTO -f $(this.promise_filename).sub";
"$(G.env) CFENGINE_TEST_OVERRIDE_PROCPID=$(init.pid_for_testing) CFENGINE_TEST_OVERRIDE_PROCDIR=$(G.testdir)/proc $(sys.cf_agent) -DAUTO -f $(this.promise_filename).sub";
}
25 changes: 24 additions & 1 deletion tests/acceptance/00_basics/environment/proc-net.cf
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,34 @@ body common control

###########################################################

bundle agent init
{
vars:
"pid_for_testing" int => "11";

methods:
"" usebundle => dir_sync(
"$(this.promise_dirname)/proc",
"$(G.testdir)/proc"
);

commands:
"
cd $(G.testdir)/proc/proc
mkdir $(pid_for_testing)
mv net $(pid_for_testing)/
ln -s $(pid_for_testing) self
ln -s self/net net
"
comment => "Create a semi-real structure with symlinks and a pid dir",
contain => in_shell;
}

bundle agent test
{
meta:
"test_skip_unsupported" string => "!linux";

commands:
"$(G.env) CFENGINE_TEST_OVERRIDE_PROCDIR=$(this.promise_dirname)/proc $(sys.cf_agent) -DAUTO -f $(this.promise_filename).sub";
"$(G.env) CFENGINE_TEST_OVERRIDE_PROCPID=$(init.pid_for_testing) CFENGINE_TEST_OVERRIDE_PROCDIR=$(G.testdir)/proc $(sys.cf_agent) -DAUTO -f $(this.promise_filename).sub";
}
Loading