blob: 4de9400459478b3fbad3ca742232ffa63281a7d4 [file] [log] [blame]
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001#include <stdio.h>
2#include <string.h>
3#include <stdint.h>
Hariharasubramanian R83951912016-01-20 07:06:36 -06004#include <arpa/inet.h>
tomjose26e17732016-03-03 08:52:51 -06005#include <string>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05006
Patrick Williams37af7332016-09-02 21:21:42 -05007#include "host-ipmid/ipmid-api.h"
Patrick Williams53a360e2016-08-12 22:01:02 -05008#include "ipmid.hpp"
Ratan Guptab8e99552017-07-27 07:07:48 +05309#include "transporthandler.hpp"
10#include "utils.hpp"
11
12#include <phosphor-logging/log.hpp>
13#include <phosphor-logging/elog-errors.hpp>
14#include "xyz/openbmc_project/Common/error.hpp"
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050015
Hariharasubramanian R83951912016-01-20 07:06:36 -060016#define SYSTEMD_NETWORKD_DBUS 1
17
18#ifdef SYSTEMD_NETWORKD_DBUS
19#include <systemd/sd-bus.h>
Sergey Solomineb9b8142016-08-23 09:07:28 -050020#include <mapper.h>
Hariharasubramanian R83951912016-01-20 07:06:36 -060021#endif
22
23// OpenBMC System Manager dbus framework
Hariharasubramanian R83951912016-01-20 07:06:36 -060024const char *obj = "/org/openbmc/NetworkManager/Interface";
25const char *ifc = "org.openbmc.NetworkManager";
26
tomjose26e17732016-03-03 08:52:51 -060027const char *nwinterface = "eth0";
28
Adriana Kobylake08fbc62016-02-09 16:17:23 -060029const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx
Adriana Kobylake08fbc62016-02-09 16:17:23 -060030
Ratan Guptab8e99552017-07-27 07:07:48 +053031struct ChannelConfig_t channelConfig;
Hariharasubramanian R83951912016-01-20 07:06:36 -060032
tomjose26e17732016-03-03 08:52:51 -060033const uint8_t SET_COMPLETE = 0;
34const uint8_t SET_IN_PROGRESS = 1;
35const uint8_t SET_COMMIT_WRITE = 2; //Optional
36const uint8_t SET_IN_PROGRESS_RESERVED = 3; //Reserved
37
38// Status of Set-In-Progress Parameter (# 0)
39uint8_t lan_set_in_progress = SET_COMPLETE;
40
Ratan Guptab8e99552017-07-27 07:07:48 +053041using namespace phosphor::logging;
42using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Hariharasubramanian R83951912016-01-20 07:06:36 -060043
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050044void register_netfn_transport_functions() __attribute__((constructor));
45
Ratan Guptab8e99552017-07-27 07:07:48 +053046// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network Manager or
Nan Li3d0df912016-10-18 19:51:41 +080047// Cache based on Set-In-Progress State
Ratan Guptab8e99552017-07-27 07:07:48 +053048ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data)
tomjose26e17732016-03-03 08:52:51 -060049{
tomjose26e17732016-03-03 08:52:51 -060050 ipmi_ret_t rc = IPMI_CC_OK;
Ratan Guptab8e99552017-07-27 07:07:48 +053051 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
52 try
tomjose26e17732016-03-03 08:52:51 -060053 {
Ratan Guptab8e99552017-07-27 07:07:48 +053054 switch (lan_param)
tomjose26e17732016-03-03 08:52:51 -060055 {
Ratan Guptab8e99552017-07-27 07:07:48 +053056 case LAN_PARM_IP:
57 {
58 std::string ipaddress;
59 if (lan_set_in_progress == SET_COMPLETE)
60 {
61 auto ipObjectInfo = ipmi::getDbusObject(
62 bus,
63 ipmi::network::IP_INTERFACE,
64 ipmi::network::ROOT,
65 ipmi::network::IP_TYPE);
66
67 auto properties = ipmi::getAllDbusProperties(
68 bus,
69 ipObjectInfo.second,
70 ipObjectInfo.first,
71 ipmi::network::IP_INTERFACE);
72
73 ipaddress = properties["Address"].get<std::string>();
74 }
75 else if (lan_set_in_progress == SET_IN_PROGRESS)
76 {
77 ipaddress = channelConfig.ipaddr;
78 }
79
80 inet_pton(AF_INET, ipaddress.c_str(),
81 reinterpret_cast<void*>(data));
82 }
83 break;
84
85 case LAN_PARM_SUBNET:
86 {
87 if (lan_set_in_progress == SET_COMPLETE)
88 {
89 auto ipObjectInfo = ipmi::getDbusObject(
90 bus,
91 ipmi::network::IP_INTERFACE,
92 ipmi::network::ROOT,
93 ipmi::network::IP_TYPE);
94
95 auto properties = ipmi::getAllDbusProperties(
96 bus,
97 ipObjectInfo.second,
98 ipObjectInfo.first,
99 ipmi::network::IP_INTERFACE);
100
101 auto prefix = properties["PrefixLength"].get<uint8_t>();
102 unsigned long mask = ipmi::network::MASK_32_BIT;
103 mask = htonl(mask << (ipmi::network::BITS_32 - prefix));
104 memcpy(data, &mask, ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
105 }
106 else if (lan_set_in_progress == SET_IN_PROGRESS)
107 {
108 inet_pton(AF_INET, channelConfig.netmask.c_str(),
109 reinterpret_cast<void*>(data));
110
111 }
112
113 }
114 break;
115
116 case LAN_PARM_GATEWAY:
117 {
118 std::string gateway;
119
120 if (lan_set_in_progress == SET_COMPLETE)
121 {
122 auto systemObject = ipmi::getDbusObject(
123 bus,
124 ipmi::network::SYSTEMCONFIG_INTERFACE,
125 ipmi::network::ROOT);
126
127 auto systemProperties = ipmi::getAllDbusProperties(
128 bus,
129 systemObject.second,
130 systemObject.first,
131 ipmi::network::SYSTEMCONFIG_INTERFACE);
132
133 gateway = systemProperties["DefaultGateway"].get<
134 std::string>();
135
136 }
137 else if (lan_set_in_progress == SET_IN_PROGRESS)
138 {
139 gateway = channelConfig.gateway;
140 }
141
142 inet_pton(AF_INET, gateway.c_str(),
143 reinterpret_cast<void*>(data));
144
145 }
146 break;
147
148 case LAN_PARM_MAC:
149 {
150 std::string macAddress;
151 if (lan_set_in_progress == SET_COMPLETE)
152 {
153 auto macObjectInfo = ipmi::getDbusObject(
154 bus,
155 ipmi::network::MAC_INTERFACE,
156 ipmi::network::ROOT);
157
158 auto variant = ipmi::getDbusProperty(
159 bus,
160 macObjectInfo.second,
161 macObjectInfo.first,
162 ipmi::network::MAC_INTERFACE,
163 "MACAddress");
164
165 macAddress = variant.get<std::string>();
166
167 }
168 else if (lan_set_in_progress == SET_IN_PROGRESS)
169 {
170 macAddress = channelConfig.macAddress;
171 }
172
173 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
174 (data),
175 (data + 1),
176 (data + 2),
177 (data + 3),
178 (data + 4),
179 (data + 5));
180 }
181 break;
182
183 default:
184 rc = IPMI_CC_PARM_OUT_OF_RANGE;
tomjose26e17732016-03-03 08:52:51 -0600185 }
186 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530187 catch (InternalFailure& e)
tomjose26e17732016-03-03 08:52:51 -0600188 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530189 commit<InternalFailure>();
190 rc = IPMI_CC_UNSPECIFIED_ERROR;
191 return rc;
tomjose26e17732016-03-03 08:52:51 -0600192 }
tomjose26e17732016-03-03 08:52:51 -0600193 return rc;
194}
195
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500196ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
197 ipmi_request_t request, ipmi_response_t response,
198 ipmi_data_len_t data_len, ipmi_context_t context)
199{
200 printf("Handling TRANSPORT WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
201 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800202 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500203 *data_len = 0;
204 return rc;
205}
206
Ratan Guptab8e99552017-07-27 07:07:48 +0530207struct set_lan_t
208{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500209 uint8_t channel;
210 uint8_t parameter;
211 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
Ratan Guptab8e99552017-07-27 07:07:48 +0530212} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500213
Ratan Guptab8e99552017-07-27 07:07:48 +0530214ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn,
215 ipmi_cmd_t cmd,
216 ipmi_request_t request,
217 ipmi_response_t response,
218 ipmi_data_len_t data_len,
219 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500220{
221 ipmi_ret_t rc = IPMI_CC_OK;
222 *data_len = 0;
Nan Li3d0df912016-10-18 19:51:41 +0800223
Ratan Guptab8e99552017-07-27 07:07:48 +0530224 char ipaddr[INET_ADDRSTRLEN];
225 char netmask[INET_ADDRSTRLEN];
226 char gateway[INET_ADDRSTRLEN];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500227
Ratan Guptab8e99552017-07-27 07:07:48 +0530228 auto reqptr = reinterpret_cast<const set_lan_t*>(request);
229 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500230
Ratan Guptab8e99552017-07-27 07:07:48 +0530231 switch (reqptr->parameter)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500232 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530233 case LAN_PARM_IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600234 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530235 snprintf(ipaddr, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
236 reqptr->data[0], reqptr->data[1],
237 reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500238
Ratan Guptab8e99552017-07-27 07:07:48 +0530239 channelConfig.ipaddr.assign(ipaddr);
240
241 }
242 break;
243
244 case LAN_PARM_MAC:
245 {
246 char mac[SIZE_MAC];
247
248 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
249 reqptr->data[0],
250 reqptr->data[1],
251 reqptr->data[2],
252 reqptr->data[3],
253 reqptr->data[4],
254 reqptr->data[5]);
255
256 auto macObjectInfo = ipmi::getDbusObject(
257 bus,
258 ipmi::network::MAC_INTERFACE,
259 ipmi::network::ROOT,
260 ipmi::network::INTERFACE);
261
262 ipmi::setDbusProperty(bus,
263 macObjectInfo.second,
264 macObjectInfo.first,
265 ipmi::network::MAC_INTERFACE,
266 "MACAddress",
267 std::string(mac));
268
269 channelConfig.macAddress = mac;
270
271 }
272 break;
273
274 case LAN_PARM_SUBNET:
275 {
276 snprintf(netmask, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
277 reqptr->data[0], reqptr->data[1],
278 reqptr->data[2], reqptr->data[3]);
279 channelConfig.netmask.assign(netmask);
280 }
281 break;
282
283 case LAN_PARM_GATEWAY:
284 {
285 snprintf(gateway, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
286 reqptr->data[0], reqptr->data[1],
287 reqptr->data[2], reqptr->data[3]);
288 channelConfig.gateway.assign(gateway);
289
290 }
291 break;
292
293 case LAN_PARM_INPROGRESS:
294 {
295 if (reqptr->data[0] == SET_COMPLETE)
296 {
297 lan_set_in_progress = SET_COMPLETE;
298
299 log<level::INFO>("Network data from Cache",
300 entry("PREFIX=%s", channelConfig.netmask.c_str()),
301 entry("ADDRESS=%s", channelConfig.ipaddr.c_str()),
302 entry("GATEWAY=%s", channelConfig.gateway.c_str()));
303
304 log<level::INFO>("Use Set Channel Access command to apply");
305
306 }
307 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
308 {
309 lan_set_in_progress = SET_IN_PROGRESS;
310 }
311
312 }
313 break;
314
315 default:
316 {
317 log<level::ERR>("Unsupported parameter",
318 entry("PARAMETER=0x%x", reqptr->parameter));
319 rc = IPMI_CC_PARM_NOT_SUPPORTED;
320 }
321
322 }
vishwa1eaea4f2016-02-26 11:57:40 -0600323
tomjose26e17732016-03-03 08:52:51 -0600324 return rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500325}
326
Ratan Guptab8e99552017-07-27 07:07:48 +0530327struct get_lan_t
328{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500329 uint8_t rev_channel;
330 uint8_t parameter;
331 uint8_t parameter_set;
332 uint8_t parameter_block;
Ratan Guptab8e99552017-07-27 07:07:48 +0530333} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500334
Ratan Guptab8e99552017-07-27 07:07:48 +0530335ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn,
336 ipmi_cmd_t cmd,
337 ipmi_request_t request,
338 ipmi_response_t response,
339 ipmi_data_len_t data_len,
340 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500341{
342 ipmi_ret_t rc = IPMI_CC_OK;
343 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500344 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500345
346 get_lan_t *reqptr = (get_lan_t*) request;
347
348 if (reqptr->rev_channel & 0x80) // Revision is bit 7
349 {
350 // Only current revision was requested
351 *data_len = sizeof(current_revision);
352 memcpy(response, &current_revision, *data_len);
353 return IPMI_CC_OK;
354 }
355
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600356 if (reqptr->parameter == LAN_PARM_INPROGRESS)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500357 {
tomjose26e17732016-03-03 08:52:51 -0600358 uint8_t buf[] = {current_revision, lan_set_in_progress};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500359 *data_len = sizeof(buf);
360 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500361 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600362 else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500363 {
364 uint8_t buf[] = {current_revision,0x04};
365 *data_len = sizeof(buf);
366 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500367 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600368 else if (reqptr->parameter == LAN_PARM_AUTHENABLES)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500369 {
370 uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04};
371 *data_len = sizeof(buf);
372 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500373 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530374 else if ((reqptr->parameter == LAN_PARM_IP) ||
375 (reqptr->parameter == LAN_PARM_SUBNET) ||
376 (reqptr->parameter == LAN_PARM_GATEWAY) ||
377 (reqptr->parameter == LAN_PARM_MAC))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500378 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530379 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500380
tomjose26e17732016-03-03 08:52:51 -0600381 *data_len = sizeof(current_revision);
382 memcpy(buf, &current_revision, *data_len);
383
Ratan Guptab8e99552017-07-27 07:07:48 +0530384 if (getNetworkData(reqptr->parameter, &buf[1]) == IPMI_CC_OK)
vishwa1eaea4f2016-02-26 11:57:40 -0600385 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530386 if (reqptr->parameter == LAN_PARM_MAC)
387 {
388 *data_len = sizeof(buf);
389 }
390 else
391 {
392 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1;
393 }
tomjose26e17732016-03-03 08:52:51 -0600394 memcpy(response, &buf, *data_len);
Adriana Kobylak342df102016-02-10 13:48:16 -0600395 }
tomjose26e17732016-03-03 08:52:51 -0600396 else
Hariharasubramanian R83951912016-01-20 07:06:36 -0600397 {
tomjose26e17732016-03-03 08:52:51 -0600398 rc = IPMI_CC_UNSPECIFIED_ERROR;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600399 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500400 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500401 else
402 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530403 log<level::ERR>("Unsupported parameter",
404 entry("PARAMETER=0x%x", reqptr->parameter));
vishwa1eaea4f2016-02-26 11:57:40 -0600405 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500406 }
407
408 return rc;
409}
410
411void register_netfn_transport_functions()
412{
Tom05732372016-09-06 17:21:23 +0530413 // <Wildcard Command>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500414 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_WILDCARD);
Tom05732372016-09-06 17:21:23 +0530415 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard,
416 PRIVILEGE_USER);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500417
Tom05732372016-09-06 17:21:23 +0530418 // <Set LAN Configuration Parameters>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500419 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_SET_LAN);
Tom05732372016-09-06 17:21:23 +0530420 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan,
421 PRIVILEGE_ADMIN);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500422
Tom05732372016-09-06 17:21:23 +0530423 // <Get LAN Configuration Parameters>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500424 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_GET_LAN);
Tom05732372016-09-06 17:21:23 +0530425 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan,
426 PRIVILEGE_OPERATOR);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500427
428 return;
429}