blob: ba46f733536aa84a1d0ff3ddfba81904fa228b05 [file] [log] [blame]
Patrick Venture4d49ae62018-09-17 11:35:32 -07001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "eth.hpp"
18
19#include "main.hpp"
20
21#include <cstdint>
22#include <string>
23
24namespace google
25{
26namespace ipmi
27{
28
29struct EthDeviceRequest
30{
31 uint8_t subcommand;
32} __attribute__((packed));
33
34// The reply to the ethdevice command specifies the
35// IPMI channel number and the if_name used for the
36// ncis connection.
37struct EthDeviceReply
38{
39 uint8_t subcommand;
40 uint8_t channel;
41 // if_name_len doesn't include the null-terminator.
42 uint8_t if_name_len;
43 uint8_t if_name[0];
44} __attribute__((packed));
45
46// The phosphor-host-ipmi daemon requires a configuration that maps
47// the if_name to the IPMI LAN channel. However, that doesn't strictly
48// define which is meant to be used for NCSI.
49#ifndef NCSI_IPMI_CHANNEL
50#define NCSI_IPMI_CHANNEL 1
51#endif
52
53#ifndef NCSI_IF_NAME
54#define NCSI_IF_NAME eth0
55#endif
56
57// TOOD(venture): The ipmid.h has this macro, which is a header we
58// can't normally access.
59#ifndef MAX_IPMI_BUFFER
60#define MAX_IPMI_BUFFER 64
61#endif
62
63// To deal with receiving a string without quotes.
64#define QUOTE(name) #name
65#define STR(macro) QUOTE(macro)
66#define NCSI_IF_NAME_STR STR(NCSI_IF_NAME)
67
68ipmi_ret_t GetEthDevice(const uint8_t* reqBuf, uint8_t* replyBuf,
69 size_t* dataLen)
70{
71 if ((*dataLen) < sizeof(struct EthDeviceRequest))
72 {
Patrick Venture0dede332018-09-17 15:28:35 -070073 fprintf(stderr, "Invalid command length: %u\n",
74 static_cast<uint32_t>(*dataLen));
Patrick Venture4d49ae62018-09-17 11:35:32 -070075 return IPMI_CC_INVALID;
76 }
77
78 std::string device = NCSI_IF_NAME_STR;
79 if (device.length() == 0)
80 {
81 fprintf(stderr, "Invalid eth string\n");
82 return IPMI_CC_INVALID;
83 }
84
85 if ((sizeof(struct EthDeviceReply) + device.length()) > MAX_IPMI_BUFFER)
86 {
87 fprintf(stderr, "Response would overflow response buffer\n");
88 return IPMI_CC_INVALID;
89 }
90
91 // Fill in the response buffer.
92 auto reply = reinterpret_cast<struct EthDeviceReply*>(&replyBuf[0]);
93 reply->subcommand = SysGetEthDevice;
94 reply->channel = NCSI_IPMI_CHANNEL;
95 reply->if_name_len = device.length();
96 memcpy(reply->if_name, device.c_str(), device.length());
97
98 (*dataLen) = sizeof(struct EthDeviceReply) + device.length();
99
100 return IPMI_CC_OK;
101}
102
103} // namespace ipmi
104} // namespace google