// Copyright 2022 Google LLC // // 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 #include #include #include #include using namespace std::string_view_literals; // A privileged port that is reserved for querying BMC DHCP completion. // This is well known by the clients querying the status. constexpr uint16_t kListenPort = 23; enum : uint8_t { DONE = 0, POWERCYCLE = 1, }; stdplus::ManagedFd createListener() { using namespace stdplus::fd; auto sock = socket(SocketDomain::INet6, SocketType::Stream, SocketProto::TCP); setFileFlags(sock, getFileFlags(sock).set(stdplus::fd::FileFlag::NonBlock)); sockaddr_in6 addr = {}; addr.sin6_family = AF_INET6; addr.sin6_port = htons(kListenPort); bind(sock, addr); listen(sock, 10); return sock; } int main(int argc, char* argv[]) { if (argc != 2) { fmt::print(stderr, "Invalid parameter count\n"); return 1; } std::vector data; if (argv[1] == "POWERCYCLE"sv) { data.push_back(POWERCYCLE); } else if (argv[1] == "DONE"sv) { data.push_back(DONE); } else { fmt::print(stderr, "Invalid parameter\n"); return 1; } try { auto listener = createListener(); auto event = sdeventplus::Event::get_default(); sdeventplus::source::IO do_accept( event, listener.get(), EPOLLIN | EPOLLET, [&](sdeventplus::source::IO&, int, uint32_t) { while (auto fd = stdplus::fd::accept(listener)) { stdplus::fd::sendExact(*fd, data, stdplus::fd::SendFlags(0)); } }); return event.loop(); } catch (const std::exception& e) { fmt::print(stderr, "Failed: {}\n", e.what()); return 1; } }