blob: 818915ee5db33709d238611c85ecfed33abc8276 [file] [log] [blame]
William A. Kennington IIIdffd6522022-02-08 01:40:43 -08001// Copyright 2022 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <fmt/format.h>
16
17#include <sdeventplus/event.hpp>
18#include <sdeventplus/source/io.hpp>
19#include <stdplus/fd/create.hpp>
20#include <stdplus/fd/ops.hpp>
21
Yuxiao Zhang5ca20ff2023-03-30 14:54:11 -070022using namespace std::string_view_literals;
23
William A. Kennington IIIdffd6522022-02-08 01:40:43 -080024// A privileged port that is reserved for querying BMC DHCP completion.
25// This is well known by the clients querying the status.
26constexpr uint16_t kListenPort = 23;
Yuxiao Zhang5ca20ff2023-03-30 14:54:11 -070027enum : uint8_t
28{
29 DONE = 0,
30 POWERCYCLE = 1,
31};
William A. Kennington IIIdffd6522022-02-08 01:40:43 -080032
33stdplus::ManagedFd createListener()
34{
35 using namespace stdplus::fd;
Patrick Williams2be45232023-05-10 07:51:22 -050036 auto sock = socket(SocketDomain::INet6, SocketType::Stream,
37 SocketProto::TCP);
William A. Kennington IIIdffd6522022-02-08 01:40:43 -080038 setFileFlags(sock, getFileFlags(sock).set(stdplus::fd::FileFlag::NonBlock));
39 sockaddr_in6 addr = {};
40 addr.sin6_family = AF_INET6;
41 addr.sin6_port = htons(kListenPort);
42 bind(sock, addr);
43 listen(sock, 10);
44 return sock;
45}
46
Yuxiao Zhang5ca20ff2023-03-30 14:54:11 -070047int main(int argc, char* argv[])
William A. Kennington IIIdffd6522022-02-08 01:40:43 -080048{
Yuxiao Zhang5ca20ff2023-03-30 14:54:11 -070049 if (argc != 2)
50 {
51 fmt::print(stderr, "Invalid parameter count\n");
52 return 1;
53 }
54
55 std::vector<uint8_t> data;
56
57 if (argv[1] == "POWERCYCLE"sv)
58 {
59 data.push_back(POWERCYCLE);
60 }
61 else if (argv[1] == "DONE"sv)
62 {
63 data.push_back(DONE);
64 }
65 else
66 {
67 fmt::print(stderr, "Invalid parameter\n");
68 return 1;
69 }
70
William A. Kennington IIIdffd6522022-02-08 01:40:43 -080071 try
72 {
73 auto listener = createListener();
74 auto event = sdeventplus::Event::get_default();
75 sdeventplus::source::IO do_accept(
76 event, listener.get(), EPOLLIN | EPOLLET,
77 [&](sdeventplus::source::IO&, int, uint32_t) {
Patrick Williams2be45232023-05-10 07:51:22 -050078 while (auto fd = stdplus::fd::accept(listener))
79 {
80 stdplus::fd::sendExact(*fd, data, stdplus::fd::SendFlags(0));
81 }
William A. Kennington IIIdffd6522022-02-08 01:40:43 -080082 });
83 return event.loop();
84 }
85 catch (const std::exception& e)
86 {
87 fmt::print(stderr, "Failed: {}\n", e.what());
88 return 1;
89 }
90}