Initial commit.
I've just messed around a bit with the Boost IP range and network types to be able to describe allocations. Checkpointing. Starting a repo.
This commit is contained in:
9
Makefile
Normal file
9
Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
CXXFLAGS+= -std=c++23
|
||||||
|
LDLIBS+= -lalepha
|
||||||
|
LDFLAGS+= -L Alepha/build-debug -Wl,-rpath,/home/user/proj/ipam/Alepha/build-debug
|
||||||
|
CPPFLAGS+= -I .
|
||||||
|
|
||||||
|
all: test
|
||||||
|
|
||||||
|
test: ipam
|
||||||
|
./ipam
|
155
ipam.cc
Normal file
155
ipam.cc
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include <boost/asio/ip/network_v6.hpp>
|
||||||
|
|
||||||
|
#include <Alepha/IOStreams/Streamable.h>
|
||||||
|
|
||||||
|
namespace asio= boost::asio;
|
||||||
|
namespace ip= asio::ip;
|
||||||
|
|
||||||
|
template< typename= Alepha::Capabilities< Alepha::IOStreams::Streamable > >
|
||||||
|
struct Allocation_core;
|
||||||
|
|
||||||
|
using Allocation= Allocation_core<>;
|
||||||
|
|
||||||
|
struct IP_Address : ip::network_v6
|
||||||
|
{
|
||||||
|
using ip::network_v6::network_v6;
|
||||||
|
|
||||||
|
IP_Address( const network_v6 &n ) : ip::network_v6( n ) {}
|
||||||
|
|
||||||
|
friend std::istream &
|
||||||
|
operator >> ( std::istream &is, IP_Address &a )
|
||||||
|
{
|
||||||
|
std::string s;
|
||||||
|
is >> s;
|
||||||
|
a= ip::make_network_v6( s );
|
||||||
|
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template< typename >
|
||||||
|
struct Allocation_core
|
||||||
|
{
|
||||||
|
ip::network_v6 network;
|
||||||
|
|
||||||
|
std::string owner;
|
||||||
|
std::string name;
|
||||||
|
std::string purpose;
|
||||||
|
|
||||||
|
std::vector< Allocation > subAllocations() const;
|
||||||
|
std::vector< Allocation > available() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector< Allocation > spaces;
|
||||||
|
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline std::vector< Allocation >
|
||||||
|
Allocation::subAllocations() const
|
||||||
|
{
|
||||||
|
std::vector< Allocation > rv;
|
||||||
|
|
||||||
|
for( const auto &alloc: spaces )
|
||||||
|
{
|
||||||
|
if( alloc.network.is_subnet_of( network ) ) rv.push_back( alloc );
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Command
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
std::string help;
|
||||||
|
std::function< void ( std::vector< std::string > ) > run;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::map< std::string, Command > commands;
|
||||||
|
|
||||||
|
void
|
||||||
|
add_command( Command command )
|
||||||
|
{
|
||||||
|
commands.insert( { command.name, command } );
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main()
|
||||||
|
try
|
||||||
|
{
|
||||||
|
spaces.push_back( { ip::make_network_v6( "2000::/3" ), "IANA", "Global Routing - v6", "The initial global routing table for v6" } );
|
||||||
|
|
||||||
|
add_command
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"help",
|
||||||
|
"List all commands",
|
||||||
|
[]( ... )
|
||||||
|
{
|
||||||
|
for( const auto &[ name, command ]: commands )
|
||||||
|
{
|
||||||
|
std::cout << name << " - " << command.help << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
add_command
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"describe",
|
||||||
|
"Describe a network range",
|
||||||
|
[]( const std::vector< std::string > &args )
|
||||||
|
{
|
||||||
|
if( args.size() != 1 ) throw std::runtime_error{ "Too many arguments." };
|
||||||
|
|
||||||
|
const auto &network= boost::lexical_cast< IP_Address >( args.at( 0 ) );
|
||||||
|
|
||||||
|
const Allocation *p= nullptr;
|
||||||
|
|
||||||
|
for( const auto &space: spaces )
|
||||||
|
{
|
||||||
|
const auto &[ where, owner, name, purpose ]= space;
|
||||||
|
if( where == network )
|
||||||
|
{
|
||||||
|
p = &space;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const auto &[ _, owner, name, purpose ]= *p;
|
||||||
|
|
||||||
|
std::cout << network << " is owned by " << owner << std::endl;
|
||||||
|
std::cout << "It is called `" << name << "`" << std::endl;
|
||||||
|
std::cout << "It is used for '" << purpose << "'" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
while( true )
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
getline( std::cin, line );
|
||||||
|
|
||||||
|
const auto parsed= Alepha::split( line, ' ' );
|
||||||
|
const auto &command= parsed.at( 0 );
|
||||||
|
auto args= parsed;
|
||||||
|
args.erase( begin( args ) );
|
||||||
|
|
||||||
|
commands.at( command ).run( args );
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
catch( const std::exception &ex )
|
||||||
|
{
|
||||||
|
std::cerr << "Error: " << ex.what() << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
Reference in New Issue
Block a user