Skip to content

Commit

Permalink
Add Parser for /proc/net/arp
Browse files Browse the repository at this point in the history
  • Loading branch information
Davidovory03 authored and dtrugman committed Jan 17, 2024
1 parent e886588 commit de5206e
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 2 deletions.
3 changes: 3 additions & 0 deletions include/pfs/net.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class net final
using netlink_socket_filter = std::function<filter::action(const netlink_socket&)>;
using unix_socket_filter = std::function<filter::action(const unix_socket&)>;
using net_route_filter = std::function<filter::action(const net_route&)>;
using net_arp_filter = std::function<filter::action(const net_arp&)>;

public:
std::vector<net_device> get_dev(net_device_filter filter = nullptr) const;
Expand All @@ -69,6 +70,8 @@ class net final

std::vector<net_route> get_route(net_route_filter filter = nullptr) const;

std::vector<net_arp> get_arp(net_arp_filter filter = nullptr) const;

private:
friend class task;
net(const std::string& parent_root);
Expand Down
34 changes: 34 additions & 0 deletions include/pfs/parsers/net_arp.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright 2020-present Daniel Trugman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef PFS_PARSERS_NET_ARP_HPP
#define PFS_PARSERS_NET_ARP_HPP

#include <string>

#include "pfs/types.hpp"

namespace pfs {
namespace impl {
namespace parsers {

net_arp parse_net_arp_line(const std::string& line);

} // namespace parsers
} // namespace impl
} // namespace pfs

#endif // PFS_PARSERS_NET_ARP_HPP
10 changes: 10 additions & 0 deletions include/pfs/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,16 @@ struct net_route
unsigned int irtt;
};

struct net_arp
{
std::string ip_address;
unsigned int type;
unsigned int flags;
std::string hw_address;
std::string mask;
std::string device;
};

// Hint: See 'https://docs.kernel.org/block/stat.html'
struct block_stat
{
Expand Down
3 changes: 3 additions & 0 deletions sample/enum_net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ int enum_net(std::vector<std::string>&& args)

auto routes = net.get_route();
print(routes);

auto arp = net.get_arp();
print(arp);
}
catch (const std::runtime_error& ex)
{
Expand Down
12 changes: 12 additions & 0 deletions sample/format.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,18 @@ inline std::ostream& operator<<(std::ostream& out, const pfs::net_route& route)
return out;
}

inline std::ostream& operator<<(std::ostream& out, const pfs::net_arp& arp)
{
out << "ip_address[" << arp.ip_address << "] ";
out << "type[" << arp.type << "] ";
out << "flags[" << arp.flags << "] ";
out << "hw_address[" << arp.hw_address << "] ";
out << "mask[" << arp.mask << "] ";
out << "device[" << arp.device << "] ";

return out;
}

inline std::ostream& operator<<(std::ostream& out,
const pfs::block_stat& stat)
{
Expand Down
16 changes: 16 additions & 0 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "pfs/net.hpp"
#include "pfs/parsers/net_route.hpp"
#include "pfs/parsers/net_arp.hpp"
#include "pfs/parsers/net_device.hpp"
#include "pfs/parsers/net_socket.hpp"
#include "pfs/parsers/unix_socket.hpp"
Expand Down Expand Up @@ -166,4 +167,19 @@ std::vector<net_route> net::get_route(net_route_filter filter) const
return output;
}

std::vector<net_arp> net::get_arp(net_arp_filter filter) const
{
static const std::string ARP_FILE("arp");
auto path = _net_root + ARP_FILE;

static const size_t HEADER_LINES = 1;

std::vector<net_arp> output;
parsers::parse_file_lines(path, std::back_inserter(output),
parsers::parse_net_arp_line,
filter, HEADER_LINES);
return output;
}


} // namespace pfs
79 changes: 79 additions & 0 deletions src/parsers/net_arp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2020-present Daniel Trugman
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "pfs/parsers/net_arp.hpp"
#include "pfs/parser_error.hpp"
#include "pfs/utils.hpp"
#include "pfs/types.hpp"

namespace pfs {
namespace impl {
namespace parsers {

net_arp parse_net_arp_line(const std::string& line)
{
// Some examples:
// clang-format off
// IP address HW type Flags HW address Mask Device
// 192.168.10.1 0x1 0x2 10:20:30:40:50:60 * eth0
// clang-format on

enum token
{
IP_ADDRESS = 0,
TYPE = 1,
FLAGS = 2,
HW_ADDRESS = 3,
MASK = 4,
DEVICE = 5,
COUNT
};

net_arp arp;

static const char DELIM = ' ';

auto tokens = utils::split(line, DELIM);
if (tokens.size() != COUNT)
{
throw parser_error("Corrupted net arp - Unexpected tokens count", line);
}

try
{
// Parse tokens into arp struct
arp.ip_address = tokens[IP_ADDRESS];
utils::stot(tokens[TYPE], arp.type, utils::base::hex);
utils::stot(tokens[FLAGS], arp.flags, utils::base::hex);
arp.hw_address = tokens[HW_ADDRESS];
arp.mask = tokens[MASK];
arp.device = tokens[DEVICE];
}
catch (const std::invalid_argument& ex)
{
throw parser_error("Corrupted net arp - Invalid argument", line);
}
catch (const std::out_of_range& ex)
{
throw parser_error("Corrupted net arp - Out of range", line);
}

return arp;
}

} // namespace parsers
} // namespace impl
} // namespace pfs
2 changes: 0 additions & 2 deletions src/parsers/net_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ namespace parsers {

namespace {

static const size_t HEX_BYTE_LEN = 8;

net_socket::net_state parse_state(const std::string& state_str)
{
int state_int;
Expand Down
47 changes: 47 additions & 0 deletions test/test_net_arp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <sstream>

#include "catch.hpp"

#include "pfs/parsers/net_arp.hpp"
#include "pfs/parser_error.hpp"
#include "pfs/types.hpp"

using namespace pfs::impl::parsers;

TEST_CASE("Parse corrupted net arp", "[net][arp]")
{
SECTION("Missing token")
{
std::string line = "192.168.10.1 0x1 0x2 10:20:30:40:50:60 *";
REQUIRE_THROWS_AS(parse_net_arp_line(line), pfs::parser_error);
}

SECTION("Extra token")
{
std::string line = "192.168.10.1 0x1 0x2 10:20:30:40:50:60 * eth0 0x4";
REQUIRE_THROWS_AS(parse_net_arp_line(line), pfs::parser_error);
}
}

TEST_CASE("Parse net arp", "[net][arp]")
{
pfs::net_arp expected;

std::string line = "192.168.10.1 0x1 0x2 10:20:30:40:50:60 * eth0";

expected.ip_address = "192.168.10.1";
expected.type = 0x1;
expected.flags = 0x2;
expected.hw_address = "10:20:30:40:50:60";
expected.mask = "*";
expected.device = "eth0";

auto arp = parse_net_arp_line(line);

REQUIRE(arp.ip_address == expected.ip_address);
REQUIRE(arp.type == expected.type);
REQUIRE(arp.flags == expected.flags);
REQUIRE(arp.hw_address == expected.hw_address);
REQUIRE(arp.mask == expected.mask);
REQUIRE(arp.device == expected.device);
}

0 comments on commit de5206e

Please sign in to comment.