blob: 39b1c9f5285f06f881b27ab6f2561eea3371884d [file] [log] [blame]
Patrick Venture586d35b2018-09-07 19:56:18 -07001#include "transporthandler.hpp"
2
Patrick Venture3a5071a2018-09-12 13:27:42 -07003#include "app/channel.hpp"
4#include "ipmid.hpp"
5#include "net.hpp"
Patrick Venture3a5071a2018-09-12 13:27:42 -07006#include "utils.hpp"
7
Patrick Venture0b02be92018-08-31 11:55:55 -07008#include <arpa/inet.h>
Patrick Venture3a5071a2018-09-12 13:27:42 -07009#include <host-ipmid/ipmid-api.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070010
11#include <chrono>
12#include <fstream>
Patrick Venture3a5071a2018-09-12 13:27:42 -070013#include <phosphor-logging/elog-errors.hpp>
14#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070015#include <sdbusplus/message/types.hpp>
Vernon Mauery1181af72018-10-08 12:05:00 -070016#include <sdbusplus/timer.hpp>
tomjose26e17732016-03-03 08:52:51 -060017#include <string>
Patrick Venture3a5071a2018-09-12 13:27:42 -070018#include <xyz/openbmc_project/Common/error.hpp>
19
20#define SYSTEMD_NETWORKD_DBUS 1
21
22#ifdef SYSTEMD_NETWORKD_DBUS
23#include <mapper.h>
24#include <systemd/sd-bus.h>
25#endif
Patrick Venture586d35b2018-09-07 19:56:18 -070026
Vernon Mauery185b9f82018-07-20 10:52:36 -070027#if __has_include(<filesystem>)
28#include <filesystem>
29#elif __has_include(<experimental/filesystem>)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053030#include <experimental/filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -070031namespace std
32{
33// splice experimental::filesystem into std
34namespace filesystem = std::experimental::filesystem;
35} // namespace std
Vernon Mauery185b9f82018-07-20 10:52:36 -070036#else
Patrick Venture0b02be92018-08-31 11:55:55 -070037#error filesystem not available
Vernon Mauery185b9f82018-07-20 10:52:36 -070038#endif
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050039
Vernon Mauery1181af72018-10-08 12:05:00 -070040extern std::unique_ptr<phosphor::Timer> networkTimer;
Ratan Gupta1247e0b2018-03-07 10:47:25 +053041
Patrick Venture0b02be92018-08-31 11:55:55 -070042const int SIZE_MAC = 18; // xx:xx:xx:xx:xx:xx
Ratan Gupta1247e0b2018-03-07 10:47:25 +053043constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Adriana Kobylake08fbc62016-02-09 16:17:23 -060044
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080045std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
Hariharasubramanian R83951912016-01-20 07:06:36 -060046
Ratan Guptab8e99552017-07-27 07:07:48 +053047using namespace phosphor::logging;
48using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta7a7f0122018-03-07 12:31:05 +053049
Vernon Mauery185b9f82018-07-20 10:52:36 -070050namespace fs = std::filesystem;
William A. Kennington III4c008022018-10-12 17:18:14 -070051namespace variant_ns = sdbusplus::message::variant_ns;
Hariharasubramanian R83951912016-01-20 07:06:36 -060052
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050053void register_netfn_transport_functions() __attribute__((constructor));
54
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080055struct ChannelConfig_t* getChannelConfig(int channel)
56{
57 auto item = channelConfig.find(channel);
58 if (item == channelConfig.end())
59 {
60 channelConfig[channel] = std::make_unique<struct ChannelConfig_t>();
61 }
62
63 return channelConfig[channel].get();
64}
65
Patrick Venture0b02be92018-08-31 11:55:55 -070066// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network
67// Manager or Cache based on Set-In-Progress State
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080068ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel)
tomjose26e17732016-03-03 08:52:51 -060069{
tomjose26e17732016-03-03 08:52:51 -060070 ipmi_ret_t rc = IPMI_CC_OK;
Ratan Guptab8e99552017-07-27 07:07:48 +053071 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Gupta533d03b2017-07-30 10:39:22 +053072
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080073 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
74 // if ethdevice is an empty string they weren't expecting this channel.
75 if (ethdevice.empty())
76 {
77 // TODO: return error from getNetworkData()
78 return IPMI_CC_INVALID_FIELD_REQUEST;
79 }
80 auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE;
81 auto channelConf = getChannelConfig(channel);
82
Ratan Guptab8e99552017-07-27 07:07:48 +053083 try
tomjose26e17732016-03-03 08:52:51 -060084 {
Ratan Guptab8e99552017-07-27 07:07:48 +053085 switch (lan_param)
tomjose26e17732016-03-03 08:52:51 -060086 {
Ratan Guptab8e99552017-07-27 07:07:48 +053087 case LAN_PARM_IP:
88 {
89 std::string ipaddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080090 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +053091 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053092 try
93 {
Patrick Venture0b02be92018-08-31 11:55:55 -070094 auto ipObjectInfo =
95 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
96 ipmi::network::ROOT, ethIP);
Ratan Guptadd646202017-11-21 17:46:59 +053097
98 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -070099 bus, ipObjectInfo.second, ipObjectInfo.first,
100 ipmi::network::IP_INTERFACE);
Ratan Guptadd646202017-11-21 17:46:59 +0530101
William A. Kennington III4c008022018-10-12 17:18:14 -0700102 ipaddress =
103 variant_ns::get<std::string>(properties["Address"]);
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
William A. Kennington III4c008022018-10-12 17:18:14 -0700177 auto dhcpEnabled = variant_ns::get<bool>(variant);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530178 // 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
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700182 std::memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530183 }
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 Ventureb51bf9c2018-09-10 15:53:14 -0700186 std::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
William A. Kennington III4c008022018-10-12 17:18:14 -0700207 auto prefix = variant_ns::get<uint8_t>(
208 properties["PrefixLength"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530209 mask = ipmi::network::MASK_32_BIT;
210 mask = htonl(mask << (ipmi::network::BITS_32 - prefix));
211 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500212 // ignore the exception, as it is a valid condition that
213 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530214 catch (InternalFailure& e)
215 {
216 // nothing to do
217 }
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700218 std::memcpy(data, &mask,
219 ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530220 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800221 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530222 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800223 inet_pton(AF_INET, channelConf->netmask.c_str(),
Ratan Guptab8e99552017-07-27 07:07:48 +0530224 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530225 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530226 }
227 break;
228
229 case LAN_PARM_GATEWAY:
230 {
231 std::string gateway;
232
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800233 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530234 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530235 try
236 {
237 auto systemObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700238 bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
239 ipmi::network::ROOT);
Ratan Guptab8e99552017-07-27 07:07:48 +0530240
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530241 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700242 bus, systemObject.second, systemObject.first,
243 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530244
William A. Kennington III4c008022018-10-12 17:18:14 -0700245 gateway = variant_ns::get<std::string>(
246 systemProperties["DefaultGateway"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530247 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500248 // ignore the exception, as it is a valid condition that
249 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530250 catch (InternalFailure& e)
251 {
252 // nothing to do
253 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530254 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800255 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530256 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800257 gateway = channelConf->gateway;
Ratan Guptab8e99552017-07-27 07:07:48 +0530258 }
259
260 inet_pton(AF_INET, gateway.c_str(),
261 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530262 }
263 break;
264
265 case LAN_PARM_MAC:
266 {
267 std::string macAddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800268 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530269 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700270 auto macObjectInfo =
271 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
272 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530273
274 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700275 bus, macObjectInfo.second, macObjectInfo.first,
276 ipmi::network::MAC_INTERFACE, "MACAddress");
Ratan Guptab8e99552017-07-27 07:07:48 +0530277
William A. Kennington III4c008022018-10-12 17:18:14 -0700278 macAddress = variant_ns::get<std::string>(variant);
Ratan Guptab8e99552017-07-27 07:07:48 +0530279 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800280 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530281 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800282 macAddress = channelConf->macAddress;
Ratan Guptab8e99552017-07-27 07:07:48 +0530283 }
284
285 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700286 (data), (data + 1), (data + 2), (data + 3), (data + 4),
Ratan Guptab8e99552017-07-27 07:07:48 +0530287 (data + 5));
288 }
289 break;
290
Ratan Gupta533d03b2017-07-30 10:39:22 +0530291 case LAN_PARM_VLAN:
292 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700293 uint16_t vlanID{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800294 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530295 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530296 try
Ratan Gupta533d03b2017-07-30 10:39:22 +0530297 {
Ratan Guptadd646202017-11-21 17:46:59 +0530298 auto ipObjectInfo = ipmi::getIPObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700299 bus, ipmi::network::IP_INTERFACE,
300 ipmi::network::ROOT, ipmi::network::IP_TYPE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530301
302 vlanID = static_cast<uint16_t>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700303 ipmi::network::getVLAN(ipObjectInfo.first));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530304
305 vlanID = htole16(vlanID);
306
307 if (vlanID)
308 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700309 // Enable the 16th bit
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530310 vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK);
311 }
312 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500313 // ignore the exception, as it is a valid condition that
314 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530315 catch (InternalFailure& e)
316 {
317 // nothing to do
Ratan Gupta533d03b2017-07-30 10:39:22 +0530318 }
319
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700320 std::memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530321 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800322 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530323 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700324 std::memcpy(data, &(channelConf->vlanID),
325 ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530326 }
327 }
328 break;
329
Ratan Guptab8e99552017-07-27 07:07:48 +0530330 default:
331 rc = IPMI_CC_PARM_OUT_OF_RANGE;
tomjose26e17732016-03-03 08:52:51 -0600332 }
333 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530334 catch (InternalFailure& e)
tomjose26e17732016-03-03 08:52:51 -0600335 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530336 commit<InternalFailure>();
337 rc = IPMI_CC_UNSPECIFIED_ERROR;
338 return rc;
tomjose26e17732016-03-03 08:52:51 -0600339 }
tomjose26e17732016-03-03 08:52:51 -0600340 return rc;
341}
342
Tom Josepha30c8d32018-03-22 02:15:03 +0530343namespace cipher
344{
345
346std::vector<uint8_t> getCipherList()
347{
348 std::vector<uint8_t> cipherList;
349
350 std::ifstream jsonFile(configFile);
351 if (!jsonFile.is_open())
352 {
353 log<level::ERR>("Channel Cipher suites file not found");
354 elog<InternalFailure>();
355 }
356
357 auto data = Json::parse(jsonFile, nullptr, false);
358 if (data.is_discarded())
359 {
360 log<level::ERR>("Parsing channel cipher suites JSON failed");
361 elog<InternalFailure>();
362 }
363
364 // Byte 1 is reserved
365 cipherList.push_back(0x00);
366
367 for (const auto& record : data)
368 {
369 cipherList.push_back(record.value(cipher, 0));
370 }
371
372 return cipherList;
373}
374
Patrick Venture0b02be92018-08-31 11:55:55 -0700375} // namespace cipher
Tom Josepha30c8d32018-03-22 02:15:03 +0530376
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500377ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700378 ipmi_request_t request,
379 ipmi_response_t response,
380 ipmi_data_len_t data_len,
381 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500382{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500383 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800384 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500385 *data_len = 0;
386 return rc;
387}
388
Ratan Guptab8e99552017-07-27 07:07:48 +0530389struct set_lan_t
390{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500391 uint8_t channel;
392 uint8_t parameter;
393 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
Patrick Venture0b02be92018-08-31 11:55:55 -0700394} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500395
Patrick Venture0b02be92018-08-31 11:55:55 -0700396ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530397 ipmi_request_t request,
398 ipmi_response_t response,
399 ipmi_data_len_t data_len,
400 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500401{
402 ipmi_ret_t rc = IPMI_CC_OK;
403 *data_len = 0;
Nan Li3d0df912016-10-18 19:51:41 +0800404
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530405 using namespace std::chrono_literals;
406
407 // time to wait before applying the network changes.
408 constexpr auto networkTimeout = 10000000us; // 10 sec
409
Ratan Guptab8e99552017-07-27 07:07:48 +0530410 char ipaddr[INET_ADDRSTRLEN];
411 char netmask[INET_ADDRSTRLEN];
412 char gateway[INET_ADDRSTRLEN];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500413
Ratan Guptab8e99552017-07-27 07:07:48 +0530414 auto reqptr = reinterpret_cast<const set_lan_t*>(request);
415 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500416
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800417 // channel number is the lower nibble
418 int channel = reqptr->channel & CHANNEL_MASK;
419 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
420 if (ethdevice.empty())
421 {
422 return IPMI_CC_INVALID_FIELD_REQUEST;
423 }
424 auto channelConf = getChannelConfig(channel);
425
Ratan Guptab8e99552017-07-27 07:07:48 +0530426 switch (reqptr->parameter)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500427 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530428 case LAN_PARM_IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600429 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700430 std::snprintf(ipaddr, INET_ADDRSTRLEN,
431 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
432 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500433
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800434 channelConf->ipaddr.assign(ipaddr);
Ratan Guptab8e99552017-07-27 07:07:48 +0530435 }
436 break;
437
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530438 case LAN_PARM_IPSRC:
439 {
440 uint8_t ipsrc{};
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700441 std::memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800442 channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530443 }
444 break;
445
Ratan Guptab8e99552017-07-27 07:07:48 +0530446 case LAN_PARM_MAC:
447 {
448 char mac[SIZE_MAC];
449
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700450 std::snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
451 reqptr->data[0], reqptr->data[1], reqptr->data[2],
452 reqptr->data[3], reqptr->data[4], reqptr->data[5]);
Ratan Guptab8e99552017-07-27 07:07:48 +0530453
Patrick Venture0b02be92018-08-31 11:55:55 -0700454 auto macObjectInfo =
455 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
456 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530457
Patrick Venture0b02be92018-08-31 11:55:55 -0700458 ipmi::setDbusProperty(
459 bus, macObjectInfo.second, macObjectInfo.first,
460 ipmi::network::MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptab8e99552017-07-27 07:07:48 +0530461
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800462 channelConf->macAddress = mac;
Ratan Guptab8e99552017-07-27 07:07:48 +0530463 }
464 break;
465
466 case LAN_PARM_SUBNET:
467 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700468 std::snprintf(netmask, INET_ADDRSTRLEN,
469 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
470 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800471 channelConf->netmask.assign(netmask);
Ratan Guptab8e99552017-07-27 07:07:48 +0530472 }
473 break;
474
475 case LAN_PARM_GATEWAY:
476 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700477 std::snprintf(gateway, INET_ADDRSTRLEN,
478 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
479 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800480 channelConf->gateway.assign(gateway);
Ratan Guptab8e99552017-07-27 07:07:48 +0530481 }
482 break;
483
Ratan Gupta533d03b2017-07-30 10:39:22 +0530484 case LAN_PARM_VLAN:
485 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700486 uint16_t vlan{};
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700487 std::memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530488 // We are not storing the enable bit
489 // We assume that ipmitool always send enable
490 // bit as 1.
491 vlan = le16toh(vlan);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800492 channelConf->vlanID = vlan;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530493 }
494 break;
495
Ratan Guptab8e99552017-07-27 07:07:48 +0530496 case LAN_PARM_INPROGRESS:
497 {
498 if (reqptr->data[0] == SET_COMPLETE)
499 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800500 channelConf->lan_set_in_progress = SET_COMPLETE;
Ratan Guptab8e99552017-07-27 07:07:48 +0530501
Patrick Venture0b02be92018-08-31 11:55:55 -0700502 log<level::INFO>(
503 "Network data from Cache",
504 entry("PREFIX=%s", channelConf->netmask.c_str()),
505 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
506 entry("GATEWAY=%s", channelConf->gateway.c_str()),
507 entry("VLAN=%d", channelConf->vlanID));
Ratan Guptab8e99552017-07-27 07:07:48 +0530508
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530509 if (!networkTimer)
510 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700511 log<level::ERR>("Network timer is not instantiated");
512 return IPMI_CC_UNSPECIFIED_ERROR;
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530513 }
514
515 // start/restart the timer
Vernon Mauery1181af72018-10-08 12:05:00 -0700516 networkTimer->start(networkTimeout);
Ratan Guptab8e99552017-07-27 07:07:48 +0530517 }
518 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
519 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800520 channelConf->lan_set_in_progress = SET_IN_PROGRESS;
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530521 channelConf->flush = true;
Ratan Guptab8e99552017-07-27 07:07:48 +0530522 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530523 }
524 break;
525
526 default:
527 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530528 rc = IPMI_CC_PARM_NOT_SUPPORTED;
529 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530530 }
vishwa1eaea4f2016-02-26 11:57:40 -0600531
tomjose26e17732016-03-03 08:52:51 -0600532 return rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500533}
534
Ratan Guptab8e99552017-07-27 07:07:48 +0530535struct get_lan_t
536{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500537 uint8_t rev_channel;
538 uint8_t parameter;
539 uint8_t parameter_set;
540 uint8_t parameter_block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700541} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500542
Patrick Venture0b02be92018-08-31 11:55:55 -0700543ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530544 ipmi_request_t request,
545 ipmi_response_t response,
546 ipmi_data_len_t data_len,
547 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500548{
549 ipmi_ret_t rc = IPMI_CC_OK;
550 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500551 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500552
Patrick Venture0b02be92018-08-31 11:55:55 -0700553 get_lan_t* reqptr = (get_lan_t*)request;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800554 // channel number is the lower nibble
555 int channel = reqptr->rev_channel & CHANNEL_MASK;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500556
557 if (reqptr->rev_channel & 0x80) // Revision is bit 7
558 {
559 // Only current revision was requested
560 *data_len = sizeof(current_revision);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700561 std::memcpy(response, &current_revision, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500562 return IPMI_CC_OK;
563 }
564
Tom Josepha30c8d32018-03-22 02:15:03 +0530565 static std::vector<uint8_t> cipherList;
566 static auto listInit = false;
567
568 if (!listInit)
569 {
570 try
571 {
572 cipherList = cipher::getCipherList();
573 listInit = true;
574 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700575 catch (const std::exception& e)
Tom Josepha30c8d32018-03-22 02:15:03 +0530576 {
577 return IPMI_CC_UNSPECIFIED_ERROR;
578 }
579 }
580
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800581 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
582 if (ethdevice.empty())
583 {
584 return IPMI_CC_INVALID_FIELD_REQUEST;
585 }
586 auto channelConf = getChannelConfig(channel);
587
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600588 if (reqptr->parameter == LAN_PARM_INPROGRESS)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500589 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800590 uint8_t buf[] = {current_revision, channelConf->lan_set_in_progress};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500591 *data_len = sizeof(buf);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700592 std::memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500593 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600594 else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500595 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700596 uint8_t buf[] = {current_revision, 0x04};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500597 *data_len = sizeof(buf);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700598 std::memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500599 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600600 else if (reqptr->parameter == LAN_PARM_AUTHENABLES)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500601 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700602 uint8_t buf[] = {current_revision, 0x04, 0x04, 0x04, 0x04, 0x04};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500603 *data_len = sizeof(buf);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700604 std::memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500605 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530606 else if ((reqptr->parameter == LAN_PARM_IP) ||
607 (reqptr->parameter == LAN_PARM_SUBNET) ||
608 (reqptr->parameter == LAN_PARM_GATEWAY) ||
609 (reqptr->parameter == LAN_PARM_MAC))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500610 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530611 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1] = {};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500612
tomjose26e17732016-03-03 08:52:51 -0600613 *data_len = sizeof(current_revision);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700614 std::memcpy(buf, &current_revision, *data_len);
tomjose26e17732016-03-03 08:52:51 -0600615
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800616 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
vishwa1eaea4f2016-02-26 11:57:40 -0600617 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530618 if (reqptr->parameter == LAN_PARM_MAC)
619 {
620 *data_len = sizeof(buf);
621 }
622 else
623 {
624 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1;
625 }
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700626 std::memcpy(response, &buf, *data_len);
Adriana Kobylak342df102016-02-10 13:48:16 -0600627 }
tomjose26e17732016-03-03 08:52:51 -0600628 else
Hariharasubramanian R83951912016-01-20 07:06:36 -0600629 {
tomjose26e17732016-03-03 08:52:51 -0600630 rc = IPMI_CC_UNSPECIFIED_ERROR;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600631 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500632 }
Ratan Gupta533d03b2017-07-30 10:39:22 +0530633 else if (reqptr->parameter == LAN_PARM_VLAN)
634 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530635 uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530636
637 *data_len = sizeof(current_revision);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700638 std::memcpy(buf, &current_revision, *data_len);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800639 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530640 {
641 *data_len = sizeof(buf);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700642 std::memcpy(response, &buf, *data_len);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530643 }
644 }
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530645 else if (reqptr->parameter == LAN_PARM_IPSRC)
646 {
647 uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {};
648 *data_len = sizeof(current_revision);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700649 std::memcpy(buff, &current_revision, *data_len);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800650 if (getNetworkData(reqptr->parameter, &buff[1], channel) == IPMI_CC_OK)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530651 {
652 *data_len = sizeof(buff);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700653 std::memcpy(response, &buff, *data_len);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530654 }
655 }
Tom Josepha30c8d32018-03-22 02:15:03 +0530656 else if (reqptr->parameter == CIPHER_SUITE_COUNT)
657 {
658 *(static_cast<uint8_t*>(response)) = current_revision;
659 // Byte 1 is reserved byte and does not indicate a cipher suite ID, so
660 // no of cipher suite entry count is one less than the size of the
661 // vector
662 auto count = static_cast<uint8_t>(cipherList.size() - 1);
663 *(static_cast<uint8_t*>(response) + 1) = count;
664 *data_len = sizeof(current_revision) + sizeof(count);
665 }
666 else if (reqptr->parameter == CIPHER_SUITE_ENTRIES)
667 {
668 *(static_cast<uint8_t*>(response)) = current_revision;
669 // Byte 1 is reserved
Patrick Venture0b02be92018-08-31 11:55:55 -0700670 std::copy_n(cipherList.data(), cipherList.size(),
Tom Josepha30c8d32018-03-22 02:15:03 +0530671 static_cast<uint8_t*>(response) + 1);
Patrick Venture0b02be92018-08-31 11:55:55 -0700672 *data_len =
673 sizeof(current_revision) + static_cast<uint8_t>(cipherList.size());
Tom Josepha30c8d32018-03-22 02:15:03 +0530674 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500675 else
676 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530677 log<level::ERR>("Unsupported parameter",
678 entry("PARAMETER=0x%x", reqptr->parameter));
vishwa1eaea4f2016-02-26 11:57:40 -0600679 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500680 }
681
682 return rc;
683}
684
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530685void applyChanges(int channel)
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530686{
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530687 std::string ipaddress;
688 std::string gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700689 uint8_t prefix{};
690 uint32_t vlanID{};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530691 std::string networkInterfacePath;
692 ipmi::DbusObjectInfo ipObject;
693 ipmi::DbusObjectInfo systemObject;
694
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530695 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
696 if (ethdevice.empty())
697 {
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530698 log<level::ERR>("Unable to get the interface name",
699 entry("CHANNEL=%d", channel));
700 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530701 }
702 auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE;
703 auto channelConf = getChannelConfig(channel);
704
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530705 try
706 {
707 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
708
709 log<level::INFO>("Network data from Cache",
710 entry("PREFIX=%s", channelConf->netmask.c_str()),
711 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
712 entry("GATEWAY=%s", channelConf->gateway.c_str()),
713 entry("VLAN=%d", channelConf->vlanID),
714 entry("IPSRC=%d", channelConf->ipsrc));
715 if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK)
716 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700717 // get the first twelve bits which is vlan id
718 // not interested in rest of the bits.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530719 channelConf->vlanID = le32toh(channelConf->vlanID);
720 vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK;
721 }
722
723 // if the asked ip src is DHCP then not interested in
724 // any given data except vlan.
725 if (channelConf->ipsrc != ipmi::network::IPOrigin::DHCP)
726 {
727 // always get the system object
Patrick Venture0b02be92018-08-31 11:55:55 -0700728 systemObject =
729 ipmi::getDbusObject(bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
730 ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530731
732 // the below code is to determine the mode of the interface
733 // as the handling is same, if the system is configured with
734 // DHCP or user has given all the data.
735 try
736 {
737 ipmi::ObjectTree ancestorMap;
738
Patrick Venture0b02be92018-08-31 11:55:55 -0700739 ipmi::InterfaceList interfaces{
740 ipmi::network::ETHERNET_INTERFACE};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530741
742 // if the system is having ip object,then
743 // get the IP object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700744 ipObject = ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
745 ipmi::network::ROOT, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530746
747 // Get the parent interface of the IP object.
748 try
749 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700750 ancestorMap = ipmi::getAllAncestors(bus, ipObject.first,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530751 std::move(interfaces));
752 }
753 catch (InternalFailure& e)
754 {
755 // if unable to get the parent interface
756 // then commit the error and return.
757 log<level::ERR>("Unable to get the parent interface",
758 entry("PATH=%s", ipObject.first.c_str()),
759 entry("INTERFACE=%s",
760 ipmi::network::ETHERNET_INTERFACE));
761 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530762 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530763 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530764 }
765
766 networkInterfacePath = ancestorMap.begin()->first;
767 }
768 catch (InternalFailure& e)
769 {
770 // TODO Currently IPMI supports single interface,need to handle
771 // Multiple interface through
772 // https://github.com/openbmc/openbmc/issues/2138
773
774 // if there is no ip configured on the system,then
775 // get the network interface object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700776 auto networkInterfaceObject =
777 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
778 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530779
780 networkInterfacePath = std::move(networkInterfaceObject.first);
781 }
782
783 // get the configured mode on the system.
William A. Kennington III4c008022018-10-12 17:18:14 -0700784 auto enableDHCP = variant_ns::get<bool>(ipmi::getDbusProperty(
785 bus, ipmi::network::SERVICE, networkInterfacePath,
786 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled"));
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()
William A. Kennington III4c008022018-10-12 17:18:14 -0700829 ? variant_ns::get<std::string>(
830 properties["Address"])
Patrick Venture0b02be92018-08-31 11:55:55 -0700831 : channelConf->ipaddr;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530832
Patrick Venture0b02be92018-08-31 11:55:55 -0700833 prefix = channelConf->netmask.empty()
William A. Kennington III4c008022018-10-12 17:18:14 -0700834 ? variant_ns::get<uint8_t>(
835 properties["PrefixLength"])
Patrick Venture0b02be92018-08-31 11:55:55 -0700836 : ipmi::network::toPrefix(
837 AF_INET, channelConf->netmask);
838 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530839 catch (InternalFailure& e)
840 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700841 log<level::INFO>(
842 "Failed to get IP object which matches",
843 entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
844 entry("MATCH=%s", ethIp.c_str()));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530845 }
846
847 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700848 bus, systemObject.second, systemObject.first,
849 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530850
William A. Kennington III4c008022018-10-12 17:18:14 -0700851 gateway = channelConf->gateway.empty()
852 ? variant_ns::get<std::string>(
853 systemProperties["DefaultGateway"])
854 : channelConf->gateway;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530855 }
856 }
857
858 // Currently network manager doesn't support purging of all the
859 // ip addresses and the vlan interfaces from the parent interface,
860 // TODO once the support is there, will make the change here.
861 // https://github.com/openbmc/openbmc/issues/2141.
862
863 // TODO Currently IPMI supports single interface,need to handle
864 // Multiple interface through
865 // https://github.com/openbmc/openbmc/issues/2138
866
867 // instead of deleting all the vlan interfaces and
868 // all the ipv4 address,we will call reset method.
Patrick Venture0b02be92018-08-31 11:55:55 -0700869 // delete all the vlan interfaces
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530870
Patrick Venture0b02be92018-08-31 11:55:55 -0700871 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530872 ipmi::network::VLAN_INTERFACE);
873
874 // set the interface mode to static
Patrick Venture0b02be92018-08-31 11:55:55 -0700875 auto networkInterfaceObject =
876 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
877 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530878
879 // setting the physical interface mode to static.
Patrick Venture0b02be92018-08-31 11:55:55 -0700880 ipmi::setDbusProperty(
881 bus, ipmi::network::SERVICE, networkInterfaceObject.first,
882 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530883
884 networkInterfacePath = networkInterfaceObject.first;
885
Patrick Venture0b02be92018-08-31 11:55:55 -0700886 // delete all the ipv4 addresses
887 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
888 ipmi::network::IP_INTERFACE, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530889
890 if (vlanID)
891 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700892 ipmi::network::createVLAN(bus, ipmi::network::SERVICE,
893 ipmi::network::ROOT, ethdevice, vlanID);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530894
895 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700896 bus, ipmi::network::VLAN_INTERFACE, ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530897
Patrick Venture0b02be92018-08-31 11:55:55 -0700898 networkInterfacePath = networkInterfaceObject.first;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530899 }
900
901 if (channelConf->ipsrc == ipmi::network::IPOrigin::DHCP)
902 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700903 ipmi::setDbusProperty(
904 bus, ipmi::network::SERVICE, networkInterfacePath,
905 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", true);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530906 }
907 else
908 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700909 // change the mode to static
910 ipmi::setDbusProperty(
911 bus, ipmi::network::SERVICE, networkInterfacePath,
912 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530913
914 if (!ipaddress.empty())
915 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700916 ipmi::network::createIP(bus, ipmi::network::SERVICE,
917 networkInterfacePath, ipv4Protocol,
918 ipaddress, prefix);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530919 }
920
921 if (!gateway.empty())
922 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700923 ipmi::setDbusProperty(bus, systemObject.second,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530924 systemObject.first,
925 ipmi::network::SYSTEMCONFIG_INTERFACE,
Patrick Venture0b02be92018-08-31 11:55:55 -0700926 "DefaultGateway", std::string(gateway));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530927 }
928 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530929 }
930 catch (InternalFailure& e)
931 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700932 log<level::ERR>(
933 "Failed to set network data", entry("PREFIX=%d", prefix),
934 entry("ADDRESS=%s", ipaddress.c_str()),
935 entry("GATEWAY=%s", gateway.c_str()), entry("VLANID=%d", vlanID),
936 entry("IPSRC=%d", channelConf->ipsrc));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530937
938 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530939 }
940
941 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530942}
943
944void commitNetworkChanges()
945{
Patrick Venture0b02be92018-08-31 11:55:55 -0700946 for (const auto& channel : channelConfig)
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530947 {
948 if (channel.second->flush)
949 {
950 applyChanges(channel.first);
951 }
952 }
953}
954
955void createNetworkTimer()
956{
957 if (!networkTimer)
958 {
959 std::function<void()> networkTimerCallback(
Patrick Venture0b02be92018-08-31 11:55:55 -0700960 std::bind(&commitNetworkChanges));
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530961
Vernon Mauery1181af72018-10-08 12:05:00 -0700962 networkTimer = std::make_unique<phosphor::Timer>(networkTimerCallback);
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530963 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530964}
965
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500966void register_netfn_transport_functions()
967{
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530968 // As this timer is only for transport handler
969 // so creating it here.
970 createNetworkTimer();
Tom05732372016-09-06 17:21:23 +0530971 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -0700972 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL,
973 ipmi_transport_wildcard, PRIVILEGE_USER);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500974
Tom05732372016-09-06 17:21:23 +0530975 // <Set LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700976 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL,
977 ipmi_transport_set_lan, PRIVILEGE_ADMIN);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500978
Tom05732372016-09-06 17:21:23 +0530979 // <Get LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700980 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL,
981 ipmi_transport_get_lan, PRIVILEGE_OPERATOR);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500982
983 return;
984}