blob: a6239ea5fb682b97d82add2582a9480a8ab89418 [file] [log] [blame]
Patrick Venture0b02be92018-08-31 11:55:55 -07001#include <arpa/inet.h>
2#include <stdint.h>
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05003#include <stdio.h>
4#include <string.h>
Patrick Venture0b02be92018-08-31 11:55:55 -07005
6#include <chrono>
7#include <fstream>
tomjose26e17732016-03-03 08:52:51 -06008#include <string>
Vernon Mauery185b9f82018-07-20 10:52:36 -07009#if __has_include(<filesystem>)
10#include <filesystem>
11#elif __has_include(<experimental/filesystem>)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053012#include <experimental/filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -070013namespace std
14{
15// splice experimental::filesystem into std
16namespace filesystem = std::experimental::filesystem;
17} // namespace std
Vernon Mauery185b9f82018-07-20 10:52:36 -070018#else
Patrick Venture0b02be92018-08-31 11:55:55 -070019#error filesystem not available
Vernon Mauery185b9f82018-07-20 10:52:36 -070020#endif
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050021
Tom Josepha30c8d32018-03-22 02:15:03 +053022#include "app/channel.hpp"
Patrick Williams53a360e2016-08-12 22:01:02 -050023#include "ipmid.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -070024#include "net.hpp"
Ratan Gupta7a7f0122018-03-07 12:31:05 +053025#include "timer.hpp"
Ratan Guptab8e99552017-07-27 07:07:48 +053026#include "transporthandler.hpp"
27#include "utils.hpp"
28
Ratan Guptab8e99552017-07-27 07:07:48 +053029#include <phosphor-logging/elog-errors.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070030#include <phosphor-logging/log.hpp>
31#include <xyz/openbmc_project/Common/error.hpp>
32
33#include "host-ipmid/ipmid-api.h"
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050034
Hariharasubramanian R83951912016-01-20 07:06:36 -060035#define SYSTEMD_NETWORKD_DBUS 1
36
37#ifdef SYSTEMD_NETWORKD_DBUS
Sergey Solomineb9b8142016-08-23 09:07:28 -050038#include <mapper.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070039#include <systemd/sd-bus.h>
Hariharasubramanian R83951912016-01-20 07:06:36 -060040#endif
41
Ratan Gupta7a7f0122018-03-07 12:31:05 +053042extern std::unique_ptr<phosphor::ipmi::Timer> networkTimer;
Ratan Gupta1247e0b2018-03-07 10:47:25 +053043
Patrick Venture0b02be92018-08-31 11:55:55 -070044const int SIZE_MAC = 18; // xx:xx:xx:xx:xx:xx
Ratan Gupta1247e0b2018-03-07 10:47:25 +053045constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Adriana Kobylake08fbc62016-02-09 16:17:23 -060046
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080047std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
Hariharasubramanian R83951912016-01-20 07:06:36 -060048
Ratan Guptab8e99552017-07-27 07:07:48 +053049using namespace phosphor::logging;
50using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta7a7f0122018-03-07 12:31:05 +053051
Vernon Mauery185b9f82018-07-20 10:52:36 -070052namespace fs = std::filesystem;
Hariharasubramanian R83951912016-01-20 07:06:36 -060053
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050054void register_netfn_transport_functions() __attribute__((constructor));
55
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080056struct ChannelConfig_t* getChannelConfig(int channel)
57{
58 auto item = channelConfig.find(channel);
59 if (item == channelConfig.end())
60 {
61 channelConfig[channel] = std::make_unique<struct ChannelConfig_t>();
62 }
63
64 return channelConfig[channel].get();
65}
66
Patrick Venture0b02be92018-08-31 11:55:55 -070067// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network
68// Manager or Cache based on Set-In-Progress State
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080069ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel)
tomjose26e17732016-03-03 08:52:51 -060070{
tomjose26e17732016-03-03 08:52:51 -060071 ipmi_ret_t rc = IPMI_CC_OK;
Ratan Guptab8e99552017-07-27 07:07:48 +053072 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Gupta533d03b2017-07-30 10:39:22 +053073
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080074 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
75 // if ethdevice is an empty string they weren't expecting this channel.
76 if (ethdevice.empty())
77 {
78 // TODO: return error from getNetworkData()
79 return IPMI_CC_INVALID_FIELD_REQUEST;
80 }
81 auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE;
82 auto channelConf = getChannelConfig(channel);
83
Ratan Guptab8e99552017-07-27 07:07:48 +053084 try
tomjose26e17732016-03-03 08:52:51 -060085 {
Ratan Guptab8e99552017-07-27 07:07:48 +053086 switch (lan_param)
tomjose26e17732016-03-03 08:52:51 -060087 {
Ratan Guptab8e99552017-07-27 07:07:48 +053088 case LAN_PARM_IP:
89 {
90 std::string ipaddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080091 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +053092 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053093 try
94 {
Patrick Venture0b02be92018-08-31 11:55:55 -070095 auto ipObjectInfo =
96 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
97 ipmi::network::ROOT, ethIP);
Ratan Guptadd646202017-11-21 17:46:59 +053098
99 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700100 bus, ipObjectInfo.second, ipObjectInfo.first,
101 ipmi::network::IP_INTERFACE);
Ratan Guptadd646202017-11-21 17:46:59 +0530102
103 ipaddress = properties["Address"].get<std::string>();
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530104 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500105 // ignore the exception, as it is a valid condition that
106 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530107 catch (InternalFailure& e)
108 {
109 // nothing to do.
110 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530111 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800112 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530113 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800114 ipaddress = channelConf->ipaddr;
Ratan Guptab8e99552017-07-27 07:07:48 +0530115 }
116
117 inet_pton(AF_INET, ipaddress.c_str(),
118 reinterpret_cast<void*>(data));
119 }
120 break;
121
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530122 case LAN_PARM_IPSRC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530123 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530124 std::string networkInterfacePath;
125
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800126 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530127 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530128 try
129 {
130 ipmi::ObjectTree ancestorMap;
131 // if the system is having ip object,then
132 // get the IP object.
133 auto ipObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700134 bus, ipmi::network::IP_INTERFACE,
135 ipmi::network::ROOT, ethIP);
Ratan Guptab8e99552017-07-27 07:07:48 +0530136
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530137 // Get the parent interface of the IP object.
138 try
139 {
140 ipmi::InterfaceList interfaces;
141 interfaces.emplace_back(
Patrick Venture0b02be92018-08-31 11:55:55 -0700142 ipmi::network::ETHERNET_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530143
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530144 ancestorMap = ipmi::getAllAncestors(
Patrick Venture0b02be92018-08-31 11:55:55 -0700145 bus, ipObject.first, std::move(interfaces));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530146 }
147 catch (InternalFailure& e)
148 {
149 // if unable to get the parent interface
150 // then commit the error and return.
Patrick Venture0b02be92018-08-31 11:55:55 -0700151 log<level::ERR>(
152 "Unable to get the parent interface",
153 entry("PATH=%s", ipObject.first.c_str()),
154 entry("INTERFACE=%s",
155 ipmi::network::ETHERNET_INTERFACE));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530156 break;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530157 }
158 // for an ip object there would be single parent
159 // interface.
160 networkInterfacePath = ancestorMap.begin()->first;
161 }
162 catch (InternalFailure& e)
163 {
164 // if there is no ip configured on the system,then
165 // get the network interface object.
166 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700167 bus, ipmi::network::ETHERNET_INTERFACE,
168 ipmi::network::ROOT, ethdevice);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530169
170 networkInterfacePath = networkInterfaceObject.first;
171 }
172
173 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700174 bus, ipmi::network::SERVICE, networkInterfacePath,
175 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530176
177 auto dhcpEnabled = variant.get<bool>();
178 // As per IPMI spec 2=>DHCP, 1=STATIC
Patrick Venture0b02be92018-08-31 11:55:55 -0700179 auto ipsrc = dhcpEnabled ? ipmi::network::IPOrigin::DHCP
180 : ipmi::network::IPOrigin::STATIC;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530181
182 memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE);
183 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800184 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530185 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700186 memcpy(data, &(channelConf->ipsrc),
187 ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530188 }
189 }
190 break;
191
192 case LAN_PARM_SUBNET:
193 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700194 unsigned long mask{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800195 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530196 {
197 try
198 {
Ratan Guptadd646202017-11-21 17:46:59 +0530199 auto ipObjectInfo = ipmi::getIPObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700200 bus, ipmi::network::IP_INTERFACE,
201 ipmi::network::ROOT, ipmi::network::IP_TYPE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530202
203 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700204 bus, ipObjectInfo.second, ipObjectInfo.first,
205 ipmi::network::IP_INTERFACE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530206
207 auto prefix = properties["PrefixLength"].get<uint8_t>();
208 mask = ipmi::network::MASK_32_BIT;
209 mask = htonl(mask << (ipmi::network::BITS_32 - prefix));
210 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500211 // ignore the exception, as it is a valid condition that
212 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530213 catch (InternalFailure& e)
214 {
215 // nothing to do
216 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530217 memcpy(data, &mask, ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
218 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800219 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530220 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800221 inet_pton(AF_INET, channelConf->netmask.c_str(),
Ratan Guptab8e99552017-07-27 07:07:48 +0530222 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530223 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530224 }
225 break;
226
227 case LAN_PARM_GATEWAY:
228 {
229 std::string gateway;
230
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800231 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530232 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530233 try
234 {
235 auto systemObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700236 bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
237 ipmi::network::ROOT);
Ratan Guptab8e99552017-07-27 07:07:48 +0530238
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530239 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700240 bus, systemObject.second, systemObject.first,
241 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530242
Patrick Venture0b02be92018-08-31 11:55:55 -0700243 gateway = systemProperties["DefaultGateway"]
244 .get<std::string>();
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530245 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500246 // ignore the exception, as it is a valid condition that
247 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530248 catch (InternalFailure& e)
249 {
250 // nothing to do
251 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530252 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800253 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530254 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800255 gateway = channelConf->gateway;
Ratan Guptab8e99552017-07-27 07:07:48 +0530256 }
257
258 inet_pton(AF_INET, gateway.c_str(),
259 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530260 }
261 break;
262
263 case LAN_PARM_MAC:
264 {
265 std::string macAddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800266 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530267 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700268 auto macObjectInfo =
269 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
270 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530271
272 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700273 bus, macObjectInfo.second, macObjectInfo.first,
274 ipmi::network::MAC_INTERFACE, "MACAddress");
Ratan Guptab8e99552017-07-27 07:07:48 +0530275
276 macAddress = variant.get<std::string>();
Ratan Guptab8e99552017-07-27 07:07:48 +0530277 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800278 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530279 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800280 macAddress = channelConf->macAddress;
Ratan Guptab8e99552017-07-27 07:07:48 +0530281 }
282
283 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700284 (data), (data + 1), (data + 2), (data + 3), (data + 4),
Ratan Guptab8e99552017-07-27 07:07:48 +0530285 (data + 5));
286 }
287 break;
288
Ratan Gupta533d03b2017-07-30 10:39:22 +0530289 case LAN_PARM_VLAN:
290 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700291 uint16_t vlanID{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800292 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530293 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530294 try
Ratan Gupta533d03b2017-07-30 10:39:22 +0530295 {
Ratan Guptadd646202017-11-21 17:46:59 +0530296 auto ipObjectInfo = ipmi::getIPObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700297 bus, ipmi::network::IP_INTERFACE,
298 ipmi::network::ROOT, ipmi::network::IP_TYPE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530299
300 vlanID = static_cast<uint16_t>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700301 ipmi::network::getVLAN(ipObjectInfo.first));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530302
303 vlanID = htole16(vlanID);
304
305 if (vlanID)
306 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700307 // Enable the 16th bit
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530308 vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK);
309 }
310 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500311 // ignore the exception, as it is a valid condition that
312 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530313 catch (InternalFailure& e)
314 {
315 // nothing to do
Ratan Gupta533d03b2017-07-30 10:39:22 +0530316 }
317
318 memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
319 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800320 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530321 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800322 memcpy(data, &(channelConf->vlanID),
Ratan Gupta533d03b2017-07-30 10:39:22 +0530323 ipmi::network::VLAN_SIZE_BYTE);
324 }
325 }
326 break;
327
Ratan Guptab8e99552017-07-27 07:07:48 +0530328 default:
329 rc = IPMI_CC_PARM_OUT_OF_RANGE;
tomjose26e17732016-03-03 08:52:51 -0600330 }
331 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530332 catch (InternalFailure& e)
tomjose26e17732016-03-03 08:52:51 -0600333 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530334 commit<InternalFailure>();
335 rc = IPMI_CC_UNSPECIFIED_ERROR;
336 return rc;
tomjose26e17732016-03-03 08:52:51 -0600337 }
tomjose26e17732016-03-03 08:52:51 -0600338 return rc;
339}
340
Tom Josepha30c8d32018-03-22 02:15:03 +0530341namespace cipher
342{
343
344std::vector<uint8_t> getCipherList()
345{
346 std::vector<uint8_t> cipherList;
347
348 std::ifstream jsonFile(configFile);
349 if (!jsonFile.is_open())
350 {
351 log<level::ERR>("Channel Cipher suites file not found");
352 elog<InternalFailure>();
353 }
354
355 auto data = Json::parse(jsonFile, nullptr, false);
356 if (data.is_discarded())
357 {
358 log<level::ERR>("Parsing channel cipher suites JSON failed");
359 elog<InternalFailure>();
360 }
361
362 // Byte 1 is reserved
363 cipherList.push_back(0x00);
364
365 for (const auto& record : data)
366 {
367 cipherList.push_back(record.value(cipher, 0));
368 }
369
370 return cipherList;
371}
372
Patrick Venture0b02be92018-08-31 11:55:55 -0700373} // namespace cipher
Tom Josepha30c8d32018-03-22 02:15:03 +0530374
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500375ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700376 ipmi_request_t request,
377 ipmi_response_t response,
378 ipmi_data_len_t data_len,
379 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500380{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500381 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800382 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500383 *data_len = 0;
384 return rc;
385}
386
Ratan Guptab8e99552017-07-27 07:07:48 +0530387struct set_lan_t
388{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500389 uint8_t channel;
390 uint8_t parameter;
391 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
Patrick Venture0b02be92018-08-31 11:55:55 -0700392} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500393
Patrick Venture0b02be92018-08-31 11:55:55 -0700394ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530395 ipmi_request_t request,
396 ipmi_response_t response,
397 ipmi_data_len_t data_len,
398 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500399{
400 ipmi_ret_t rc = IPMI_CC_OK;
401 *data_len = 0;
Nan Li3d0df912016-10-18 19:51:41 +0800402
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530403 using namespace std::chrono_literals;
404
405 // time to wait before applying the network changes.
406 constexpr auto networkTimeout = 10000000us; // 10 sec
407
Ratan Guptab8e99552017-07-27 07:07:48 +0530408 char ipaddr[INET_ADDRSTRLEN];
409 char netmask[INET_ADDRSTRLEN];
410 char gateway[INET_ADDRSTRLEN];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500411
Ratan Guptab8e99552017-07-27 07:07:48 +0530412 auto reqptr = reinterpret_cast<const set_lan_t*>(request);
413 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500414
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800415 // channel number is the lower nibble
416 int channel = reqptr->channel & CHANNEL_MASK;
417 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
418 if (ethdevice.empty())
419 {
420 return IPMI_CC_INVALID_FIELD_REQUEST;
421 }
422 auto channelConf = getChannelConfig(channel);
423
Ratan Guptab8e99552017-07-27 07:07:48 +0530424 switch (reqptr->parameter)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500425 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530426 case LAN_PARM_IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600427 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530428 snprintf(ipaddr, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700429 reqptr->data[0], reqptr->data[1], reqptr->data[2],
430 reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500431
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800432 channelConf->ipaddr.assign(ipaddr);
Ratan Guptab8e99552017-07-27 07:07:48 +0530433 }
434 break;
435
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530436 case LAN_PARM_IPSRC:
437 {
438 uint8_t ipsrc{};
439 memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800440 channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530441 }
442 break;
443
Ratan Guptab8e99552017-07-27 07:07:48 +0530444 case LAN_PARM_MAC:
445 {
446 char mac[SIZE_MAC];
447
448 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700449 reqptr->data[0], reqptr->data[1], reqptr->data[2],
450 reqptr->data[3], reqptr->data[4], reqptr->data[5]);
Ratan Guptab8e99552017-07-27 07:07:48 +0530451
Patrick Venture0b02be92018-08-31 11:55:55 -0700452 auto macObjectInfo =
453 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
454 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530455
Patrick Venture0b02be92018-08-31 11:55:55 -0700456 ipmi::setDbusProperty(
457 bus, macObjectInfo.second, macObjectInfo.first,
458 ipmi::network::MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptab8e99552017-07-27 07:07:48 +0530459
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800460 channelConf->macAddress = mac;
Ratan Guptab8e99552017-07-27 07:07:48 +0530461 }
462 break;
463
464 case LAN_PARM_SUBNET:
465 {
466 snprintf(netmask, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700467 reqptr->data[0], reqptr->data[1], reqptr->data[2],
468 reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800469 channelConf->netmask.assign(netmask);
Ratan Guptab8e99552017-07-27 07:07:48 +0530470 }
471 break;
472
473 case LAN_PARM_GATEWAY:
474 {
475 snprintf(gateway, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700476 reqptr->data[0], reqptr->data[1], reqptr->data[2],
477 reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800478 channelConf->gateway.assign(gateway);
Ratan Guptab8e99552017-07-27 07:07:48 +0530479 }
480 break;
481
Ratan Gupta533d03b2017-07-30 10:39:22 +0530482 case LAN_PARM_VLAN:
483 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700484 uint16_t vlan{};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530485 memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
486 // We are not storing the enable bit
487 // We assume that ipmitool always send enable
488 // bit as 1.
489 vlan = le16toh(vlan);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800490 channelConf->vlanID = vlan;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530491 }
492 break;
493
Ratan Guptab8e99552017-07-27 07:07:48 +0530494 case LAN_PARM_INPROGRESS:
495 {
496 if (reqptr->data[0] == SET_COMPLETE)
497 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800498 channelConf->lan_set_in_progress = SET_COMPLETE;
Ratan Guptab8e99552017-07-27 07:07:48 +0530499
Patrick Venture0b02be92018-08-31 11:55:55 -0700500 log<level::INFO>(
501 "Network data from Cache",
502 entry("PREFIX=%s", channelConf->netmask.c_str()),
503 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
504 entry("GATEWAY=%s", channelConf->gateway.c_str()),
505 entry("VLAN=%d", channelConf->vlanID));
Ratan Guptab8e99552017-07-27 07:07:48 +0530506
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530507 if (!networkTimer)
508 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700509 log<level::ERR>("Network timer is not instantiated");
510 return IPMI_CC_UNSPECIFIED_ERROR;
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530511 }
512
513 // start/restart the timer
514 networkTimer->startTimer(networkTimeout);
Ratan Guptab8e99552017-07-27 07:07:48 +0530515 }
516 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
517 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800518 channelConf->lan_set_in_progress = SET_IN_PROGRESS;
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530519 channelConf->flush = true;
Ratan Guptab8e99552017-07-27 07:07:48 +0530520 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530521 }
522 break;
523
524 default:
525 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530526 rc = IPMI_CC_PARM_NOT_SUPPORTED;
527 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530528 }
vishwa1eaea4f2016-02-26 11:57:40 -0600529
tomjose26e17732016-03-03 08:52:51 -0600530 return rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500531}
532
Ratan Guptab8e99552017-07-27 07:07:48 +0530533struct get_lan_t
534{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500535 uint8_t rev_channel;
536 uint8_t parameter;
537 uint8_t parameter_set;
538 uint8_t parameter_block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700539} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500540
Patrick Venture0b02be92018-08-31 11:55:55 -0700541ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530542 ipmi_request_t request,
543 ipmi_response_t response,
544 ipmi_data_len_t data_len,
545 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500546{
547 ipmi_ret_t rc = IPMI_CC_OK;
548 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500549 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500550
Patrick Venture0b02be92018-08-31 11:55:55 -0700551 get_lan_t* reqptr = (get_lan_t*)request;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800552 // channel number is the lower nibble
553 int channel = reqptr->rev_channel & CHANNEL_MASK;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500554
555 if (reqptr->rev_channel & 0x80) // Revision is bit 7
556 {
557 // Only current revision was requested
558 *data_len = sizeof(current_revision);
559 memcpy(response, &current_revision, *data_len);
560 return IPMI_CC_OK;
561 }
562
Tom Josepha30c8d32018-03-22 02:15:03 +0530563 static std::vector<uint8_t> cipherList;
564 static auto listInit = false;
565
566 if (!listInit)
567 {
568 try
569 {
570 cipherList = cipher::getCipherList();
571 listInit = true;
572 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700573 catch (const std::exception& e)
Tom Josepha30c8d32018-03-22 02:15:03 +0530574 {
575 return IPMI_CC_UNSPECIFIED_ERROR;
576 }
577 }
578
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800579 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
580 if (ethdevice.empty())
581 {
582 return IPMI_CC_INVALID_FIELD_REQUEST;
583 }
584 auto channelConf = getChannelConfig(channel);
585
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600586 if (reqptr->parameter == LAN_PARM_INPROGRESS)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500587 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800588 uint8_t buf[] = {current_revision, channelConf->lan_set_in_progress};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500589 *data_len = sizeof(buf);
590 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500591 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600592 else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500593 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700594 uint8_t buf[] = {current_revision, 0x04};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500595 *data_len = sizeof(buf);
596 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500597 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600598 else if (reqptr->parameter == LAN_PARM_AUTHENABLES)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500599 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700600 uint8_t buf[] = {current_revision, 0x04, 0x04, 0x04, 0x04, 0x04};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500601 *data_len = sizeof(buf);
602 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500603 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530604 else if ((reqptr->parameter == LAN_PARM_IP) ||
605 (reqptr->parameter == LAN_PARM_SUBNET) ||
606 (reqptr->parameter == LAN_PARM_GATEWAY) ||
607 (reqptr->parameter == LAN_PARM_MAC))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500608 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530609 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1] = {};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500610
tomjose26e17732016-03-03 08:52:51 -0600611 *data_len = sizeof(current_revision);
612 memcpy(buf, &current_revision, *data_len);
613
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800614 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
vishwa1eaea4f2016-02-26 11:57:40 -0600615 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530616 if (reqptr->parameter == LAN_PARM_MAC)
617 {
618 *data_len = sizeof(buf);
619 }
620 else
621 {
622 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1;
623 }
tomjose26e17732016-03-03 08:52:51 -0600624 memcpy(response, &buf, *data_len);
Adriana Kobylak342df102016-02-10 13:48:16 -0600625 }
tomjose26e17732016-03-03 08:52:51 -0600626 else
Hariharasubramanian R83951912016-01-20 07:06:36 -0600627 {
tomjose26e17732016-03-03 08:52:51 -0600628 rc = IPMI_CC_UNSPECIFIED_ERROR;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600629 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500630 }
Ratan Gupta533d03b2017-07-30 10:39:22 +0530631 else if (reqptr->parameter == LAN_PARM_VLAN)
632 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530633 uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530634
635 *data_len = sizeof(current_revision);
636 memcpy(buf, &current_revision, *data_len);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800637 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530638 {
639 *data_len = sizeof(buf);
640 memcpy(response, &buf, *data_len);
641 }
642 }
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530643 else if (reqptr->parameter == LAN_PARM_IPSRC)
644 {
645 uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {};
646 *data_len = sizeof(current_revision);
647 memcpy(buff, &current_revision, *data_len);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800648 if (getNetworkData(reqptr->parameter, &buff[1], channel) == IPMI_CC_OK)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530649 {
650 *data_len = sizeof(buff);
651 memcpy(response, &buff, *data_len);
652 }
653 }
Tom Josepha30c8d32018-03-22 02:15:03 +0530654 else if (reqptr->parameter == CIPHER_SUITE_COUNT)
655 {
656 *(static_cast<uint8_t*>(response)) = current_revision;
657 // Byte 1 is reserved byte and does not indicate a cipher suite ID, so
658 // no of cipher suite entry count is one less than the size of the
659 // vector
660 auto count = static_cast<uint8_t>(cipherList.size() - 1);
661 *(static_cast<uint8_t*>(response) + 1) = count;
662 *data_len = sizeof(current_revision) + sizeof(count);
663 }
664 else if (reqptr->parameter == CIPHER_SUITE_ENTRIES)
665 {
666 *(static_cast<uint8_t*>(response)) = current_revision;
667 // Byte 1 is reserved
Patrick Venture0b02be92018-08-31 11:55:55 -0700668 std::copy_n(cipherList.data(), cipherList.size(),
Tom Josepha30c8d32018-03-22 02:15:03 +0530669 static_cast<uint8_t*>(response) + 1);
Patrick Venture0b02be92018-08-31 11:55:55 -0700670 *data_len =
671 sizeof(current_revision) + static_cast<uint8_t>(cipherList.size());
Tom Josepha30c8d32018-03-22 02:15:03 +0530672 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500673 else
674 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530675 log<level::ERR>("Unsupported parameter",
676 entry("PARAMETER=0x%x", reqptr->parameter));
vishwa1eaea4f2016-02-26 11:57:40 -0600677 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500678 }
679
680 return rc;
681}
682
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530683void applyChanges(int channel)
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530684{
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530685 std::string ipaddress;
686 std::string gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700687 uint8_t prefix{};
688 uint32_t vlanID{};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530689 std::string networkInterfacePath;
690 ipmi::DbusObjectInfo ipObject;
691 ipmi::DbusObjectInfo systemObject;
692
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530693 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
694 if (ethdevice.empty())
695 {
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530696 log<level::ERR>("Unable to get the interface name",
697 entry("CHANNEL=%d", channel));
698 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530699 }
700 auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE;
701 auto channelConf = getChannelConfig(channel);
702
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530703 try
704 {
705 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
706
707 log<level::INFO>("Network data from Cache",
708 entry("PREFIX=%s", channelConf->netmask.c_str()),
709 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
710 entry("GATEWAY=%s", channelConf->gateway.c_str()),
711 entry("VLAN=%d", channelConf->vlanID),
712 entry("IPSRC=%d", channelConf->ipsrc));
713 if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK)
714 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700715 // get the first twelve bits which is vlan id
716 // not interested in rest of the bits.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530717 channelConf->vlanID = le32toh(channelConf->vlanID);
718 vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK;
719 }
720
721 // if the asked ip src is DHCP then not interested in
722 // any given data except vlan.
723 if (channelConf->ipsrc != ipmi::network::IPOrigin::DHCP)
724 {
725 // always get the system object
Patrick Venture0b02be92018-08-31 11:55:55 -0700726 systemObject =
727 ipmi::getDbusObject(bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
728 ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530729
730 // the below code is to determine the mode of the interface
731 // as the handling is same, if the system is configured with
732 // DHCP or user has given all the data.
733 try
734 {
735 ipmi::ObjectTree ancestorMap;
736
Patrick Venture0b02be92018-08-31 11:55:55 -0700737 ipmi::InterfaceList interfaces{
738 ipmi::network::ETHERNET_INTERFACE};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530739
740 // if the system is having ip object,then
741 // get the IP object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700742 ipObject = ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
743 ipmi::network::ROOT, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530744
745 // Get the parent interface of the IP object.
746 try
747 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700748 ancestorMap = ipmi::getAllAncestors(bus, ipObject.first,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530749 std::move(interfaces));
750 }
751 catch (InternalFailure& e)
752 {
753 // if unable to get the parent interface
754 // then commit the error and return.
755 log<level::ERR>("Unable to get the parent interface",
756 entry("PATH=%s", ipObject.first.c_str()),
757 entry("INTERFACE=%s",
758 ipmi::network::ETHERNET_INTERFACE));
759 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530760 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530761 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530762 }
763
764 networkInterfacePath = ancestorMap.begin()->first;
765 }
766 catch (InternalFailure& e)
767 {
768 // TODO Currently IPMI supports single interface,need to handle
769 // Multiple interface through
770 // https://github.com/openbmc/openbmc/issues/2138
771
772 // if there is no ip configured on the system,then
773 // get the network interface object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700774 auto networkInterfaceObject =
775 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
776 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530777
778 networkInterfacePath = std::move(networkInterfaceObject.first);
779 }
780
781 // get the configured mode on the system.
Patrick Venture0b02be92018-08-31 11:55:55 -0700782 auto enableDHCP =
783 ipmi::getDbusProperty(
784 bus, ipmi::network::SERVICE, networkInterfacePath,
785 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled")
786 .get<bool>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530787
788 // if ip address source is not given then get the ip source mode
789 // from the system so that it can be applied later.
790 if (channelConf->ipsrc == ipmi::network::IPOrigin::UNSPECIFIED)
791 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700792 channelConf->ipsrc = (enableDHCP)
793 ? ipmi::network::IPOrigin::DHCP
794 : ipmi::network::IPOrigin::STATIC;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530795 }
796
797 // check whether user has given all the data
798 // or the configured system interface is dhcp enabled,
799 // in both of the cases get the values from the cache.
800 if ((!channelConf->ipaddr.empty() &&
801 !channelConf->netmask.empty() &&
802 !channelConf->gateway.empty()) ||
803 (enableDHCP)) // configured system interface mode = DHCP
804 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700805 // convert mask into prefix
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530806 ipaddress = channelConf->ipaddr;
807 prefix = ipmi::network::toPrefix(AF_INET, channelConf->netmask);
808 gateway = channelConf->gateway;
809 }
810 else // asked ip src = static and configured system src = static
Patrick Venture0b02be92018-08-31 11:55:55 -0700811 // or partially given data.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530812 {
813 // We have partial filled cache so get the remaining
814 // info from the system.
815
816 // Get the network data from the system as user has
817 // not given all the data then use the data fetched from the
818 // system but it is implementation dependent,IPMI spec doesn't
819 // force it.
820
821 // if system is not having any ip object don't throw error,
822 try
823 {
824 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700825 bus, ipObject.second, ipObject.first,
826 ipmi::network::IP_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530827
Patrick Venture0b02be92018-08-31 11:55:55 -0700828 ipaddress = channelConf->ipaddr.empty()
829 ? properties["Address"].get<std::string>()
830 : channelConf->ipaddr;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530831
Patrick Venture0b02be92018-08-31 11:55:55 -0700832 prefix = channelConf->netmask.empty()
833 ? properties["PrefixLength"].get<uint8_t>()
834 : ipmi::network::toPrefix(
835 AF_INET, channelConf->netmask);
836 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530837 catch (InternalFailure& e)
838 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700839 log<level::INFO>(
840 "Failed to get IP object which matches",
841 entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
842 entry("MATCH=%s", ethIp.c_str()));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530843 }
844
845 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700846 bus, systemObject.second, systemObject.first,
847 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530848
Patrick Venture0b02be92018-08-31 11:55:55 -0700849 gateway =
850 channelConf->gateway.empty()
851 ? systemProperties["DefaultGateway"].get<std::string>()
852 : channelConf->gateway;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530853 }
854 }
855
856 // Currently network manager doesn't support purging of all the
857 // ip addresses and the vlan interfaces from the parent interface,
858 // TODO once the support is there, will make the change here.
859 // https://github.com/openbmc/openbmc/issues/2141.
860
861 // TODO Currently IPMI supports single interface,need to handle
862 // Multiple interface through
863 // https://github.com/openbmc/openbmc/issues/2138
864
865 // instead of deleting all the vlan interfaces and
866 // all the ipv4 address,we will call reset method.
Patrick Venture0b02be92018-08-31 11:55:55 -0700867 // delete all the vlan interfaces
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530868
Patrick Venture0b02be92018-08-31 11:55:55 -0700869 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530870 ipmi::network::VLAN_INTERFACE);
871
872 // set the interface mode to static
Patrick Venture0b02be92018-08-31 11:55:55 -0700873 auto networkInterfaceObject =
874 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
875 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530876
877 // setting the physical interface mode to static.
Patrick Venture0b02be92018-08-31 11:55:55 -0700878 ipmi::setDbusProperty(
879 bus, ipmi::network::SERVICE, networkInterfaceObject.first,
880 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530881
882 networkInterfacePath = networkInterfaceObject.first;
883
Patrick Venture0b02be92018-08-31 11:55:55 -0700884 // delete all the ipv4 addresses
885 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
886 ipmi::network::IP_INTERFACE, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530887
888 if (vlanID)
889 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700890 ipmi::network::createVLAN(bus, ipmi::network::SERVICE,
891 ipmi::network::ROOT, ethdevice, vlanID);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530892
893 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700894 bus, ipmi::network::VLAN_INTERFACE, ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530895
Patrick Venture0b02be92018-08-31 11:55:55 -0700896 networkInterfacePath = networkInterfaceObject.first;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530897 }
898
899 if (channelConf->ipsrc == ipmi::network::IPOrigin::DHCP)
900 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700901 ipmi::setDbusProperty(
902 bus, ipmi::network::SERVICE, networkInterfacePath,
903 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", true);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530904 }
905 else
906 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700907 // change the mode to static
908 ipmi::setDbusProperty(
909 bus, ipmi::network::SERVICE, networkInterfacePath,
910 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530911
912 if (!ipaddress.empty())
913 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700914 ipmi::network::createIP(bus, ipmi::network::SERVICE,
915 networkInterfacePath, ipv4Protocol,
916 ipaddress, prefix);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530917 }
918
919 if (!gateway.empty())
920 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700921 ipmi::setDbusProperty(bus, systemObject.second,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530922 systemObject.first,
923 ipmi::network::SYSTEMCONFIG_INTERFACE,
Patrick Venture0b02be92018-08-31 11:55:55 -0700924 "DefaultGateway", std::string(gateway));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530925 }
926 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530927 }
928 catch (InternalFailure& e)
929 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700930 log<level::ERR>(
931 "Failed to set network data", entry("PREFIX=%d", prefix),
932 entry("ADDRESS=%s", ipaddress.c_str()),
933 entry("GATEWAY=%s", gateway.c_str()), entry("VLANID=%d", vlanID),
934 entry("IPSRC=%d", channelConf->ipsrc));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530935
936 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530937 }
938
939 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530940}
941
942void commitNetworkChanges()
943{
Patrick Venture0b02be92018-08-31 11:55:55 -0700944 for (const auto& channel : channelConfig)
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530945 {
946 if (channel.second->flush)
947 {
948 applyChanges(channel.first);
949 }
950 }
951}
952
953void createNetworkTimer()
954{
955 if (!networkTimer)
956 {
957 std::function<void()> networkTimerCallback(
Patrick Venture0b02be92018-08-31 11:55:55 -0700958 std::bind(&commitNetworkChanges));
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530959
Patrick Venture0b02be92018-08-31 11:55:55 -0700960 networkTimer = std::make_unique<phosphor::ipmi::Timer>(
961 ipmid_get_sd_event_connection(), networkTimerCallback);
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530962 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530963}
964
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500965void register_netfn_transport_functions()
966{
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530967 // As this timer is only for transport handler
968 // so creating it here.
969 createNetworkTimer();
Tom05732372016-09-06 17:21:23 +0530970 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -0700971 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL,
972 ipmi_transport_wildcard, PRIVILEGE_USER);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500973
Tom05732372016-09-06 17:21:23 +0530974 // <Set LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700975 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL,
976 ipmi_transport_set_lan, PRIVILEGE_ADMIN);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500977
Tom05732372016-09-06 17:21:23 +0530978 // <Get LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700979 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL,
980 ipmi_transport_get_lan, PRIVILEGE_OPERATOR);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500981
982 return;
983}