#include "link_layer.hpp" #include "raw_socket_link.hpp" #include "tcp_link.hpp" #include "udp_link.hpp" #include #include #include #include #include #include #ifdef SOCKTAP_WITH_CUBE_EVK # include "nfiniity_cube_evk_link.hpp" #endif #ifdef SOCKTAP_WITH_COHDA_LLC # include "cohda_link.hpp" #endif #ifdef SOCKTAP_WITH_AUTOTALKS # include "autotalks_link.hpp" # include "autotalks.hpp" #endif #ifdef SOCKTAP_WITH_RPC # include "rpc_link.hpp" #endif boost::optional> parse_ip_port(const std::string& ip_port) { using opt_ip_port = boost::optional>; std::size_t ip_len = ip_port.find_last_of(":"); if (ip_len == std::string::npos) { // error: port not found std::cerr << "[" << ip_port << "] Missing port." << std::endl; return opt_ip_port(); } std::size_t port = std::strtoul(ip_port.substr(ip_len + 1).c_str(), NULL, 10); if (port < 1 || port > 65535) { // error: port out of range std::cerr << "[" << ip_port << "] Port " << port << " out of range (1-65535)." << std::endl; return opt_ip_port(); } boost::system::error_code ec; boost::asio::ip::address ip = boost::asio::ip::make_address(ip_port.substr(0, ip_len), ec); if (ec) { // error: IP-address invalid std::cerr << "[" << ip_port << "] Invalid IP-address: " << ec.message() << std::endl; return opt_ip_port(); } return opt_ip_port({ip, port}); } std::unique_ptr create_link_layer(boost::asio::io_context& io_context, const EthernetDevice& device, const std::string& name, const boost::program_options::variables_map& vm) { std::unique_ptr link_layer; if (name == "ethernet" || name == "cohda") { boost::asio::generic::raw_protocol raw_protocol(AF_PACKET, vanetza::access::ethertype::GeoNetworking.net()); boost::asio::generic::raw_protocol::socket raw_socket(io_context, raw_protocol); raw_socket.bind(device.endpoint(AF_PACKET)); if (name == "ethernet") { link_layer.reset(new RawSocketLink { std::move(raw_socket) }); } else if (name == "cohda") { #ifdef SOCKTAP_WITH_COHDA_LLC link_layer.reset(new CohdaLink { std::move(raw_socket) }); #endif } } else if (name == "udp") { namespace ip = boost::asio::ip; ip::udp::endpoint multicast(ip::make_address("239.118.122.97"), 8947); link_layer.reset(new UdpLink { io_context, multicast, device }); } else if (name == "tcp") { namespace ip = boost::asio::ip; TcpLink* tcp = new TcpLink { io_context }; if (vm.count("tcp-connect")) { for (const std::string& ip_port : vm["tcp-connect"].as>()) { auto ip_port_pair = parse_ip_port(ip_port); if (ip_port_pair) { tcp->connect(ip::tcp::endpoint(ip_port_pair.value().first, ip_port_pair.value().second)); } } } if (vm.count("tcp-accept")) { for (const std::string& ip_port : vm["tcp-accept"].as>()) { auto ip_port_pair = parse_ip_port(ip_port); if (ip_port_pair) { tcp->accept(ip::tcp::endpoint(ip_port_pair.value().first, ip_port_pair.value().second)); } } } link_layer.reset(tcp); } else if (name == "autotalks") { #ifdef SOCKTAP_WITH_AUTOTALKS link_layer.reset(new AutotalksLink { io_context }); #endif } else if (name == "cube-evk") { #ifdef SOCKTAP_WITH_CUBE_EVK link_layer.reset(new CubeEvkLink { io_context, boost::asio::ip::make_address(vm["cube-ip"].as()), vm["cube-tx-port"].as(), vm["cube-rx-port"].as() }); #endif } else if (name == "rpc") { #ifdef SOCKTAP_WITH_RPC boost::asio::ip::tcp::socket socket(io_context); boost::asio::ip::tcp::resolver resolver(io_context); auto rpc_host = vm["rpc-host"].as(); auto rpc_port = vm["rpc-port"].as(); auto endpoints = resolver.resolve(rpc_host, std::to_string(rpc_port)); boost::asio::connect(socket, endpoints); link_layer.reset(new RpcLinkLayer {io_context, std::move(socket)}); if (auto rpc_link_layer = static_cast(link_layer.get())) { rpc_link_layer->radio_technology(vm["rpc-radio-technology"].as()); rpc_link_layer->enable_debug(vm["rpc-debug"].as()); } #endif } return link_layer; } void add_link_layer_options(boost::program_options::options_description& options) { options.add_options() ("tcp-connect", boost::program_options::value>()->multitoken(), "Connect to TCP-Host(s). Comma separated list of [ip]:[port].") ("tcp-accept", boost::program_options::value>()->multitoken(), "Accept TCP-Connections. Comma separated list of [ip]:[port].") ; }