diff options
Diffstat (limited to 'test/packetimpact/dut/posix_server.cc')
-rw-r--r-- | test/packetimpact/dut/posix_server.cc | 464 |
1 files changed, 0 insertions, 464 deletions
diff --git a/test/packetimpact/dut/posix_server.cc b/test/packetimpact/dut/posix_server.cc deleted file mode 100644 index ea83bbe72..000000000 --- a/test/packetimpact/dut/posix_server.cc +++ /dev/null @@ -1,464 +0,0 @@ -// Copyright 2020 The gVisor Authors. -// -// 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 <arpa/inet.h> -#include <fcntl.h> -#include <getopt.h> -#include <netdb.h> -#include <netinet/in.h> -#include <poll.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <time.h> -#include <unistd.h> - -#include <iostream> -#include <unordered_map> - -#include "include/grpcpp/security/server_credentials.h" -#include "include/grpcpp/server_builder.h" -#include "include/grpcpp/server_context.h" -#include "absl/strings/str_format.h" -#include "test/packetimpact/proto/posix_server.grpc.pb.h" -#include "test/packetimpact/proto/posix_server.pb.h" - -// Converts a sockaddr_storage to a Sockaddr message. -::grpc::Status sockaddr_to_proto(const sockaddr_storage &addr, - socklen_t addrlen, - posix_server::Sockaddr *sockaddr_proto) { - switch (addr.ss_family) { - case AF_INET: { - auto addr_in = reinterpret_cast<const sockaddr_in *>(&addr); - auto response_in = sockaddr_proto->mutable_in(); - response_in->set_family(addr_in->sin_family); - response_in->set_port(ntohs(addr_in->sin_port)); - response_in->mutable_addr()->assign( - reinterpret_cast<const char *>(&addr_in->sin_addr.s_addr), 4); - return ::grpc::Status::OK; - } - case AF_INET6: { - auto addr_in6 = reinterpret_cast<const sockaddr_in6 *>(&addr); - auto response_in6 = sockaddr_proto->mutable_in6(); - response_in6->set_family(addr_in6->sin6_family); - response_in6->set_port(ntohs(addr_in6->sin6_port)); - response_in6->set_flowinfo(ntohl(addr_in6->sin6_flowinfo)); - response_in6->mutable_addr()->assign( - reinterpret_cast<const char *>(&addr_in6->sin6_addr.s6_addr), 16); - // sin6_scope_id is stored in host byte order. - // - // https://www.gnu.org/software/libc/manual/html_node/Internet-Address-Formats.html - response_in6->set_scope_id(addr_in6->sin6_scope_id); - return ::grpc::Status::OK; - } - } - return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Unknown Sockaddr"); -} - -::grpc::Status proto_to_sockaddr(const posix_server::Sockaddr &sockaddr_proto, - sockaddr_storage *addr, socklen_t *addr_len) { - switch (sockaddr_proto.sockaddr_case()) { - case posix_server::Sockaddr::SockaddrCase::kIn: { - auto proto_in = sockaddr_proto.in(); - if (proto_in.addr().size() != 4) { - return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, - "IPv4 address must be 4 bytes"); - } - auto addr_in = reinterpret_cast<sockaddr_in *>(addr); - addr_in->sin_family = proto_in.family(); - addr_in->sin_port = htons(proto_in.port()); - proto_in.addr().copy(reinterpret_cast<char *>(&addr_in->sin_addr.s_addr), - 4); - *addr_len = sizeof(*addr_in); - break; - } - case posix_server::Sockaddr::SockaddrCase::kIn6: { - auto proto_in6 = sockaddr_proto.in6(); - if (proto_in6.addr().size() != 16) { - return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, - "IPv6 address must be 16 bytes"); - } - auto addr_in6 = reinterpret_cast<sockaddr_in6 *>(addr); - addr_in6->sin6_family = proto_in6.family(); - addr_in6->sin6_port = htons(proto_in6.port()); - addr_in6->sin6_flowinfo = htonl(proto_in6.flowinfo()); - proto_in6.addr().copy( - reinterpret_cast<char *>(&addr_in6->sin6_addr.s6_addr), 16); - // sin6_scope_id is stored in host byte order. - // - // https://www.gnu.org/software/libc/manual/html_node/Internet-Address-Formats.html - addr_in6->sin6_scope_id = proto_in6.scope_id(); - *addr_len = sizeof(*addr_in6); - break; - } - case posix_server::Sockaddr::SockaddrCase::SOCKADDR_NOT_SET: - default: - return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, - "Unknown Sockaddr"); - } - return ::grpc::Status::OK; -} - -class PosixImpl final : public posix_server::Posix::Service { - ::grpc::Status Accept(grpc::ServerContext *context, - const ::posix_server::AcceptRequest *request, - ::posix_server::AcceptResponse *response) override { - sockaddr_storage addr; - socklen_t addrlen = sizeof(addr); - response->set_fd(accept(request->sockfd(), - reinterpret_cast<sockaddr *>(&addr), &addrlen)); - if (response->fd() < 0) { - response->set_errno_(errno); - } - return sockaddr_to_proto(addr, addrlen, response->mutable_addr()); - } - - ::grpc::Status Bind(grpc::ServerContext *context, - const ::posix_server::BindRequest *request, - ::posix_server::BindResponse *response) override { - if (!request->has_addr()) { - return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, - "Missing address"); - } - - sockaddr_storage addr; - socklen_t addr_len; - auto err = proto_to_sockaddr(request->addr(), &addr, &addr_len); - if (!err.ok()) { - return err; - } - - response->set_ret( - bind(request->sockfd(), reinterpret_cast<sockaddr *>(&addr), addr_len)); - if (response->ret() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } - - ::grpc::Status Close(grpc::ServerContext *context, - const ::posix_server::CloseRequest *request, - ::posix_server::CloseResponse *response) override { - response->set_ret(close(request->fd())); - if (response->ret() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } - - ::grpc::Status Connect(grpc::ServerContext *context, - const ::posix_server::ConnectRequest *request, - ::posix_server::ConnectResponse *response) override { - if (!request->has_addr()) { - return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, - "Missing address"); - } - sockaddr_storage addr; - socklen_t addr_len; - auto err = proto_to_sockaddr(request->addr(), &addr, &addr_len); - if (!err.ok()) { - return err; - } - - response->set_ret(connect(request->sockfd(), - reinterpret_cast<sockaddr *>(&addr), addr_len)); - if (response->ret() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } - - ::grpc::Status GetSockName( - grpc::ServerContext *context, - const ::posix_server::GetSockNameRequest *request, - ::posix_server::GetSockNameResponse *response) override { - sockaddr_storage addr; - socklen_t addrlen = sizeof(addr); - response->set_ret(getsockname( - request->sockfd(), reinterpret_cast<sockaddr *>(&addr), &addrlen)); - if (response->ret() < 0) { - response->set_errno_(errno); - } - return sockaddr_to_proto(addr, addrlen, response->mutable_addr()); - } - - ::grpc::Status GetSockOpt( - grpc::ServerContext *context, - const ::posix_server::GetSockOptRequest *request, - ::posix_server::GetSockOptResponse *response) override { - switch (request->type()) { - case ::posix_server::GetSockOptRequest::BYTES: { - socklen_t optlen = request->optlen(); - std::vector<char> buf(optlen); - response->set_ret(::getsockopt(request->sockfd(), request->level(), - request->optname(), buf.data(), - &optlen)); - if (optlen >= 0) { - response->mutable_optval()->set_bytesval(buf.data(), optlen); - } - break; - } - case ::posix_server::GetSockOptRequest::INT: { - int intval = 0; - socklen_t optlen = sizeof(intval); - response->set_ret(::getsockopt(request->sockfd(), request->level(), - request->optname(), &intval, &optlen)); - response->mutable_optval()->set_intval(intval); - break; - } - case ::posix_server::GetSockOptRequest::TIME: { - timeval tv; - socklen_t optlen = sizeof(tv); - response->set_ret(::getsockopt(request->sockfd(), request->level(), - request->optname(), &tv, &optlen)); - response->mutable_optval()->mutable_timeval()->set_seconds(tv.tv_sec); - response->mutable_optval()->mutable_timeval()->set_microseconds( - tv.tv_usec); - break; - } - default: - return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, - "Unknown SockOpt Type"); - } - if (response->ret() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } - - ::grpc::Status Listen(grpc::ServerContext *context, - const ::posix_server::ListenRequest *request, - ::posix_server::ListenResponse *response) override { - response->set_ret(listen(request->sockfd(), request->backlog())); - if (response->ret() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } - - ::grpc::Status Poll(::grpc::ServerContext *context, - const ::posix_server::PollRequest *request, - ::posix_server::PollResponse *response) override { - std::vector<struct pollfd> pfds; - pfds.reserve(request->pfds_size()); - for (const auto &pfd : request->pfds()) { - pfds.push_back({ - .fd = pfd.fd(), - .events = static_cast<short>(pfd.events()), - }); - } - int ret = ::poll(pfds.data(), pfds.size(), request->timeout_millis()); - - response->set_ret(ret); - if (ret < 0) { - response->set_errno_(errno); - } else { - // Only pollfds that have non-empty revents are returned, the client can't - // rely on indexes of the request array. - for (const auto &pfd : pfds) { - if (pfd.revents) { - auto *proto_pfd = response->add_pfds(); - proto_pfd->set_fd(pfd.fd); - proto_pfd->set_events(pfd.revents); - } - } - if (int ready = response->pfds_size(); ret != ready) { - return ::grpc::Status( - ::grpc::StatusCode::INTERNAL, - absl::StrFormat( - "poll's return value(%d) doesn't match the number of " - "file descriptors that are actually ready(%d)", - ret, ready)); - } - } - return ::grpc::Status::OK; - } - - ::grpc::Status Send(::grpc::ServerContext *context, - const ::posix_server::SendRequest *request, - ::posix_server::SendResponse *response) override { - response->set_ret(::send(request->sockfd(), request->buf().data(), - request->buf().size(), request->flags())); - if (response->ret() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } - - ::grpc::Status SendTo(::grpc::ServerContext *context, - const ::posix_server::SendToRequest *request, - ::posix_server::SendToResponse *response) override { - if (!request->has_dest_addr()) { - return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, - "Missing address"); - } - sockaddr_storage addr; - socklen_t addr_len; - auto err = proto_to_sockaddr(request->dest_addr(), &addr, &addr_len); - if (!err.ok()) { - return err; - } - - response->set_ret(::sendto(request->sockfd(), request->buf().data(), - request->buf().size(), request->flags(), - reinterpret_cast<sockaddr *>(&addr), addr_len)); - if (response->ret() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } - - ::grpc::Status SetNonblocking( - grpc::ServerContext *context, - const ::posix_server::SetNonblockingRequest *request, - ::posix_server::SetNonblockingResponse *response) override { - int flags = fcntl(request->fd(), F_GETFL); - if (flags == -1) { - response->set_ret(-1); - response->set_errno_(errno); - response->set_cmd("F_GETFL"); - return ::grpc::Status::OK; - } - if (request->nonblocking()) { - flags |= O_NONBLOCK; - } else { - flags &= ~O_NONBLOCK; - } - int ret = fcntl(request->fd(), F_SETFL, flags); - response->set_ret(ret); - if (ret == -1) { - response->set_errno_(errno); - response->set_cmd("F_SETFL"); - } - return ::grpc::Status::OK; - } - - ::grpc::Status SetSockOpt( - grpc::ServerContext *context, - const ::posix_server::SetSockOptRequest *request, - ::posix_server::SetSockOptResponse *response) override { - switch (request->optval().val_case()) { - case ::posix_server::SockOptVal::kBytesval: - response->set_ret(setsockopt(request->sockfd(), request->level(), - request->optname(), - request->optval().bytesval().c_str(), - request->optval().bytesval().size())); - break; - case ::posix_server::SockOptVal::kIntval: { - int opt = request->optval().intval(); - response->set_ret(::setsockopt(request->sockfd(), request->level(), - request->optname(), &opt, sizeof(opt))); - break; - } - case ::posix_server::SockOptVal::kTimeval: { - timeval tv = {.tv_sec = static_cast<time_t>( - request->optval().timeval().seconds()), - .tv_usec = static_cast<suseconds_t>( - request->optval().timeval().microseconds())}; - response->set_ret(setsockopt(request->sockfd(), request->level(), - request->optname(), &tv, sizeof(tv))); - break; - } - default: - return ::grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, - "Unknown SockOpt Type"); - } - if (response->ret() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } - - ::grpc::Status Socket(grpc::ServerContext *context, - const ::posix_server::SocketRequest *request, - ::posix_server::SocketResponse *response) override { - response->set_fd( - socket(request->domain(), request->type(), request->protocol())); - if (response->fd() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } - - ::grpc::Status Shutdown(grpc::ServerContext *context, - const ::posix_server::ShutdownRequest *request, - ::posix_server::ShutdownResponse *response) override { - response->set_ret(shutdown(request->fd(), request->how())); - if (response->ret() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } - - ::grpc::Status Recv(::grpc::ServerContext *context, - const ::posix_server::RecvRequest *request, - ::posix_server::RecvResponse *response) override { - std::vector<char> buf(request->len()); - response->set_ret( - recv(request->sockfd(), buf.data(), buf.size(), request->flags())); - if (response->ret() >= 0) { - response->set_buf(buf.data(), response->ret()); - } - if (response->ret() < 0) { - response->set_errno_(errno); - } - return ::grpc::Status::OK; - } -}; - -// Parse command line options. Returns a pointer to the first argument beyond -// the options. -void parse_command_line_options(int argc, char *argv[], std::string *ip, - int *port) { - static struct option options[] = {{"ip", required_argument, NULL, 1}, - {"port", required_argument, NULL, 2}, - {0, 0, 0, 0}}; - - // Parse the arguments. - int c; - while ((c = getopt_long(argc, argv, "", options, NULL)) > 0) { - if (c == 1) { - *ip = optarg; - } else if (c == 2) { - *port = std::stoi(std::string(optarg)); - } - } -} - -void run_server(const std::string &ip, int port) { - PosixImpl posix_service; - grpc::ServerBuilder builder; - std::string server_address = ip + ":" + std::to_string(port); - // Set the authentication mechanism. - std::shared_ptr<grpc::ServerCredentials> creds = - grpc::InsecureServerCredentials(); - builder.AddListeningPort(server_address, creds); - builder.RegisterService(&posix_service); - - std::unique_ptr<grpc::Server> server(builder.BuildAndStart()); - std::cerr << "Server listening on " << server_address << std::endl; - server->Wait(); - std::cerr << "posix_server is finished." << std::endl; -} - -int main(int argc, char *argv[]) { - std::cerr << "posix_server is starting." << std::endl; - std::string ip; - int port; - parse_command_line_options(argc, argv, &ip, &port); - - std::cerr << "Got IP " << ip << " and port " << port << "." << std::endl; - run_server(ip, port); -} |