blob: 95b983a7a9e9c5ca0e79c2d5f466ce6edb6319ac [file] [log] [blame]
Ratan Gupta7a7f0122018-03-07 12:31:05 +05301#include <chrono>
Tom Josepha30c8d32018-03-22 02:15:03 +05302#include <fstream>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05003#include <stdio.h>
4#include <string.h>
5#include <stdint.h>
Hariharasubramanian R83951912016-01-20 07:06:36 -06006#include <arpa/inet.h>
tomjose26e17732016-03-03 08:52:51 -06007#include <string>
Vernon Mauery185b9f82018-07-20 10:52:36 -07008#if __has_include(<filesystem>)
9#include <filesystem>
10#elif __has_include(<experimental/filesystem>)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053011#include <experimental/filesystem>
Vernon Mauery185b9f82018-07-20 10:52:36 -070012namespace std {
13 // splice experimental::filesystem into std
14 namespace filesystem = std::experimental::filesystem;
15}
16#else
17# error filesystem not available
18#endif
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050019
Tom Josepha30c8d32018-03-22 02:15:03 +053020#include "app/channel.hpp"
Patrick Williams37af7332016-09-02 21:21:42 -050021#include "host-ipmid/ipmid-api.h"
Patrick Williams53a360e2016-08-12 22:01:02 -050022#include "ipmid.hpp"
Ratan Gupta7a7f0122018-03-07 12:31:05 +053023#include "timer.hpp"
Ratan Guptab8e99552017-07-27 07:07:48 +053024#include "transporthandler.hpp"
25#include "utils.hpp"
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080026#include "net.hpp"
Ratan Guptab8e99552017-07-27 07:07:48 +053027
28#include <phosphor-logging/log.hpp>
29#include <phosphor-logging/elog-errors.hpp>
30#include "xyz/openbmc_project/Common/error.hpp"
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050031
Hariharasubramanian R83951912016-01-20 07:06:36 -060032#define SYSTEMD_NETWORKD_DBUS 1
33
34#ifdef SYSTEMD_NETWORKD_DBUS
35#include <systemd/sd-bus.h>
Sergey Solomineb9b8142016-08-23 09:07:28 -050036#include <mapper.h>
Hariharasubramanian R83951912016-01-20 07:06:36 -060037#endif
38
Ratan Gupta7a7f0122018-03-07 12:31:05 +053039extern std::unique_ptr<phosphor::ipmi::Timer> networkTimer;
Ratan Gupta1247e0b2018-03-07 10:47:25 +053040
Adriana Kobylake08fbc62016-02-09 16:17:23 -060041const int SIZE_MAC = 18; //xx:xx:xx:xx:xx:xx
Ratan Gupta1247e0b2018-03-07 10:47:25 +053042constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Adriana Kobylake08fbc62016-02-09 16:17:23 -060043
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080044std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
Hariharasubramanian R83951912016-01-20 07:06:36 -060045
Ratan Guptab8e99552017-07-27 07:07:48 +053046using namespace phosphor::logging;
47using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta7a7f0122018-03-07 12:31:05 +053048
Vernon Mauery185b9f82018-07-20 10:52:36 -070049namespace fs = std::filesystem;
Hariharasubramanian R83951912016-01-20 07:06:36 -060050
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050051void register_netfn_transport_functions() __attribute__((constructor));
52
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080053struct ChannelConfig_t* getChannelConfig(int channel)
54{
55 auto item = channelConfig.find(channel);
56 if (item == channelConfig.end())
57 {
58 channelConfig[channel] = std::make_unique<struct ChannelConfig_t>();
59 }
60
61 return channelConfig[channel].get();
62}
63
Ratan Guptab8e99552017-07-27 07:07:48 +053064// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network Manager or
Nan Li3d0df912016-10-18 19:51:41 +080065// Cache based on Set-In-Progress State
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080066ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel)
tomjose26e17732016-03-03 08:52:51 -060067{
tomjose26e17732016-03-03 08:52:51 -060068 ipmi_ret_t rc = IPMI_CC_OK;
Ratan Guptab8e99552017-07-27 07:07:48 +053069 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Gupta533d03b2017-07-30 10:39:22 +053070
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080071 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
72 // if ethdevice is an empty string they weren't expecting this channel.
73 if (ethdevice.empty())
74 {
75 // TODO: return error from getNetworkData()
76 return IPMI_CC_INVALID_FIELD_REQUEST;
77 }
78 auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE;
79 auto channelConf = getChannelConfig(channel);
80
Ratan Guptab8e99552017-07-27 07:07:48 +053081 try
tomjose26e17732016-03-03 08:52:51 -060082 {
Ratan Guptab8e99552017-07-27 07:07:48 +053083 switch (lan_param)
tomjose26e17732016-03-03 08:52:51 -060084 {
Ratan Guptab8e99552017-07-27 07:07:48 +053085 case LAN_PARM_IP:
86 {
87 std::string ipaddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080088 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +053089 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053090 try
91 {
Ratan Guptadd646202017-11-21 17:46:59 +053092 auto ipObjectInfo = ipmi::getIPObject(
93 bus,
94 ipmi::network::IP_INTERFACE,
95 ipmi::network::ROOT,
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080096 ethIP);
Ratan Guptadd646202017-11-21 17:46:59 +053097
98 auto properties = ipmi::getAllDbusProperties(
99 bus,
100 ipObjectInfo.second,
101 ipObjectInfo.first,
102 ipmi::network::IP_INTERFACE);
103
104 ipaddress = properties["Address"].get<std::string>();
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530105 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500106 // ignore the exception, as it is a valid condition that
107 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530108 catch (InternalFailure& e)
109 {
110 // nothing to do.
111 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530112 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800113 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530114 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800115 ipaddress = channelConf->ipaddr;
Ratan Guptab8e99552017-07-27 07:07:48 +0530116 }
117
118 inet_pton(AF_INET, ipaddress.c_str(),
119 reinterpret_cast<void*>(data));
120 }
121 break;
122
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530123 case LAN_PARM_IPSRC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530124 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530125 std::string networkInterfacePath;
126
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800127 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530128 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530129 try
130 {
131 ipmi::ObjectTree ancestorMap;
132 // if the system is having ip object,then
133 // get the IP object.
134 auto ipObject = ipmi::getDbusObject(
135 bus,
136 ipmi::network::IP_INTERFACE,
137 ipmi::network::ROOT,
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800138 ethIP);
Ratan Guptab8e99552017-07-27 07:07:48 +0530139
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530140 // Get the parent interface of the IP object.
141 try
142 {
143 ipmi::InterfaceList interfaces;
144 interfaces.emplace_back(
145 ipmi::network::ETHERNET_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530146
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530147 ancestorMap = ipmi::getAllAncestors(
148 bus,
149 ipObject.first,
150 std::move(interfaces));
151 }
152 catch (InternalFailure& e)
153 {
154 // if unable to get the parent interface
155 // then commit the error and return.
156 log<level::ERR>("Unable to get the parent interface",
157 entry("PATH=%s", ipObject.first.c_str()),
158 entry("INTERFACE=%s",
159 ipmi::network::ETHERNET_INTERFACE));
160 break;
161
162 }
163 // for an ip object there would be single parent
164 // interface.
165 networkInterfacePath = ancestorMap.begin()->first;
166 }
167 catch (InternalFailure& e)
168 {
169 // if there is no ip configured on the system,then
170 // get the network interface object.
171 auto networkInterfaceObject = ipmi::getDbusObject(
172 bus,
173 ipmi::network::ETHERNET_INTERFACE,
174 ipmi::network::ROOT,
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800175 ethdevice);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530176
177 networkInterfacePath = networkInterfaceObject.first;
178 }
179
180 auto variant = ipmi::getDbusProperty(
181 bus,
182 ipmi::network::SERVICE,
183 networkInterfacePath,
184 ipmi::network::ETHERNET_INTERFACE,
185 "DHCPEnabled");
186
187 auto dhcpEnabled = variant.get<bool>();
188 // As per IPMI spec 2=>DHCP, 1=STATIC
189 auto ipsrc = dhcpEnabled ? ipmi::network::IPOrigin::DHCP :
190 ipmi::network::IPOrigin::STATIC;
191
192 memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE);
193 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800194 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530195 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800196 memcpy(data, &(channelConf->ipsrc),
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530197 ipmi::network::IPSRC_SIZE_BYTE);
198 }
199 }
200 break;
201
202 case LAN_PARM_SUBNET:
203 {
204 unsigned long mask {};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800205 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530206 {
207 try
208 {
Ratan Guptadd646202017-11-21 17:46:59 +0530209 auto ipObjectInfo = ipmi::getIPObject(
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530210 bus,
211 ipmi::network::IP_INTERFACE,
212 ipmi::network::ROOT,
213 ipmi::network::IP_TYPE);
214
215 auto properties = ipmi::getAllDbusProperties(
216 bus,
217 ipObjectInfo.second,
218 ipObjectInfo.first,
219 ipmi::network::IP_INTERFACE);
220
221 auto prefix = properties["PrefixLength"].get<uint8_t>();
222 mask = ipmi::network::MASK_32_BIT;
223 mask = htonl(mask << (ipmi::network::BITS_32 - prefix));
224 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500225 // ignore the exception, as it is a valid condition that
226 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530227 catch (InternalFailure& e)
228 {
229 // nothing to do
230 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530231 memcpy(data, &mask, ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
232 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800233 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530234 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800235 inet_pton(AF_INET, channelConf->netmask.c_str(),
Ratan Guptab8e99552017-07-27 07:07:48 +0530236 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530237 }
238
239 }
240 break;
241
242 case LAN_PARM_GATEWAY:
243 {
244 std::string gateway;
245
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800246 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530247 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530248 try
249 {
250 auto systemObject = ipmi::getDbusObject(
251 bus,
252 ipmi::network::SYSTEMCONFIG_INTERFACE,
253 ipmi::network::ROOT);
Ratan Guptab8e99552017-07-27 07:07:48 +0530254
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530255 auto systemProperties = ipmi::getAllDbusProperties(
256 bus,
257 systemObject.second,
258 systemObject.first,
259 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530260
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530261 gateway = systemProperties["DefaultGateway"].get<
262 std::string>();
263 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500264 // ignore the exception, as it is a valid condition that
265 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530266 catch (InternalFailure& e)
267 {
268 // nothing to do
269 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530270
271 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800272 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530273 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800274 gateway = channelConf->gateway;
Ratan Guptab8e99552017-07-27 07:07:48 +0530275 }
276
277 inet_pton(AF_INET, gateway.c_str(),
278 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530279 }
280 break;
281
282 case LAN_PARM_MAC:
283 {
284 std::string macAddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800285 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530286 {
287 auto macObjectInfo = ipmi::getDbusObject(
288 bus,
289 ipmi::network::MAC_INTERFACE,
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800290 ipmi::network::ROOT,
291 ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530292
293 auto variant = ipmi::getDbusProperty(
294 bus,
295 macObjectInfo.second,
296 macObjectInfo.first,
297 ipmi::network::MAC_INTERFACE,
298 "MACAddress");
299
300 macAddress = variant.get<std::string>();
301
302 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800303 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530304 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800305 macAddress = channelConf->macAddress;
Ratan Guptab8e99552017-07-27 07:07:48 +0530306 }
307
308 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
309 (data),
310 (data + 1),
311 (data + 2),
312 (data + 3),
313 (data + 4),
314 (data + 5));
315 }
316 break;
317
Ratan Gupta533d03b2017-07-30 10:39:22 +0530318 case LAN_PARM_VLAN:
319 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530320 uint16_t vlanID {};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800321 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530322 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530323 try
Ratan Gupta533d03b2017-07-30 10:39:22 +0530324 {
Ratan Guptadd646202017-11-21 17:46:59 +0530325 auto ipObjectInfo = ipmi::getIPObject(
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530326 bus,
327 ipmi::network::IP_INTERFACE,
328 ipmi::network::ROOT,
329 ipmi::network::IP_TYPE);
330
331 vlanID = static_cast<uint16_t>(
332 ipmi::network::getVLAN(ipObjectInfo.first));
333
334 vlanID = htole16(vlanID);
335
336 if (vlanID)
337 {
338 //Enable the 16th bit
339 vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK);
340 }
341 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500342 // ignore the exception, as it is a valid condition that
343 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530344 catch (InternalFailure& e)
345 {
346 // nothing to do
Ratan Gupta533d03b2017-07-30 10:39:22 +0530347 }
348
349 memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
350 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800351 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530352 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800353 memcpy(data, &(channelConf->vlanID),
Ratan Gupta533d03b2017-07-30 10:39:22 +0530354 ipmi::network::VLAN_SIZE_BYTE);
355 }
356 }
357 break;
358
Ratan Guptab8e99552017-07-27 07:07:48 +0530359 default:
360 rc = IPMI_CC_PARM_OUT_OF_RANGE;
tomjose26e17732016-03-03 08:52:51 -0600361 }
362 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530363 catch (InternalFailure& e)
tomjose26e17732016-03-03 08:52:51 -0600364 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530365 commit<InternalFailure>();
366 rc = IPMI_CC_UNSPECIFIED_ERROR;
367 return rc;
tomjose26e17732016-03-03 08:52:51 -0600368 }
tomjose26e17732016-03-03 08:52:51 -0600369 return rc;
370}
371
Tom Josepha30c8d32018-03-22 02:15:03 +0530372namespace cipher
373{
374
375std::vector<uint8_t> getCipherList()
376{
377 std::vector<uint8_t> cipherList;
378
379 std::ifstream jsonFile(configFile);
380 if (!jsonFile.is_open())
381 {
382 log<level::ERR>("Channel Cipher suites file not found");
383 elog<InternalFailure>();
384 }
385
386 auto data = Json::parse(jsonFile, nullptr, false);
387 if (data.is_discarded())
388 {
389 log<level::ERR>("Parsing channel cipher suites JSON failed");
390 elog<InternalFailure>();
391 }
392
393 // Byte 1 is reserved
394 cipherList.push_back(0x00);
395
396 for (const auto& record : data)
397 {
398 cipherList.push_back(record.value(cipher, 0));
399 }
400
401 return cipherList;
402}
403
404} //namespace cipher
405
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500406ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
407 ipmi_request_t request, ipmi_response_t response,
408 ipmi_data_len_t data_len, ipmi_context_t context)
409{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500410 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800411 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500412 *data_len = 0;
413 return rc;
414}
415
Ratan Guptab8e99552017-07-27 07:07:48 +0530416struct set_lan_t
417{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500418 uint8_t channel;
419 uint8_t parameter;
420 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
Ratan Guptab8e99552017-07-27 07:07:48 +0530421} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500422
Ratan Guptab8e99552017-07-27 07:07:48 +0530423ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn,
424 ipmi_cmd_t cmd,
425 ipmi_request_t request,
426 ipmi_response_t response,
427 ipmi_data_len_t data_len,
428 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500429{
430 ipmi_ret_t rc = IPMI_CC_OK;
431 *data_len = 0;
Nan Li3d0df912016-10-18 19:51:41 +0800432
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530433 using namespace std::chrono_literals;
434
435 // time to wait before applying the network changes.
436 constexpr auto networkTimeout = 10000000us; // 10 sec
437
Ratan Guptab8e99552017-07-27 07:07:48 +0530438 char ipaddr[INET_ADDRSTRLEN];
439 char netmask[INET_ADDRSTRLEN];
440 char gateway[INET_ADDRSTRLEN];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500441
Ratan Guptab8e99552017-07-27 07:07:48 +0530442 auto reqptr = reinterpret_cast<const set_lan_t*>(request);
443 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500444
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800445 // channel number is the lower nibble
446 int channel = reqptr->channel & CHANNEL_MASK;
447 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
448 if (ethdevice.empty())
449 {
450 return IPMI_CC_INVALID_FIELD_REQUEST;
451 }
452 auto channelConf = getChannelConfig(channel);
453
Ratan Guptab8e99552017-07-27 07:07:48 +0530454 switch (reqptr->parameter)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500455 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530456 case LAN_PARM_IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600457 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530458 snprintf(ipaddr, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
459 reqptr->data[0], reqptr->data[1],
460 reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500461
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800462 channelConf->ipaddr.assign(ipaddr);
Ratan Guptab8e99552017-07-27 07:07:48 +0530463 }
464 break;
465
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530466 case LAN_PARM_IPSRC:
467 {
468 uint8_t ipsrc{};
469 memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800470 channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530471 }
472 break;
473
Ratan Guptab8e99552017-07-27 07:07:48 +0530474 case LAN_PARM_MAC:
475 {
476 char mac[SIZE_MAC];
477
478 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
479 reqptr->data[0],
480 reqptr->data[1],
481 reqptr->data[2],
482 reqptr->data[3],
483 reqptr->data[4],
484 reqptr->data[5]);
485
486 auto macObjectInfo = ipmi::getDbusObject(
487 bus,
488 ipmi::network::MAC_INTERFACE,
489 ipmi::network::ROOT,
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800490 ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530491
492 ipmi::setDbusProperty(bus,
493 macObjectInfo.second,
494 macObjectInfo.first,
495 ipmi::network::MAC_INTERFACE,
496 "MACAddress",
497 std::string(mac));
498
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800499 channelConf->macAddress = mac;
Ratan Guptab8e99552017-07-27 07:07:48 +0530500 }
501 break;
502
503 case LAN_PARM_SUBNET:
504 {
505 snprintf(netmask, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
506 reqptr->data[0], reqptr->data[1],
507 reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800508 channelConf->netmask.assign(netmask);
Ratan Guptab8e99552017-07-27 07:07:48 +0530509 }
510 break;
511
512 case LAN_PARM_GATEWAY:
513 {
514 snprintf(gateway, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
515 reqptr->data[0], reqptr->data[1],
516 reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800517 channelConf->gateway.assign(gateway);
Ratan Guptab8e99552017-07-27 07:07:48 +0530518 }
519 break;
520
Ratan Gupta533d03b2017-07-30 10:39:22 +0530521 case LAN_PARM_VLAN:
522 {
523 uint16_t vlan {};
524 memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
525 // We are not storing the enable bit
526 // We assume that ipmitool always send enable
527 // bit as 1.
528 vlan = le16toh(vlan);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800529 channelConf->vlanID = vlan;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530530 }
531 break;
532
Ratan Guptab8e99552017-07-27 07:07:48 +0530533 case LAN_PARM_INPROGRESS:
534 {
535 if (reqptr->data[0] == SET_COMPLETE)
536 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800537 channelConf->lan_set_in_progress = SET_COMPLETE;
Ratan Guptab8e99552017-07-27 07:07:48 +0530538
539 log<level::INFO>("Network data from Cache",
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800540 entry("PREFIX=%s", channelConf->netmask.c_str()),
541 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
542 entry("GATEWAY=%s", channelConf->gateway.c_str()),
543 entry("VLAN=%d", channelConf->vlanID));
Ratan Guptab8e99552017-07-27 07:07:48 +0530544
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530545 if (!networkTimer)
546 {
547 log<level::ERR>("Network timer is not instantiated");
548 return IPMI_CC_UNSPECIFIED_ERROR;
549 }
550
551 // start/restart the timer
552 networkTimer->startTimer(networkTimeout);
Ratan Guptab8e99552017-07-27 07:07:48 +0530553 }
554 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
555 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800556 channelConf->lan_set_in_progress = SET_IN_PROGRESS;
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530557 channelConf->flush = true;
Ratan Guptab8e99552017-07-27 07:07:48 +0530558 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530559 }
560 break;
561
562 default:
563 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530564 rc = IPMI_CC_PARM_NOT_SUPPORTED;
565 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530566 }
vishwa1eaea4f2016-02-26 11:57:40 -0600567
tomjose26e17732016-03-03 08:52:51 -0600568 return rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500569}
570
Ratan Guptab8e99552017-07-27 07:07:48 +0530571struct get_lan_t
572{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500573 uint8_t rev_channel;
574 uint8_t parameter;
575 uint8_t parameter_set;
576 uint8_t parameter_block;
Ratan Guptab8e99552017-07-27 07:07:48 +0530577} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500578
Ratan Guptab8e99552017-07-27 07:07:48 +0530579ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn,
580 ipmi_cmd_t cmd,
581 ipmi_request_t request,
582 ipmi_response_t response,
583 ipmi_data_len_t data_len,
584 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500585{
586 ipmi_ret_t rc = IPMI_CC_OK;
587 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500588 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500589
590 get_lan_t *reqptr = (get_lan_t*) request;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800591 // channel number is the lower nibble
592 int channel = reqptr->rev_channel & CHANNEL_MASK;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500593
594 if (reqptr->rev_channel & 0x80) // Revision is bit 7
595 {
596 // Only current revision was requested
597 *data_len = sizeof(current_revision);
598 memcpy(response, &current_revision, *data_len);
599 return IPMI_CC_OK;
600 }
601
Tom Josepha30c8d32018-03-22 02:15:03 +0530602 static std::vector<uint8_t> cipherList;
603 static auto listInit = false;
604
605 if (!listInit)
606 {
607 try
608 {
609 cipherList = cipher::getCipherList();
610 listInit = true;
611 }
612 catch (const std::exception &e)
613 {
614 return IPMI_CC_UNSPECIFIED_ERROR;
615 }
616 }
617
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800618 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
619 if (ethdevice.empty())
620 {
621 return IPMI_CC_INVALID_FIELD_REQUEST;
622 }
623 auto channelConf = getChannelConfig(channel);
624
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600625 if (reqptr->parameter == LAN_PARM_INPROGRESS)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500626 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800627 uint8_t buf[] = {current_revision, channelConf->lan_set_in_progress};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500628 *data_len = sizeof(buf);
629 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500630 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600631 else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500632 {
633 uint8_t buf[] = {current_revision,0x04};
634 *data_len = sizeof(buf);
635 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500636 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600637 else if (reqptr->parameter == LAN_PARM_AUTHENABLES)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500638 {
639 uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04};
640 *data_len = sizeof(buf);
641 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500642 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530643 else if ((reqptr->parameter == LAN_PARM_IP) ||
644 (reqptr->parameter == LAN_PARM_SUBNET) ||
645 (reqptr->parameter == LAN_PARM_GATEWAY) ||
646 (reqptr->parameter == LAN_PARM_MAC))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500647 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530648 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1] = {};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500649
tomjose26e17732016-03-03 08:52:51 -0600650 *data_len = sizeof(current_revision);
651 memcpy(buf, &current_revision, *data_len);
652
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800653 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
vishwa1eaea4f2016-02-26 11:57:40 -0600654 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530655 if (reqptr->parameter == LAN_PARM_MAC)
656 {
657 *data_len = sizeof(buf);
658 }
659 else
660 {
661 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1;
662 }
tomjose26e17732016-03-03 08:52:51 -0600663 memcpy(response, &buf, *data_len);
Adriana Kobylak342df102016-02-10 13:48:16 -0600664 }
tomjose26e17732016-03-03 08:52:51 -0600665 else
Hariharasubramanian R83951912016-01-20 07:06:36 -0600666 {
tomjose26e17732016-03-03 08:52:51 -0600667 rc = IPMI_CC_UNSPECIFIED_ERROR;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600668 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500669 }
Ratan Gupta533d03b2017-07-30 10:39:22 +0530670 else if (reqptr->parameter == LAN_PARM_VLAN)
671 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530672 uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530673
674 *data_len = sizeof(current_revision);
675 memcpy(buf, &current_revision, *data_len);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800676 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530677 {
678 *data_len = sizeof(buf);
679 memcpy(response, &buf, *data_len);
680 }
681 }
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530682 else if (reqptr->parameter == LAN_PARM_IPSRC)
683 {
684 uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {};
685 *data_len = sizeof(current_revision);
686 memcpy(buff, &current_revision, *data_len);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800687 if (getNetworkData(reqptr->parameter, &buff[1], channel) == IPMI_CC_OK)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530688 {
689 *data_len = sizeof(buff);
690 memcpy(response, &buff, *data_len);
691 }
692 }
Tom Josepha30c8d32018-03-22 02:15:03 +0530693 else if (reqptr->parameter == CIPHER_SUITE_COUNT)
694 {
695 *(static_cast<uint8_t*>(response)) = current_revision;
696 // Byte 1 is reserved byte and does not indicate a cipher suite ID, so
697 // no of cipher suite entry count is one less than the size of the
698 // vector
699 auto count = static_cast<uint8_t>(cipherList.size() - 1);
700 *(static_cast<uint8_t*>(response) + 1) = count;
701 *data_len = sizeof(current_revision) + sizeof(count);
702 }
703 else if (reqptr->parameter == CIPHER_SUITE_ENTRIES)
704 {
705 *(static_cast<uint8_t*>(response)) = current_revision;
706 // Byte 1 is reserved
707 std::copy_n(cipherList.data(),
708 cipherList.size(),
709 static_cast<uint8_t*>(response) + 1);
710 *data_len = sizeof(current_revision) +
711 static_cast<uint8_t>(cipherList.size());
712 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500713 else
714 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530715 log<level::ERR>("Unsupported parameter",
716 entry("PARAMETER=0x%x", reqptr->parameter));
vishwa1eaea4f2016-02-26 11:57:40 -0600717 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500718 }
719
720 return rc;
721}
722
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530723void applyChanges(int channel)
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530724{
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530725 std::string ipaddress;
726 std::string gateway;
727 uint8_t prefix {};
728 uint32_t vlanID {};
729 std::string networkInterfacePath;
730 ipmi::DbusObjectInfo ipObject;
731 ipmi::DbusObjectInfo systemObject;
732
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530733 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
734 if (ethdevice.empty())
735 {
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530736 log<level::ERR>("Unable to get the interface name",
737 entry("CHANNEL=%d", channel));
738 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530739 }
740 auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE;
741 auto channelConf = getChannelConfig(channel);
742
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530743 try
744 {
745 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
746
747 log<level::INFO>("Network data from Cache",
748 entry("PREFIX=%s", channelConf->netmask.c_str()),
749 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
750 entry("GATEWAY=%s", channelConf->gateway.c_str()),
751 entry("VLAN=%d", channelConf->vlanID),
752 entry("IPSRC=%d", channelConf->ipsrc));
753 if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK)
754 {
755 //get the first twelve bits which is vlan id
756 //not interested in rest of the bits.
757 channelConf->vlanID = le32toh(channelConf->vlanID);
758 vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK;
759 }
760
761 // if the asked ip src is DHCP then not interested in
762 // any given data except vlan.
763 if (channelConf->ipsrc != ipmi::network::IPOrigin::DHCP)
764 {
765 // always get the system object
766 systemObject = ipmi::getDbusObject(
767 bus,
768 ipmi::network::SYSTEMCONFIG_INTERFACE,
769 ipmi::network::ROOT);
770
771 // the below code is to determine the mode of the interface
772 // as the handling is same, if the system is configured with
773 // DHCP or user has given all the data.
774 try
775 {
776 ipmi::ObjectTree ancestorMap;
777
778 ipmi::InterfaceList interfaces {
779 ipmi::network::ETHERNET_INTERFACE };
780
781 // if the system is having ip object,then
782 // get the IP object.
Ratan Guptadf53d222018-03-18 23:13:39 +0530783 ipObject = ipmi::getIPObject(bus,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530784 ipmi::network::IP_INTERFACE,
785 ipmi::network::ROOT,
786 ethIp);
787
788 // Get the parent interface of the IP object.
789 try
790 {
791 ancestorMap = ipmi::getAllAncestors(bus,
792 ipObject.first,
793 std::move(interfaces));
794 }
795 catch (InternalFailure& e)
796 {
797 // if unable to get the parent interface
798 // then commit the error and return.
799 log<level::ERR>("Unable to get the parent interface",
800 entry("PATH=%s", ipObject.first.c_str()),
801 entry("INTERFACE=%s",
802 ipmi::network::ETHERNET_INTERFACE));
803 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530804 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530805 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530806 }
807
808 networkInterfacePath = ancestorMap.begin()->first;
809 }
810 catch (InternalFailure& e)
811 {
812 // TODO Currently IPMI supports single interface,need to handle
813 // Multiple interface through
814 // https://github.com/openbmc/openbmc/issues/2138
815
816 // if there is no ip configured on the system,then
817 // get the network interface object.
818 auto networkInterfaceObject = ipmi::getDbusObject(
819 bus,
820 ipmi::network::ETHERNET_INTERFACE,
821 ipmi::network::ROOT,
822 ethdevice);
823
824 networkInterfacePath = std::move(networkInterfaceObject.first);
825 }
826
827 // get the configured mode on the system.
828 auto enableDHCP = ipmi::getDbusProperty(
829 bus,
830 ipmi::network::SERVICE,
831 networkInterfacePath,
832 ipmi::network::ETHERNET_INTERFACE,
833 "DHCPEnabled").get<bool>();
834
835 // if ip address source is not given then get the ip source mode
836 // from the system so that it can be applied later.
837 if (channelConf->ipsrc == ipmi::network::IPOrigin::UNSPECIFIED)
838 {
839 channelConf->ipsrc = (enableDHCP) ?
840 ipmi::network::IPOrigin::DHCP :
841 ipmi::network::IPOrigin::STATIC;
842 }
843
844 // check whether user has given all the data
845 // or the configured system interface is dhcp enabled,
846 // in both of the cases get the values from the cache.
847 if ((!channelConf->ipaddr.empty() &&
848 !channelConf->netmask.empty() &&
849 !channelConf->gateway.empty()) ||
850 (enableDHCP)) // configured system interface mode = DHCP
851 {
852 //convert mask into prefix
853 ipaddress = channelConf->ipaddr;
854 prefix = ipmi::network::toPrefix(AF_INET, channelConf->netmask);
855 gateway = channelConf->gateway;
856 }
857 else // asked ip src = static and configured system src = static
858 // or partially given data.
859 {
860 // We have partial filled cache so get the remaining
861 // info from the system.
862
863 // Get the network data from the system as user has
864 // not given all the data then use the data fetched from the
865 // system but it is implementation dependent,IPMI spec doesn't
866 // force it.
867
868 // if system is not having any ip object don't throw error,
869 try
870 {
871 auto properties = ipmi::getAllDbusProperties(
872 bus,
873 ipObject.second,
874 ipObject.first,
875 ipmi::network::IP_INTERFACE);
876
877 ipaddress = channelConf->ipaddr.empty() ?
878 properties["Address"].get<std::string>() :
879 channelConf->ipaddr;
880
881 prefix = channelConf->netmask.empty() ?
882 properties["PrefixLength"].get<uint8_t>() :
883 ipmi::network::toPrefix(AF_INET,
884 channelConf->netmask);
885 }
886 catch (InternalFailure& e)
887 {
888 log<level::INFO>("Failed to get IP object which matches",
889 entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
Joseph Reynolds510eb9c2018-05-30 11:51:28 -0500890 entry("MATCH=%s", ethIp.c_str()));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530891 }
892
893 auto systemProperties = ipmi::getAllDbusProperties(
894 bus,
895 systemObject.second,
896 systemObject.first,
897 ipmi::network::SYSTEMCONFIG_INTERFACE);
898
899 gateway = channelConf->gateway.empty() ?
900 systemProperties["DefaultGateway"].get<std::string>() :
901 channelConf->gateway;
902 }
903 }
904
905 // Currently network manager doesn't support purging of all the
906 // ip addresses and the vlan interfaces from the parent interface,
907 // TODO once the support is there, will make the change here.
908 // https://github.com/openbmc/openbmc/issues/2141.
909
910 // TODO Currently IPMI supports single interface,need to handle
911 // Multiple interface through
912 // https://github.com/openbmc/openbmc/issues/2138
913
914 // instead of deleting all the vlan interfaces and
915 // all the ipv4 address,we will call reset method.
916 //delete all the vlan interfaces
917
918 ipmi::deleteAllDbusObjects(bus,
919 ipmi::network::ROOT,
920 ipmi::network::VLAN_INTERFACE);
921
922 // set the interface mode to static
923 auto networkInterfaceObject = ipmi::getDbusObject(
924 bus,
925 ipmi::network::ETHERNET_INTERFACE,
926 ipmi::network::ROOT,
927 ethdevice);
928
929 // setting the physical interface mode to static.
930 ipmi::setDbusProperty(bus,
931 ipmi::network::SERVICE,
932 networkInterfaceObject.first,
933 ipmi::network::ETHERNET_INTERFACE,
934 "DHCPEnabled",
935 false);
936
937 networkInterfacePath = networkInterfaceObject.first;
938
939 //delete all the ipv4 addresses
940 ipmi::deleteAllDbusObjects(bus,
941 ipmi::network::ROOT,
942 ipmi::network::IP_INTERFACE,
943 ethIp);
944
945 if (vlanID)
946 {
947 ipmi::network::createVLAN(bus,
948 ipmi::network::SERVICE,
949 ipmi::network::ROOT,
950 ethdevice,
951 vlanID);
952
953 auto networkInterfaceObject = ipmi::getDbusObject(
954 bus,
955 ipmi::network::VLAN_INTERFACE,
956 ipmi::network::ROOT);
957
958 networkInterfacePath = networkInterfaceObject.first;
959 }
960
961 if (channelConf->ipsrc == ipmi::network::IPOrigin::DHCP)
962 {
963 ipmi::setDbusProperty(bus,
964 ipmi::network::SERVICE,
965 networkInterfacePath,
966 ipmi::network::ETHERNET_INTERFACE,
967 "DHCPEnabled",
968 true);
969 }
970 else
971 {
972 //change the mode to static
973 ipmi::setDbusProperty(bus,
974 ipmi::network::SERVICE,
975 networkInterfacePath,
976 ipmi::network::ETHERNET_INTERFACE,
977 "DHCPEnabled",
978 false);
979
980 if (!ipaddress.empty())
981 {
982 ipmi::network::createIP(bus,
983 ipmi::network::SERVICE,
984 networkInterfacePath,
985 ipv4Protocol,
986 ipaddress,
987 prefix);
988 }
989
990 if (!gateway.empty())
991 {
992 ipmi::setDbusProperty(bus,
993 systemObject.second,
994 systemObject.first,
995 ipmi::network::SYSTEMCONFIG_INTERFACE,
996 "DefaultGateway",
997 std::string(gateway));
998 }
999 }
1000
1001 }
1002 catch (InternalFailure& e)
1003 {
1004 log<level::ERR>("Failed to set network data",
1005 entry("PREFIX=%d", prefix),
1006 entry("ADDRESS=%s", ipaddress.c_str()),
1007 entry("GATEWAY=%s", gateway.c_str()),
1008 entry("VLANID=%d", vlanID),
1009 entry("IPSRC=%d", channelConf->ipsrc));
1010
1011 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301012 }
1013
1014 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +05301015}
1016
1017void commitNetworkChanges()
1018{
1019 for (const auto &channel : channelConfig)
1020 {
1021 if (channel.second->flush)
1022 {
1023 applyChanges(channel.first);
1024 }
1025 }
1026}
1027
1028void createNetworkTimer()
1029{
1030 if (!networkTimer)
1031 {
1032 std::function<void()> networkTimerCallback(
1033 std::bind(&commitNetworkChanges));
1034
1035 networkTimer =
1036 std::make_unique<phosphor::ipmi::Timer>(
1037 ipmid_get_sd_event_connection(),
1038 networkTimerCallback);
1039 }
1040
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301041}
1042
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001043void register_netfn_transport_functions()
1044{
Ratan Gupta7a7f0122018-03-07 12:31:05 +05301045 // As this timer is only for transport handler
1046 // so creating it here.
1047 createNetworkTimer();
Tom05732372016-09-06 17:21:23 +05301048 // <Wildcard Command>
Tom05732372016-09-06 17:21:23 +05301049 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL, ipmi_transport_wildcard,
1050 PRIVILEGE_USER);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001051
Tom05732372016-09-06 17:21:23 +05301052 // <Set LAN Configuration Parameters>
Tom05732372016-09-06 17:21:23 +05301053 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL, ipmi_transport_set_lan,
1054 PRIVILEGE_ADMIN);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001055
Tom05732372016-09-06 17:21:23 +05301056 // <Get LAN Configuration Parameters>
Tom05732372016-09-06 17:21:23 +05301057 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL, ipmi_transport_get_lan,
1058 PRIVILEGE_OPERATOR);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001059
1060 return;
1061}