blob: 59d933a77e86968130f7a6707b5ec543ccded988 [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"
Johnathan Mantey74a21022018-12-13 13:17:56 -08004#include "user_channel/channel_layer.hpp"
Patrick Venture3a5071a2018-09-12 13:27:42 -07005
Patrick Venture0b02be92018-08-31 11:55:55 -07006#include <arpa/inet.h>
Patrick Venture0b02be92018-08-31 11:55:55 -07007
8#include <chrono>
Vernon Mauerybdda8002019-02-26 10:18:51 -08009#include <filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -070010#include <fstream>
Vernon Mauerye08fbff2019-04-03 09:19:34 -070011#include <ipmid/api.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070012#include <ipmid/utils.hpp>
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 Mauery1b7f6f22019-03-13 13:11:25 -070027// timer for network changes
28std::unique_ptr<phosphor::Timer> networkTimer = nullptr;
Ratan Gupta1247e0b2018-03-07 10:47:25 +053029
Patrick Venture0b02be92018-08-31 11:55:55 -070030const int SIZE_MAC = 18; // xx:xx:xx:xx:xx:xx
Ratan Gupta1247e0b2018-03-07 10:47:25 +053031constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Adriana Kobylake08fbc62016-02-09 16:17:23 -060032
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080033std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
Hariharasubramanian R83951912016-01-20 07:06:36 -060034
Ratan Guptab8e99552017-07-27 07:07:48 +053035using namespace phosphor::logging;
36using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta7a7f0122018-03-07 12:31:05 +053037
Vernon Mauery185b9f82018-07-20 10:52:36 -070038namespace fs = std::filesystem;
William A. Kennington III4c008022018-10-12 17:18:14 -070039namespace variant_ns = sdbusplus::message::variant_ns;
Hariharasubramanian R83951912016-01-20 07:06:36 -060040
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050041void register_netfn_transport_functions() __attribute__((constructor));
42
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080043struct ChannelConfig_t* getChannelConfig(int channel)
44{
45 auto item = channelConfig.find(channel);
46 if (item == channelConfig.end())
47 {
48 channelConfig[channel] = std::make_unique<struct ChannelConfig_t>();
49 }
50
51 return channelConfig[channel].get();
52}
53
Patrick Venture0b02be92018-08-31 11:55:55 -070054// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network
55// Manager or Cache based on Set-In-Progress State
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080056ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel)
tomjose26e17732016-03-03 08:52:51 -060057{
tomjose26e17732016-03-03 08:52:51 -060058 ipmi_ret_t rc = IPMI_CC_OK;
Ratan Guptab8e99552017-07-27 07:07:48 +053059 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Gupta533d03b2017-07-30 10:39:22 +053060
Johnathan Mantey74a21022018-12-13 13:17:56 -080061 auto ethdevice = ipmi::getChannelName(channel);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080062 // if ethdevice is an empty string they weren't expecting this channel.
63 if (ethdevice.empty())
64 {
65 // TODO: return error from getNetworkData()
66 return IPMI_CC_INVALID_FIELD_REQUEST;
67 }
68 auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE;
69 auto channelConf = getChannelConfig(channel);
70
Ratan Guptab8e99552017-07-27 07:07:48 +053071 try
tomjose26e17732016-03-03 08:52:51 -060072 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -080073 switch (static_cast<LanParam>(lan_param))
tomjose26e17732016-03-03 08:52:51 -060074 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -080075 case LanParam::IP:
Ratan Guptab8e99552017-07-27 07:07:48 +053076 {
77 std::string ipaddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080078 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +053079 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053080 try
81 {
Patrick Venture0b02be92018-08-31 11:55:55 -070082 auto ipObjectInfo =
83 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
84 ipmi::network::ROOT, ethIP);
Ratan Guptadd646202017-11-21 17:46:59 +053085
86 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -070087 bus, ipObjectInfo.second, ipObjectInfo.first,
88 ipmi::network::IP_INTERFACE);
Ratan Guptadd646202017-11-21 17:46:59 +053089
William A. Kennington III4c008022018-10-12 17:18:14 -070090 ipaddress =
91 variant_ns::get<std::string>(properties["Address"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053092 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -050093 // ignore the exception, as it is a valid condition that
94 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053095 catch (InternalFailure& e)
96 {
97 // nothing to do.
98 }
Ratan Guptab8e99552017-07-27 07:07:48 +053099 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800100 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530101 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800102 ipaddress = channelConf->ipaddr;
Ratan Guptab8e99552017-07-27 07:07:48 +0530103 }
104
105 inet_pton(AF_INET, ipaddress.c_str(),
106 reinterpret_cast<void*>(data));
107 }
108 break;
109
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800110 case LanParam::IPSRC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530111 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530112 std::string networkInterfacePath;
113
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800114 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530115 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530116 try
117 {
118 ipmi::ObjectTree ancestorMap;
119 // if the system is having ip object,then
120 // get the IP object.
121 auto ipObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700122 bus, ipmi::network::IP_INTERFACE,
123 ipmi::network::ROOT, ethIP);
Ratan Guptab8e99552017-07-27 07:07:48 +0530124
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530125 // Get the parent interface of the IP object.
126 try
127 {
128 ipmi::InterfaceList interfaces;
129 interfaces.emplace_back(
Patrick Venture0b02be92018-08-31 11:55:55 -0700130 ipmi::network::ETHERNET_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530131
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530132 ancestorMap = ipmi::getAllAncestors(
Patrick Venture0b02be92018-08-31 11:55:55 -0700133 bus, ipObject.first, std::move(interfaces));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530134 }
135 catch (InternalFailure& e)
136 {
137 // if unable to get the parent interface
138 // then commit the error and return.
Patrick Venture0b02be92018-08-31 11:55:55 -0700139 log<level::ERR>(
140 "Unable to get the parent interface",
141 entry("PATH=%s", ipObject.first.c_str()),
142 entry("INTERFACE=%s",
143 ipmi::network::ETHERNET_INTERFACE));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530144 break;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530145 }
146 // for an ip object there would be single parent
147 // interface.
148 networkInterfacePath = ancestorMap.begin()->first;
149 }
150 catch (InternalFailure& e)
151 {
152 // if there is no ip configured on the system,then
153 // get the network interface object.
154 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700155 bus, ipmi::network::ETHERNET_INTERFACE,
156 ipmi::network::ROOT, ethdevice);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530157
158 networkInterfacePath = networkInterfaceObject.first;
159 }
160
161 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700162 bus, ipmi::network::SERVICE, networkInterfacePath,
163 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530164
William A. Kennington III4c008022018-10-12 17:18:14 -0700165 auto dhcpEnabled = variant_ns::get<bool>(variant);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530166 // As per IPMI spec 2=>DHCP, 1=STATIC
Patrick Venture0b02be92018-08-31 11:55:55 -0700167 auto ipsrc = dhcpEnabled ? ipmi::network::IPOrigin::DHCP
168 : ipmi::network::IPOrigin::STATIC;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530169
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700170 std::memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530171 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800172 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530173 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700174 std::memcpy(data, &(channelConf->ipsrc),
175 ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530176 }
177 }
178 break;
179
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800180 case LanParam::SUBNET:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530181 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700182 unsigned long mask{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800183 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530184 {
185 try
186 {
Johnathan Mantey88416832019-01-30 15:51:04 -0800187 auto ipObjectInfo =
188 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
189 ipmi::network::ROOT, ethIP);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530190
191 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700192 bus, ipObjectInfo.second, ipObjectInfo.first,
193 ipmi::network::IP_INTERFACE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530194
William A. Kennington III4c008022018-10-12 17:18:14 -0700195 auto prefix = variant_ns::get<uint8_t>(
196 properties["PrefixLength"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530197 mask = ipmi::network::MASK_32_BIT;
198 mask = htonl(mask << (ipmi::network::BITS_32 - prefix));
199 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500200 // ignore the exception, as it is a valid condition that
201 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530202 catch (InternalFailure& e)
203 {
204 // nothing to do
205 }
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700206 std::memcpy(data, &mask,
207 ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530208 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800209 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530210 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800211 inet_pton(AF_INET, channelConf->netmask.c_str(),
Ratan Guptab8e99552017-07-27 07:07:48 +0530212 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530213 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530214 }
215 break;
216
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800217 case LanParam::GATEWAY:
Ratan Guptab8e99552017-07-27 07:07:48 +0530218 {
219 std::string gateway;
220
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800221 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530222 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530223 try
224 {
225 auto systemObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700226 bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
227 ipmi::network::ROOT);
Ratan Guptab8e99552017-07-27 07:07:48 +0530228
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530229 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700230 bus, systemObject.second, systemObject.first,
231 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530232
William A. Kennington III4c008022018-10-12 17:18:14 -0700233 gateway = variant_ns::get<std::string>(
234 systemProperties["DefaultGateway"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530235 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500236 // ignore the exception, as it is a valid condition that
237 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530238 catch (InternalFailure& e)
239 {
240 // nothing to do
241 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530242 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800243 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530244 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800245 gateway = channelConf->gateway;
Ratan Guptab8e99552017-07-27 07:07:48 +0530246 }
247
248 inet_pton(AF_INET, gateway.c_str(),
249 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530250 }
251 break;
252
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800253 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530254 {
255 std::string macAddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800256 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530257 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700258 auto macObjectInfo =
259 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
260 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530261
262 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700263 bus, macObjectInfo.second, macObjectInfo.first,
264 ipmi::network::MAC_INTERFACE, "MACAddress");
Ratan Guptab8e99552017-07-27 07:07:48 +0530265
William A. Kennington III4c008022018-10-12 17:18:14 -0700266 macAddress = variant_ns::get<std::string>(variant);
Ratan Guptab8e99552017-07-27 07:07:48 +0530267 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800268 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530269 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800270 macAddress = channelConf->macAddress;
Ratan Guptab8e99552017-07-27 07:07:48 +0530271 }
272
273 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700274 (data), (data + 1), (data + 2), (data + 3), (data + 4),
Ratan Guptab8e99552017-07-27 07:07:48 +0530275 (data + 5));
276 }
277 break;
278
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800279 case LanParam::VLAN:
Ratan Gupta533d03b2017-07-30 10:39:22 +0530280 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700281 uint16_t vlanID{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800282 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530283 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530284 try
Ratan Gupta533d03b2017-07-30 10:39:22 +0530285 {
Ratan Guptadd646202017-11-21 17:46:59 +0530286 auto ipObjectInfo = ipmi::getIPObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700287 bus, ipmi::network::IP_INTERFACE,
288 ipmi::network::ROOT, ipmi::network::IP_TYPE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530289
290 vlanID = static_cast<uint16_t>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700291 ipmi::network::getVLAN(ipObjectInfo.first));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530292
293 vlanID = htole16(vlanID);
294
295 if (vlanID)
296 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700297 // Enable the 16th bit
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530298 vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK);
299 }
300 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500301 // ignore the exception, as it is a valid condition that
302 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530303 catch (InternalFailure& e)
304 {
305 // nothing to do
Ratan Gupta533d03b2017-07-30 10:39:22 +0530306 }
307
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700308 std::memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530309 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800310 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530311 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700312 std::memcpy(data, &(channelConf->vlanID),
313 ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530314 }
315 }
316 break;
317
Ratan Guptab8e99552017-07-27 07:07:48 +0530318 default:
319 rc = IPMI_CC_PARM_OUT_OF_RANGE;
tomjose26e17732016-03-03 08:52:51 -0600320 }
321 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530322 catch (InternalFailure& e)
tomjose26e17732016-03-03 08:52:51 -0600323 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530324 commit<InternalFailure>();
325 rc = IPMI_CC_UNSPECIFIED_ERROR;
326 return rc;
tomjose26e17732016-03-03 08:52:51 -0600327 }
tomjose26e17732016-03-03 08:52:51 -0600328 return rc;
329}
330
Tom Josepha30c8d32018-03-22 02:15:03 +0530331namespace cipher
332{
333
334std::vector<uint8_t> getCipherList()
335{
336 std::vector<uint8_t> cipherList;
337
338 std::ifstream jsonFile(configFile);
339 if (!jsonFile.is_open())
340 {
341 log<level::ERR>("Channel Cipher suites file not found");
342 elog<InternalFailure>();
343 }
344
345 auto data = Json::parse(jsonFile, nullptr, false);
346 if (data.is_discarded())
347 {
348 log<level::ERR>("Parsing channel cipher suites JSON failed");
349 elog<InternalFailure>();
350 }
351
352 // Byte 1 is reserved
353 cipherList.push_back(0x00);
354
355 for (const auto& record : data)
356 {
357 cipherList.push_back(record.value(cipher, 0));
358 }
359
360 return cipherList;
361}
362
Patrick Venture0b02be92018-08-31 11:55:55 -0700363} // namespace cipher
Tom Josepha30c8d32018-03-22 02:15:03 +0530364
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500365ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700366 ipmi_request_t request,
367 ipmi_response_t response,
368 ipmi_data_len_t data_len,
369 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500370{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500371 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800372 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500373 *data_len = 0;
374 return rc;
375}
376
Ratan Guptab8e99552017-07-27 07:07:48 +0530377struct set_lan_t
378{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500379 uint8_t channel;
380 uint8_t parameter;
381 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
Patrick Venture0b02be92018-08-31 11:55:55 -0700382} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500383
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530384ipmi_ret_t checkAndUpdateNetwork(int channel)
385{
386 auto channelConf = getChannelConfig(channel);
387 using namespace std::chrono_literals;
388 // time to wait before applying the network changes.
389 constexpr auto networkTimeout = 10000000us; // 10 sec
390
391 // Skip the timer. Expecting more update as we are in SET_IN_PROGRESS
392 if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
393 {
394 return IPMI_CC_OK;
395 }
396
397 // Start the timer, if it is direct single param update without
398 // SET_IN_PROGRESS or many params updated through SET_IN_PROGRESS to
399 // SET_COMPLETE Note: Even for update with SET_IN_PROGRESS, don't apply the
400 // changes immediately, as ipmitool sends each param individually
401 // through SET_IN_PROGRESS to SET_COMPLETE.
402 channelConf->flush = true;
403 if (!networkTimer)
404 {
405 log<level::ERR>("Network timer is not instantiated");
406 return IPMI_CC_UNSPECIFIED_ERROR;
407 }
408 // start the timer.
409 networkTimer->start(networkTimeout);
410 return IPMI_CC_OK;
411}
412
Patrick Venture0b02be92018-08-31 11:55:55 -0700413ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530414 ipmi_request_t request,
415 ipmi_response_t response,
416 ipmi_data_len_t data_len,
417 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500418{
419 ipmi_ret_t rc = IPMI_CC_OK;
420 *data_len = 0;
Nan Li3d0df912016-10-18 19:51:41 +0800421
Ratan Guptab8e99552017-07-27 07:07:48 +0530422 char ipaddr[INET_ADDRSTRLEN];
423 char netmask[INET_ADDRSTRLEN];
424 char gateway[INET_ADDRSTRLEN];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500425
Ratan Guptab8e99552017-07-27 07:07:48 +0530426 auto reqptr = reinterpret_cast<const set_lan_t*>(request);
427 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500428
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800429 // channel number is the lower nibble
430 int channel = reqptr->channel & CHANNEL_MASK;
Johnathan Mantey74a21022018-12-13 13:17:56 -0800431 auto ethdevice = ipmi::getChannelName(channel);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800432 if (ethdevice.empty())
433 {
434 return IPMI_CC_INVALID_FIELD_REQUEST;
435 }
436 auto channelConf = getChannelConfig(channel);
437
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800438 switch (static_cast<LanParam>(reqptr->parameter))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500439 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800440 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600441 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700442 std::snprintf(ipaddr, INET_ADDRSTRLEN,
443 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
444 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500445
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800446 channelConf->ipaddr.assign(ipaddr);
Ratan Guptab8e99552017-07-27 07:07:48 +0530447 }
448 break;
449
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800450 case LanParam::IPSRC:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530451 {
452 uint8_t ipsrc{};
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700453 std::memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800454 channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530455 }
456 break;
457
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800458 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530459 {
460 char mac[SIZE_MAC];
461
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700462 std::snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
463 reqptr->data[0], reqptr->data[1], reqptr->data[2],
464 reqptr->data[3], reqptr->data[4], reqptr->data[5]);
Ratan Guptab8e99552017-07-27 07:07:48 +0530465
Patrick Venture0b02be92018-08-31 11:55:55 -0700466 auto macObjectInfo =
467 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
468 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530469
Patrick Venture0b02be92018-08-31 11:55:55 -0700470 ipmi::setDbusProperty(
471 bus, macObjectInfo.second, macObjectInfo.first,
472 ipmi::network::MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptab8e99552017-07-27 07:07:48 +0530473
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800474 channelConf->macAddress = mac;
Ratan Guptab8e99552017-07-27 07:07:48 +0530475 }
476 break;
477
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800478 case LanParam::SUBNET:
Ratan Guptab8e99552017-07-27 07:07:48 +0530479 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700480 std::snprintf(netmask, INET_ADDRSTRLEN,
481 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
482 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800483 channelConf->netmask.assign(netmask);
Ratan Guptab8e99552017-07-27 07:07:48 +0530484 }
485 break;
486
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800487 case LanParam::GATEWAY:
Ratan Guptab8e99552017-07-27 07:07:48 +0530488 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700489 std::snprintf(gateway, INET_ADDRSTRLEN,
490 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
491 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800492 channelConf->gateway.assign(gateway);
Ratan Guptab8e99552017-07-27 07:07:48 +0530493 }
494 break;
495
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800496 case LanParam::VLAN:
Ratan Gupta533d03b2017-07-30 10:39:22 +0530497 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700498 uint16_t vlan{};
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700499 std::memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530500 // We are not storing the enable bit
501 // We assume that ipmitool always send enable
502 // bit as 1.
503 vlan = le16toh(vlan);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800504 channelConf->vlanID = vlan;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530505 }
506 break;
507
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800508 case LanParam::INPROGRESS:
Ratan Guptab8e99552017-07-27 07:07:48 +0530509 {
510 if (reqptr->data[0] == SET_COMPLETE)
511 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800512 channelConf->lan_set_in_progress = SET_COMPLETE;
Ratan Guptab8e99552017-07-27 07:07:48 +0530513
Patrick Venture0b02be92018-08-31 11:55:55 -0700514 log<level::INFO>(
515 "Network data from Cache",
516 entry("PREFIX=%s", channelConf->netmask.c_str()),
517 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
518 entry("GATEWAY=%s", channelConf->gateway.c_str()),
519 entry("VLAN=%d", channelConf->vlanID));
Ratan Guptab8e99552017-07-27 07:07:48 +0530520 }
521 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
522 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800523 channelConf->lan_set_in_progress = SET_IN_PROGRESS;
Ratan Guptab8e99552017-07-27 07:07:48 +0530524 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530525 }
526 break;
527
528 default:
529 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530530 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530531 return rc;
Ratan Guptab8e99552017-07-27 07:07:48 +0530532 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530533 }
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530534 rc = checkAndUpdateNetwork(channel);
vishwa1eaea4f2016-02-26 11:57:40 -0600535
tomjose26e17732016-03-03 08:52:51 -0600536 return rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500537}
538
Ratan Guptab8e99552017-07-27 07:07:48 +0530539struct get_lan_t
540{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500541 uint8_t rev_channel;
542 uint8_t parameter;
543 uint8_t parameter_set;
544 uint8_t parameter_block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700545} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500546
Patrick Venture0b02be92018-08-31 11:55:55 -0700547ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530548 ipmi_request_t request,
549 ipmi_response_t response,
550 ipmi_data_len_t data_len,
551 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500552{
553 ipmi_ret_t rc = IPMI_CC_OK;
554 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500555 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500556
Patrick Venture0b02be92018-08-31 11:55:55 -0700557 get_lan_t* reqptr = (get_lan_t*)request;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800558 // channel number is the lower nibble
559 int channel = reqptr->rev_channel & CHANNEL_MASK;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500560
561 if (reqptr->rev_channel & 0x80) // Revision is bit 7
562 {
563 // Only current revision was requested
564 *data_len = sizeof(current_revision);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700565 std::memcpy(response, &current_revision, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500566 return IPMI_CC_OK;
567 }
568
Tom Josepha30c8d32018-03-22 02:15:03 +0530569 static std::vector<uint8_t> cipherList;
570 static auto listInit = false;
571
572 if (!listInit)
573 {
574 try
575 {
576 cipherList = cipher::getCipherList();
577 listInit = true;
578 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700579 catch (const std::exception& e)
Tom Josepha30c8d32018-03-22 02:15:03 +0530580 {
581 return IPMI_CC_UNSPECIFIED_ERROR;
582 }
583 }
584
Johnathan Mantey74a21022018-12-13 13:17:56 -0800585 auto ethdevice = ipmi::getChannelName(channel);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800586 if (ethdevice.empty())
587 {
588 return IPMI_CC_INVALID_FIELD_REQUEST;
589 }
590 auto channelConf = getChannelConfig(channel);
591
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800592 LanParam param = static_cast<LanParam>(reqptr->parameter);
593 switch (param)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500594 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800595 case LanParam::INPROGRESS:
vishwa1eaea4f2016-02-26 11:57:40 -0600596 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800597 uint8_t buf[] = {current_revision,
598 channelConf->lan_set_in_progress};
599 *data_len = sizeof(buf);
600 std::memcpy(response, &buf, *data_len);
601 break;
602 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800603 case LanParam::AUTHSUPPORT:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800604 {
605 uint8_t buf[] = {current_revision, 0x04};
606 *data_len = sizeof(buf);
607 std::memcpy(response, &buf, *data_len);
608 break;
609 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800610 case LanParam::AUTHENABLES:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800611 {
612 uint8_t buf[] = {current_revision, 0x04, 0x04, 0x04, 0x04, 0x04};
613 *data_len = sizeof(buf);
614 std::memcpy(response, &buf, *data_len);
615 break;
616 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800617 case LanParam::IP:
618 case LanParam::SUBNET:
619 case LanParam::GATEWAY:
620 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800621 {
622 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1] = {};
623
624 *data_len = sizeof(current_revision);
625 std::memcpy(buf, &current_revision, *data_len);
626
627 if (getNetworkData(reqptr->parameter, &buf[1], channel) ==
628 IPMI_CC_OK)
Ratan Guptab8e99552017-07-27 07:07:48 +0530629 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800630 if (param == LanParam::MAC)
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800631 {
632 *data_len = sizeof(buf);
633 }
634 else
635 {
636 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1;
637 }
638 std::memcpy(response, &buf, *data_len);
Ratan Guptab8e99552017-07-27 07:07:48 +0530639 }
640 else
641 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800642 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptab8e99552017-07-27 07:07:48 +0530643 }
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800644 break;
Adriana Kobylak342df102016-02-10 13:48:16 -0600645 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800646 case LanParam::VLAN:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600647 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800648 uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530649
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800650 *data_len = sizeof(current_revision);
651 std::memcpy(buf, &current_revision, *data_len);
652 if (getNetworkData(reqptr->parameter, &buf[1], channel) ==
653 IPMI_CC_OK)
654 {
655 *data_len = sizeof(buf);
656 std::memcpy(response, &buf, *data_len);
657 }
658 break;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530659 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800660 case LanParam::IPSRC:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530661 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800662 uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {};
663 *data_len = sizeof(current_revision);
664 std::memcpy(buff, &current_revision, *data_len);
665 if (getNetworkData(reqptr->parameter, &buff[1], channel) ==
666 IPMI_CC_OK)
667 {
668 *data_len = sizeof(buff);
669 std::memcpy(response, &buff, *data_len);
670 }
671 break;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530672 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800673 case LanParam::CIPHER_SUITE_COUNT:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800674 {
675 *(static_cast<uint8_t*>(response)) = current_revision;
676 // Byte 1 is reserved byte and does not indicate a cipher suite ID,
677 // so no of cipher suite entry count is one less than the size of
678 // the vector
679 auto count = static_cast<uint8_t>(cipherList.size() - 1);
680 *(static_cast<uint8_t*>(response) + 1) = count;
681 *data_len = sizeof(current_revision) + sizeof(count);
682 break;
683 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800684 case LanParam::CIPHER_SUITE_ENTRIES:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800685 {
686 *(static_cast<uint8_t*>(response)) = current_revision;
687 // Byte 1 is reserved
688 std::copy_n(cipherList.data(), cipherList.size(),
689 static_cast<uint8_t*>(response) + 1);
690 *data_len = sizeof(current_revision) +
691 static_cast<uint8_t>(cipherList.size());
692 break;
693 }
694 default:
695 log<level::ERR>("Unsupported parameter",
696 entry("PARAMETER=0x%x", reqptr->parameter));
697 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500698 }
699
700 return rc;
701}
702
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530703void applyChanges(int channel)
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530704{
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530705 std::string ipaddress;
706 std::string gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700707 uint8_t prefix{};
708 uint32_t vlanID{};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530709 std::string networkInterfacePath;
710 ipmi::DbusObjectInfo ipObject;
711 ipmi::DbusObjectInfo systemObject;
712
Johnathan Mantey74a21022018-12-13 13:17:56 -0800713 auto ethdevice = ipmi::getChannelName(channel);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530714 if (ethdevice.empty())
715 {
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530716 log<level::ERR>("Unable to get the interface name",
717 entry("CHANNEL=%d", channel));
718 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530719 }
720 auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE;
721 auto channelConf = getChannelConfig(channel);
722
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530723 try
724 {
725 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
726
727 log<level::INFO>("Network data from Cache",
728 entry("PREFIX=%s", channelConf->netmask.c_str()),
729 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
730 entry("GATEWAY=%s", channelConf->gateway.c_str()),
731 entry("VLAN=%d", channelConf->vlanID),
732 entry("IPSRC=%d", channelConf->ipsrc));
733 if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK)
734 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700735 // get the first twelve bits which is vlan id
736 // not interested in rest of the bits.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530737 channelConf->vlanID = le32toh(channelConf->vlanID);
738 vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK;
739 }
740
741 // if the asked ip src is DHCP then not interested in
742 // any given data except vlan.
743 if (channelConf->ipsrc != ipmi::network::IPOrigin::DHCP)
744 {
745 // always get the system object
Patrick Venture0b02be92018-08-31 11:55:55 -0700746 systemObject =
747 ipmi::getDbusObject(bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
748 ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530749
750 // the below code is to determine the mode of the interface
751 // as the handling is same, if the system is configured with
752 // DHCP or user has given all the data.
753 try
754 {
755 ipmi::ObjectTree ancestorMap;
756
Patrick Venture0b02be92018-08-31 11:55:55 -0700757 ipmi::InterfaceList interfaces{
758 ipmi::network::ETHERNET_INTERFACE};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530759
760 // if the system is having ip object,then
761 // get the IP object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700762 ipObject = ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
763 ipmi::network::ROOT, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530764
765 // Get the parent interface of the IP object.
766 try
767 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700768 ancestorMap = ipmi::getAllAncestors(bus, ipObject.first,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530769 std::move(interfaces));
770 }
771 catch (InternalFailure& e)
772 {
773 // if unable to get the parent interface
774 // then commit the error and return.
775 log<level::ERR>("Unable to get the parent interface",
776 entry("PATH=%s", ipObject.first.c_str()),
777 entry("INTERFACE=%s",
778 ipmi::network::ETHERNET_INTERFACE));
779 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530780 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530781 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530782 }
783
784 networkInterfacePath = ancestorMap.begin()->first;
785 }
786 catch (InternalFailure& e)
787 {
788 // TODO Currently IPMI supports single interface,need to handle
789 // Multiple interface through
790 // https://github.com/openbmc/openbmc/issues/2138
791
792 // if there is no ip configured on the system,then
793 // get the network interface object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700794 auto networkInterfaceObject =
795 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
796 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530797
798 networkInterfacePath = std::move(networkInterfaceObject.first);
799 }
800
801 // get the configured mode on the system.
William A. Kennington III4c008022018-10-12 17:18:14 -0700802 auto enableDHCP = variant_ns::get<bool>(ipmi::getDbusProperty(
803 bus, ipmi::network::SERVICE, networkInterfacePath,
804 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled"));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530805
806 // if ip address source is not given then get the ip source mode
807 // from the system so that it can be applied later.
808 if (channelConf->ipsrc == ipmi::network::IPOrigin::UNSPECIFIED)
809 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700810 channelConf->ipsrc = (enableDHCP)
811 ? ipmi::network::IPOrigin::DHCP
812 : ipmi::network::IPOrigin::STATIC;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530813 }
814
815 // check whether user has given all the data
816 // or the configured system interface is dhcp enabled,
817 // in both of the cases get the values from the cache.
818 if ((!channelConf->ipaddr.empty() &&
819 !channelConf->netmask.empty() &&
820 !channelConf->gateway.empty()) ||
821 (enableDHCP)) // configured system interface mode = DHCP
822 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700823 // convert mask into prefix
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530824 ipaddress = channelConf->ipaddr;
825 prefix = ipmi::network::toPrefix(AF_INET, channelConf->netmask);
826 gateway = channelConf->gateway;
827 }
828 else // asked ip src = static and configured system src = static
Patrick Venture0b02be92018-08-31 11:55:55 -0700829 // or partially given data.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530830 {
831 // We have partial filled cache so get the remaining
832 // info from the system.
833
834 // Get the network data from the system as user has
835 // not given all the data then use the data fetched from the
836 // system but it is implementation dependent,IPMI spec doesn't
837 // force it.
838
839 // if system is not having any ip object don't throw error,
840 try
841 {
842 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700843 bus, ipObject.second, ipObject.first,
844 ipmi::network::IP_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530845
Patrick Venture0b02be92018-08-31 11:55:55 -0700846 ipaddress = channelConf->ipaddr.empty()
William A. Kennington III4c008022018-10-12 17:18:14 -0700847 ? variant_ns::get<std::string>(
848 properties["Address"])
Patrick Venture0b02be92018-08-31 11:55:55 -0700849 : channelConf->ipaddr;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530850
Patrick Venture0b02be92018-08-31 11:55:55 -0700851 prefix = channelConf->netmask.empty()
William A. Kennington III4c008022018-10-12 17:18:14 -0700852 ? variant_ns::get<uint8_t>(
853 properties["PrefixLength"])
Patrick Venture0b02be92018-08-31 11:55:55 -0700854 : ipmi::network::toPrefix(
855 AF_INET, channelConf->netmask);
856 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530857 catch (InternalFailure& e)
858 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700859 log<level::INFO>(
860 "Failed to get IP object which matches",
861 entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
862 entry("MATCH=%s", ethIp.c_str()));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530863 }
864
865 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700866 bus, systemObject.second, systemObject.first,
867 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530868
William A. Kennington III4c008022018-10-12 17:18:14 -0700869 gateway = channelConf->gateway.empty()
870 ? variant_ns::get<std::string>(
871 systemProperties["DefaultGateway"])
872 : channelConf->gateway;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530873 }
874 }
875
876 // Currently network manager doesn't support purging of all the
877 // ip addresses and the vlan interfaces from the parent interface,
878 // TODO once the support is there, will make the change here.
879 // https://github.com/openbmc/openbmc/issues/2141.
880
881 // TODO Currently IPMI supports single interface,need to handle
882 // Multiple interface through
883 // https://github.com/openbmc/openbmc/issues/2138
884
885 // instead of deleting all the vlan interfaces and
886 // all the ipv4 address,we will call reset method.
Patrick Venture0b02be92018-08-31 11:55:55 -0700887 // delete all the vlan interfaces
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530888
Patrick Venture0b02be92018-08-31 11:55:55 -0700889 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530890 ipmi::network::VLAN_INTERFACE);
891
892 // set the interface mode to static
Patrick Venture0b02be92018-08-31 11:55:55 -0700893 auto networkInterfaceObject =
894 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
895 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530896
897 // setting the physical interface mode to static.
Patrick Venture0b02be92018-08-31 11:55:55 -0700898 ipmi::setDbusProperty(
899 bus, ipmi::network::SERVICE, networkInterfaceObject.first,
900 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530901
902 networkInterfacePath = networkInterfaceObject.first;
903
Patrick Venture0b02be92018-08-31 11:55:55 -0700904 // delete all the ipv4 addresses
905 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
906 ipmi::network::IP_INTERFACE, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530907
908 if (vlanID)
909 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700910 ipmi::network::createVLAN(bus, ipmi::network::SERVICE,
911 ipmi::network::ROOT, ethdevice, vlanID);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530912
913 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700914 bus, ipmi::network::VLAN_INTERFACE, ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530915
Patrick Venture0b02be92018-08-31 11:55:55 -0700916 networkInterfacePath = networkInterfaceObject.first;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530917 }
918
919 if (channelConf->ipsrc == ipmi::network::IPOrigin::DHCP)
920 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700921 ipmi::setDbusProperty(
922 bus, ipmi::network::SERVICE, networkInterfacePath,
923 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", true);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530924 }
925 else
926 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700927 // change the mode to static
928 ipmi::setDbusProperty(
929 bus, ipmi::network::SERVICE, networkInterfacePath,
930 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530931
932 if (!ipaddress.empty())
933 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700934 ipmi::network::createIP(bus, ipmi::network::SERVICE,
935 networkInterfacePath, ipv4Protocol,
936 ipaddress, prefix);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530937 }
938
939 if (!gateway.empty())
940 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700941 ipmi::setDbusProperty(bus, systemObject.second,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530942 systemObject.first,
943 ipmi::network::SYSTEMCONFIG_INTERFACE,
Patrick Venture0b02be92018-08-31 11:55:55 -0700944 "DefaultGateway", std::string(gateway));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530945 }
946 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530947 }
Vernon Mauery7a614182018-11-27 12:54:52 -0800948 catch (sdbusplus::exception::exception& e)
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530949 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700950 log<level::ERR>(
951 "Failed to set network data", entry("PREFIX=%d", prefix),
952 entry("ADDRESS=%s", ipaddress.c_str()),
953 entry("GATEWAY=%s", gateway.c_str()), entry("VLANID=%d", vlanID),
954 entry("IPSRC=%d", channelConf->ipsrc));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530955
956 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530957 }
958
959 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530960}
961
962void commitNetworkChanges()
963{
Patrick Venture0b02be92018-08-31 11:55:55 -0700964 for (const auto& channel : channelConfig)
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530965 {
966 if (channel.second->flush)
967 {
968 applyChanges(channel.first);
969 }
970 }
971}
972
973void createNetworkTimer()
974{
975 if (!networkTimer)
976 {
977 std::function<void()> networkTimerCallback(
Patrick Venture0b02be92018-08-31 11:55:55 -0700978 std::bind(&commitNetworkChanges));
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530979
Vernon Mauery1181af72018-10-08 12:05:00 -0700980 networkTimer = std::make_unique<phosphor::Timer>(networkTimerCallback);
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530981 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530982}
983
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500984void register_netfn_transport_functions()
985{
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530986 // As this timer is only for transport handler
987 // so creating it here.
988 createNetworkTimer();
Tom05732372016-09-06 17:21:23 +0530989 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -0700990 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL,
991 ipmi_transport_wildcard, PRIVILEGE_USER);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500992
Tom05732372016-09-06 17:21:23 +0530993 // <Set LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700994 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL,
995 ipmi_transport_set_lan, PRIVILEGE_ADMIN);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500996
Tom05732372016-09-06 17:21:23 +0530997 // <Get LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700998 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL,
999 ipmi_transport_get_lan, PRIVILEGE_OPERATOR);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001000
1001 return;
1002}