blob: f4326c1c2983bf24e216495531e8edcc0ede7ee6 [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>
Ratan Guptacc6cdbf2017-09-01 23:06:25 +05306#include <experimental/filesystem>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05007
Patrick Williams37af7332016-09-02 21:21:42 -05008#include "host-ipmid/ipmid-api.h"
Patrick Williams53a360e2016-08-12 22:01:02 -05009#include "ipmid.hpp"
Ratan Guptab8e99552017-07-27 07:07:48 +053010#include "transporthandler.hpp"
11#include "utils.hpp"
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080012#include "net.hpp"
Ratan Guptab8e99552017-07-27 07:07:48 +053013
14#include <phosphor-logging/log.hpp>
15#include <phosphor-logging/elog-errors.hpp>
16#include "xyz/openbmc_project/Common/error.hpp"
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050017
Hariharasubramanian R83951912016-01-20 07:06:36 -060018#define SYSTEMD_NETWORKD_DBUS 1
19
20#ifdef SYSTEMD_NETWORKD_DBUS
21#include <systemd/sd-bus.h>
Sergey Solomineb9b8142016-08-23 09:07:28 -050022#include <mapper.h>
Hariharasubramanian R83951912016-01-20 07:06:36 -060023#endif
24
Adriana Kobylake08fbc62016-02-09 16:17:23 -060025const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx
Adriana Kobylake08fbc62016-02-09 16:17:23 -060026
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080027std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
Hariharasubramanian R83951912016-01-20 07:06:36 -060028
Ratan Guptab8e99552017-07-27 07:07:48 +053029using namespace phosphor::logging;
30using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053031namespace fs = std::experimental::filesystem;
Hariharasubramanian R83951912016-01-20 07:06:36 -060032
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050033void register_netfn_transport_functions() __attribute__((constructor));
34
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080035struct ChannelConfig_t* getChannelConfig(int channel)
36{
37 auto item = channelConfig.find(channel);
38 if (item == channelConfig.end())
39 {
40 channelConfig[channel] = std::make_unique<struct ChannelConfig_t>();
41 }
42
43 return channelConfig[channel].get();
44}
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
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080048ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel)
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());
Ratan Gupta533d03b2017-07-30 10:39:22 +053052
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080053 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
54 // if ethdevice is an empty string they weren't expecting this channel.
55 if (ethdevice.empty())
56 {
57 // TODO: return error from getNetworkData()
58 return IPMI_CC_INVALID_FIELD_REQUEST;
59 }
60 auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE;
61 auto channelConf = getChannelConfig(channel);
62
Ratan Guptab8e99552017-07-27 07:07:48 +053063 try
tomjose26e17732016-03-03 08:52:51 -060064 {
Ratan Guptab8e99552017-07-27 07:07:48 +053065 switch (lan_param)
tomjose26e17732016-03-03 08:52:51 -060066 {
Ratan Guptab8e99552017-07-27 07:07:48 +053067 case LAN_PARM_IP:
68 {
69 std::string ipaddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080070 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +053071 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053072 try
73 {
Ratan Guptadd646202017-11-21 17:46:59 +053074 auto ipObjectInfo = ipmi::getIPObject(
75 bus,
76 ipmi::network::IP_INTERFACE,
77 ipmi::network::ROOT,
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080078 ethIP);
Ratan Guptadd646202017-11-21 17:46:59 +053079
80 auto properties = ipmi::getAllDbusProperties(
81 bus,
82 ipObjectInfo.second,
83 ipObjectInfo.first,
84 ipmi::network::IP_INTERFACE);
85
86 ipaddress = properties["Address"].get<std::string>();
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053087 }
88 // ignore the exception, as it is a valid condtion that
89 // system is not confiured with any ip.
90 catch (InternalFailure& e)
91 {
92 // nothing to do.
93 }
Ratan Guptab8e99552017-07-27 07:07:48 +053094 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080095 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +053096 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080097 ipaddress = channelConf->ipaddr;
Ratan Guptab8e99552017-07-27 07:07:48 +053098 }
99
100 inet_pton(AF_INET, ipaddress.c_str(),
101 reinterpret_cast<void*>(data));
102 }
103 break;
104
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530105 case LAN_PARM_IPSRC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530106 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530107 std::string networkInterfacePath;
108
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800109 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530110 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530111 try
112 {
113 ipmi::ObjectTree ancestorMap;
114 // if the system is having ip object,then
115 // get the IP object.
116 auto ipObject = ipmi::getDbusObject(
117 bus,
118 ipmi::network::IP_INTERFACE,
119 ipmi::network::ROOT,
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800120 ethIP);
Ratan Guptab8e99552017-07-27 07:07:48 +0530121
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530122 // Get the parent interface of the IP object.
123 try
124 {
125 ipmi::InterfaceList interfaces;
126 interfaces.emplace_back(
127 ipmi::network::ETHERNET_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530128
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530129 ancestorMap = ipmi::getAllAncestors(
130 bus,
131 ipObject.first,
132 std::move(interfaces));
133 }
134 catch (InternalFailure& e)
135 {
136 // if unable to get the parent interface
137 // then commit the error and return.
138 log<level::ERR>("Unable to get the parent interface",
139 entry("PATH=%s", ipObject.first.c_str()),
140 entry("INTERFACE=%s",
141 ipmi::network::ETHERNET_INTERFACE));
142 break;
143
144 }
145 // for an ip object there would be single parent
146 // interface.
147 networkInterfacePath = ancestorMap.begin()->first;
148 }
149 catch (InternalFailure& e)
150 {
151 // if there is no ip configured on the system,then
152 // get the network interface object.
153 auto networkInterfaceObject = ipmi::getDbusObject(
154 bus,
155 ipmi::network::ETHERNET_INTERFACE,
156 ipmi::network::ROOT,
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800157 ethdevice);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530158
159 networkInterfacePath = networkInterfaceObject.first;
160 }
161
162 auto variant = ipmi::getDbusProperty(
163 bus,
164 ipmi::network::SERVICE,
165 networkInterfacePath,
166 ipmi::network::ETHERNET_INTERFACE,
167 "DHCPEnabled");
168
169 auto dhcpEnabled = variant.get<bool>();
170 // As per IPMI spec 2=>DHCP, 1=STATIC
171 auto ipsrc = dhcpEnabled ? ipmi::network::IPOrigin::DHCP :
172 ipmi::network::IPOrigin::STATIC;
173
174 memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE);
175 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800176 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530177 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800178 memcpy(data, &(channelConf->ipsrc),
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530179 ipmi::network::IPSRC_SIZE_BYTE);
180 }
181 }
182 break;
183
184 case LAN_PARM_SUBNET:
185 {
186 unsigned long mask {};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800187 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530188 {
189 try
190 {
Ratan Guptadd646202017-11-21 17:46:59 +0530191 auto ipObjectInfo = ipmi::getIPObject(
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530192 bus,
193 ipmi::network::IP_INTERFACE,
194 ipmi::network::ROOT,
195 ipmi::network::IP_TYPE);
196
197 auto properties = ipmi::getAllDbusProperties(
198 bus,
199 ipObjectInfo.second,
200 ipObjectInfo.first,
201 ipmi::network::IP_INTERFACE);
202
203 auto prefix = properties["PrefixLength"].get<uint8_t>();
204 mask = ipmi::network::MASK_32_BIT;
205 mask = htonl(mask << (ipmi::network::BITS_32 - prefix));
206 }
207 // ignore the exception, as it is a valid condtion that
208 // system is not confiured with any ip.
209 catch (InternalFailure& e)
210 {
211 // nothing to do
212 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530213 memcpy(data, &mask, ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
214 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800215 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530216 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800217 inet_pton(AF_INET, channelConf->netmask.c_str(),
Ratan Guptab8e99552017-07-27 07:07:48 +0530218 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530219 }
220
221 }
222 break;
223
224 case LAN_PARM_GATEWAY:
225 {
226 std::string gateway;
227
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800228 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530229 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530230 try
231 {
232 auto systemObject = ipmi::getDbusObject(
233 bus,
234 ipmi::network::SYSTEMCONFIG_INTERFACE,
235 ipmi::network::ROOT);
Ratan Guptab8e99552017-07-27 07:07:48 +0530236
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530237 auto systemProperties = ipmi::getAllDbusProperties(
238 bus,
239 systemObject.second,
240 systemObject.first,
241 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530242
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530243 gateway = systemProperties["DefaultGateway"].get<
244 std::string>();
245 }
246 // ignore the exception, as it is a valid condtion that
247 // system is not confiured with any ip.
248 catch (InternalFailure& e)
249 {
250 // nothing to do
251 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530252
253 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800254 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530255 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800256 gateway = channelConf->gateway;
Ratan Guptab8e99552017-07-27 07:07:48 +0530257 }
258
259 inet_pton(AF_INET, gateway.c_str(),
260 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530261 }
262 break;
263
264 case LAN_PARM_MAC:
265 {
266 std::string macAddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800267 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530268 {
269 auto macObjectInfo = ipmi::getDbusObject(
270 bus,
271 ipmi::network::MAC_INTERFACE,
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800272 ipmi::network::ROOT,
273 ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530274
275 auto variant = ipmi::getDbusProperty(
276 bus,
277 macObjectInfo.second,
278 macObjectInfo.first,
279 ipmi::network::MAC_INTERFACE,
280 "MACAddress");
281
282 macAddress = variant.get<std::string>();
283
284 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800285 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530286 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800287 macAddress = channelConf->macAddress;
Ratan Guptab8e99552017-07-27 07:07:48 +0530288 }
289
290 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
291 (data),
292 (data + 1),
293 (data + 2),
294 (data + 3),
295 (data + 4),
296 (data + 5));
297 }
298 break;
299
Ratan Gupta533d03b2017-07-30 10:39:22 +0530300 case LAN_PARM_VLAN:
301 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530302 uint16_t vlanID {};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800303 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530304 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530305 try
Ratan Gupta533d03b2017-07-30 10:39:22 +0530306 {
Ratan Guptadd646202017-11-21 17:46:59 +0530307 auto ipObjectInfo = ipmi::getIPObject(
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530308 bus,
309 ipmi::network::IP_INTERFACE,
310 ipmi::network::ROOT,
311 ipmi::network::IP_TYPE);
312
313 vlanID = static_cast<uint16_t>(
314 ipmi::network::getVLAN(ipObjectInfo.first));
315
316 vlanID = htole16(vlanID);
317
318 if (vlanID)
319 {
320 //Enable the 16th bit
321 vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK);
322 }
323 }
324 // ignore the exception, as it is a valid condtion that
325 // system is not confiured with any ip.
326 catch (InternalFailure& e)
327 {
328 // nothing to do
Ratan Gupta533d03b2017-07-30 10:39:22 +0530329 }
330
331 memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
332 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800333 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530334 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800335 memcpy(data, &(channelConf->vlanID),
Ratan Gupta533d03b2017-07-30 10:39:22 +0530336 ipmi::network::VLAN_SIZE_BYTE);
337 }
338 }
339 break;
340
Ratan Guptab8e99552017-07-27 07:07:48 +0530341 default:
342 rc = IPMI_CC_PARM_OUT_OF_RANGE;
tomjose26e17732016-03-03 08:52:51 -0600343 }
344 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530345 catch (InternalFailure& e)
tomjose26e17732016-03-03 08:52:51 -0600346 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530347 commit<InternalFailure>();
348 rc = IPMI_CC_UNSPECIFIED_ERROR;
349 return rc;
tomjose26e17732016-03-03 08:52:51 -0600350 }
tomjose26e17732016-03-03 08:52:51 -0600351 return rc;
352}
353
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500354ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
355 ipmi_request_t request, ipmi_response_t response,
356 ipmi_data_len_t data_len, ipmi_context_t context)
357{
358 printf("Handling TRANSPORT WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
359 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800360 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500361 *data_len = 0;
362 return rc;
363}
364
Ratan Guptab8e99552017-07-27 07:07:48 +0530365struct set_lan_t
366{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500367 uint8_t channel;
368 uint8_t parameter;
369 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
Ratan Guptab8e99552017-07-27 07:07:48 +0530370} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500371
Ratan Guptab8e99552017-07-27 07:07:48 +0530372ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn,
373 ipmi_cmd_t cmd,
374 ipmi_request_t request,
375 ipmi_response_t response,
376 ipmi_data_len_t data_len,
377 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500378{
379 ipmi_ret_t rc = IPMI_CC_OK;
380 *data_len = 0;
Nan Li3d0df912016-10-18 19:51:41 +0800381
Ratan Guptab8e99552017-07-27 07:07:48 +0530382 char ipaddr[INET_ADDRSTRLEN];
383 char netmask[INET_ADDRSTRLEN];
384 char gateway[INET_ADDRSTRLEN];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500385
Ratan Guptab8e99552017-07-27 07:07:48 +0530386 auto reqptr = reinterpret_cast<const set_lan_t*>(request);
387 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500388
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800389 // channel number is the lower nibble
390 int channel = reqptr->channel & CHANNEL_MASK;
391 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
392 if (ethdevice.empty())
393 {
394 return IPMI_CC_INVALID_FIELD_REQUEST;
395 }
396 auto channelConf = getChannelConfig(channel);
397
Ratan Guptab8e99552017-07-27 07:07:48 +0530398 switch (reqptr->parameter)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500399 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530400 case LAN_PARM_IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600401 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530402 snprintf(ipaddr, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
403 reqptr->data[0], reqptr->data[1],
404 reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500405
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800406 channelConf->ipaddr.assign(ipaddr);
Ratan Guptab8e99552017-07-27 07:07:48 +0530407 }
408 break;
409
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530410 case LAN_PARM_IPSRC:
411 {
412 uint8_t ipsrc{};
413 memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800414 channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530415 }
416 break;
417
Ratan Guptab8e99552017-07-27 07:07:48 +0530418 case LAN_PARM_MAC:
419 {
420 char mac[SIZE_MAC];
421
422 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
423 reqptr->data[0],
424 reqptr->data[1],
425 reqptr->data[2],
426 reqptr->data[3],
427 reqptr->data[4],
428 reqptr->data[5]);
429
430 auto macObjectInfo = ipmi::getDbusObject(
431 bus,
432 ipmi::network::MAC_INTERFACE,
433 ipmi::network::ROOT,
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800434 ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530435
436 ipmi::setDbusProperty(bus,
437 macObjectInfo.second,
438 macObjectInfo.first,
439 ipmi::network::MAC_INTERFACE,
440 "MACAddress",
441 std::string(mac));
442
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800443 channelConf->macAddress = mac;
Ratan Guptab8e99552017-07-27 07:07:48 +0530444 }
445 break;
446
447 case LAN_PARM_SUBNET:
448 {
449 snprintf(netmask, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
450 reqptr->data[0], reqptr->data[1],
451 reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800452 channelConf->netmask.assign(netmask);
Ratan Guptab8e99552017-07-27 07:07:48 +0530453 }
454 break;
455
456 case LAN_PARM_GATEWAY:
457 {
458 snprintf(gateway, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
459 reqptr->data[0], reqptr->data[1],
460 reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800461 channelConf->gateway.assign(gateway);
Ratan Guptab8e99552017-07-27 07:07:48 +0530462 }
463 break;
464
Ratan Gupta533d03b2017-07-30 10:39:22 +0530465 case LAN_PARM_VLAN:
466 {
467 uint16_t vlan {};
468 memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
469 // We are not storing the enable bit
470 // We assume that ipmitool always send enable
471 // bit as 1.
472 vlan = le16toh(vlan);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800473 channelConf->vlanID = vlan;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530474 }
475 break;
476
Ratan Guptab8e99552017-07-27 07:07:48 +0530477 case LAN_PARM_INPROGRESS:
478 {
479 if (reqptr->data[0] == SET_COMPLETE)
480 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800481 channelConf->lan_set_in_progress = SET_COMPLETE;
Ratan Guptab8e99552017-07-27 07:07:48 +0530482
483 log<level::INFO>("Network data from Cache",
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800484 entry("PREFIX=%s", channelConf->netmask.c_str()),
485 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
486 entry("GATEWAY=%s", channelConf->gateway.c_str()),
487 entry("VLAN=%d", channelConf->vlanID));
Ratan Guptab8e99552017-07-27 07:07:48 +0530488
489 log<level::INFO>("Use Set Channel Access command to apply");
Ratan Guptab8e99552017-07-27 07:07:48 +0530490 }
491 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
492 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800493 channelConf->lan_set_in_progress = SET_IN_PROGRESS;
Ratan Guptab8e99552017-07-27 07:07:48 +0530494 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530495 }
496 break;
497
498 default:
499 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530500 rc = IPMI_CC_PARM_NOT_SUPPORTED;
501 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530502 }
vishwa1eaea4f2016-02-26 11:57:40 -0600503
tomjose26e17732016-03-03 08:52:51 -0600504 return rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500505}
506
Ratan Guptab8e99552017-07-27 07:07:48 +0530507struct get_lan_t
508{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500509 uint8_t rev_channel;
510 uint8_t parameter;
511 uint8_t parameter_set;
512 uint8_t parameter_block;
Ratan Guptab8e99552017-07-27 07:07:48 +0530513} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500514
Ratan Guptab8e99552017-07-27 07:07:48 +0530515ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn,
516 ipmi_cmd_t cmd,
517 ipmi_request_t request,
518 ipmi_response_t response,
519 ipmi_data_len_t data_len,
520 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500521{
522 ipmi_ret_t rc = IPMI_CC_OK;
523 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500524 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500525
526 get_lan_t *reqptr = (get_lan_t*) request;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800527 // channel number is the lower nibble
528 int channel = reqptr->rev_channel & CHANNEL_MASK;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500529
530 if (reqptr->rev_channel & 0x80) // Revision is bit 7
531 {
532 // Only current revision was requested
533 *data_len = sizeof(current_revision);
534 memcpy(response, &current_revision, *data_len);
535 return IPMI_CC_OK;
536 }
537
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800538 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
539 if (ethdevice.empty())
540 {
541 return IPMI_CC_INVALID_FIELD_REQUEST;
542 }
543 auto channelConf = getChannelConfig(channel);
544
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600545 if (reqptr->parameter == LAN_PARM_INPROGRESS)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500546 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800547 uint8_t buf[] = {current_revision, channelConf->lan_set_in_progress};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500548 *data_len = sizeof(buf);
549 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500550 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600551 else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500552 {
553 uint8_t buf[] = {current_revision,0x04};
554 *data_len = sizeof(buf);
555 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500556 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600557 else if (reqptr->parameter == LAN_PARM_AUTHENABLES)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500558 {
559 uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04};
560 *data_len = sizeof(buf);
561 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500562 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530563 else if ((reqptr->parameter == LAN_PARM_IP) ||
564 (reqptr->parameter == LAN_PARM_SUBNET) ||
565 (reqptr->parameter == LAN_PARM_GATEWAY) ||
566 (reqptr->parameter == LAN_PARM_MAC))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500567 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530568 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1] = {};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500569
tomjose26e17732016-03-03 08:52:51 -0600570 *data_len = sizeof(current_revision);
571 memcpy(buf, &current_revision, *data_len);
572
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800573 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
vishwa1eaea4f2016-02-26 11:57:40 -0600574 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530575 if (reqptr->parameter == LAN_PARM_MAC)
576 {
577 *data_len = sizeof(buf);
578 }
579 else
580 {
581 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1;
582 }
tomjose26e17732016-03-03 08:52:51 -0600583 memcpy(response, &buf, *data_len);
Adriana Kobylak342df102016-02-10 13:48:16 -0600584 }
tomjose26e17732016-03-03 08:52:51 -0600585 else
Hariharasubramanian R83951912016-01-20 07:06:36 -0600586 {
tomjose26e17732016-03-03 08:52:51 -0600587 rc = IPMI_CC_UNSPECIFIED_ERROR;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600588 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500589 }
Ratan Gupta533d03b2017-07-30 10:39:22 +0530590 else if (reqptr->parameter == LAN_PARM_VLAN)
591 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530592 uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530593
594 *data_len = sizeof(current_revision);
595 memcpy(buf, &current_revision, *data_len);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800596 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530597 {
598 *data_len = sizeof(buf);
599 memcpy(response, &buf, *data_len);
600 }
601 }
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530602 else if (reqptr->parameter == LAN_PARM_IPSRC)
603 {
604 uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {};
605 *data_len = sizeof(current_revision);
606 memcpy(buff, &current_revision, *data_len);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800607 if (getNetworkData(reqptr->parameter, &buff[1], channel) == IPMI_CC_OK)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530608 {
609 *data_len = sizeof(buff);
610 memcpy(response, &buff, *data_len);
611 }
612 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500613 else
614 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530615 log<level::ERR>("Unsupported parameter",
616 entry("PARAMETER=0x%x", reqptr->parameter));
vishwa1eaea4f2016-02-26 11:57:40 -0600617 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500618 }
619
620 return rc;
621}
622
623void register_netfn_transport_functions()
624{
Tom05732372016-09-06 17:21:23 +0530625 // <Wildcard Command>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500626 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_WILDCARD);
Tom05732372016-09-06 17:21:23 +0530627 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard,
628 PRIVILEGE_USER);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500629
Tom05732372016-09-06 17:21:23 +0530630 // <Set LAN Configuration Parameters>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500631 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_SET_LAN);
Tom05732372016-09-06 17:21:23 +0530632 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan,
633 PRIVILEGE_ADMIN);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500634
Tom05732372016-09-06 17:21:23 +0530635 // <Get LAN Configuration Parameters>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500636 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_TRANSPORT, IPMI_CMD_GET_LAN);
Tom05732372016-09-06 17:21:23 +0530637 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan,
638 PRIVILEGE_OPERATOR);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500639
640 return;
641}