blob: acff25166308a40cdbab470746be41870d68b791 [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;
Hariharasubramanian R83951912016-01-20 07:06:36 -060039
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050040void register_netfn_transport_functions() __attribute__((constructor));
41
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080042struct ChannelConfig_t* getChannelConfig(int channel)
43{
44 auto item = channelConfig.find(channel);
45 if (item == channelConfig.end())
46 {
47 channelConfig[channel] = std::make_unique<struct ChannelConfig_t>();
48 }
49
50 return channelConfig[channel].get();
51}
52
Patrick Venture0b02be92018-08-31 11:55:55 -070053// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network
54// Manager or Cache based on Set-In-Progress State
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080055ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel)
tomjose26e17732016-03-03 08:52:51 -060056{
tomjose26e17732016-03-03 08:52:51 -060057 ipmi_ret_t rc = IPMI_CC_OK;
Ratan Guptab8e99552017-07-27 07:07:48 +053058 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Gupta533d03b2017-07-30 10:39:22 +053059
Johnathan Mantey74a21022018-12-13 13:17:56 -080060 auto ethdevice = ipmi::getChannelName(channel);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080061 // if ethdevice is an empty string they weren't expecting this channel.
62 if (ethdevice.empty())
63 {
64 // TODO: return error from getNetworkData()
65 return IPMI_CC_INVALID_FIELD_REQUEST;
66 }
67 auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE;
68 auto channelConf = getChannelConfig(channel);
69
Ratan Guptab8e99552017-07-27 07:07:48 +053070 try
tomjose26e17732016-03-03 08:52:51 -060071 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -080072 switch (static_cast<LanParam>(lan_param))
tomjose26e17732016-03-03 08:52:51 -060073 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -080074 case LanParam::IP:
Ratan Guptab8e99552017-07-27 07:07:48 +053075 {
76 std::string ipaddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080077 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +053078 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053079 try
80 {
Patrick Venture0b02be92018-08-31 11:55:55 -070081 auto ipObjectInfo =
82 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
83 ipmi::network::ROOT, ethIP);
Ratan Guptadd646202017-11-21 17:46:59 +053084
85 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -070086 bus, ipObjectInfo.second, ipObjectInfo.first,
87 ipmi::network::IP_INTERFACE);
Ratan Guptadd646202017-11-21 17:46:59 +053088
William A. Kennington III4c008022018-10-12 17:18:14 -070089 ipaddress =
Vernon Maueryf442e112019-04-09 11:44:36 -070090 std::get<std::string>(properties["Address"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053091 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -050092 // ignore the exception, as it is a valid condition that
93 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053094 catch (InternalFailure& e)
95 {
96 // nothing to do.
97 }
Ratan Guptab8e99552017-07-27 07:07:48 +053098 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080099 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530100 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800101 ipaddress = channelConf->ipaddr;
Ratan Guptab8e99552017-07-27 07:07:48 +0530102 }
103
104 inet_pton(AF_INET, ipaddress.c_str(),
105 reinterpret_cast<void*>(data));
106 }
107 break;
108
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800109 case LanParam::IPSRC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530110 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530111 std::string networkInterfacePath;
112
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800113 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530114 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530115 try
116 {
117 ipmi::ObjectTree ancestorMap;
118 // if the system is having ip object,then
119 // get the IP object.
120 auto ipObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700121 bus, ipmi::network::IP_INTERFACE,
122 ipmi::network::ROOT, ethIP);
Ratan Guptab8e99552017-07-27 07:07:48 +0530123
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530124 // Get the parent interface of the IP object.
125 try
126 {
127 ipmi::InterfaceList interfaces;
128 interfaces.emplace_back(
Patrick Venture0b02be92018-08-31 11:55:55 -0700129 ipmi::network::ETHERNET_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530130
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530131 ancestorMap = ipmi::getAllAncestors(
Patrick Venture0b02be92018-08-31 11:55:55 -0700132 bus, ipObject.first, std::move(interfaces));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530133 }
134 catch (InternalFailure& e)
135 {
136 // if unable to get the parent interface
137 // then commit the error and return.
Patrick Venture0b02be92018-08-31 11:55:55 -0700138 log<level::ERR>(
139 "Unable to get the parent interface",
140 entry("PATH=%s", ipObject.first.c_str()),
141 entry("INTERFACE=%s",
142 ipmi::network::ETHERNET_INTERFACE));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530143 break;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530144 }
145 // for an ip object there would be single parent
146 // interface.
147 networkInterfacePath = ancestorMap.begin()->first;
148 }
149 catch (InternalFailure& e)
150 {
151 // if there is no ip configured on the system,then
152 // get the network interface object.
153 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700154 bus, ipmi::network::ETHERNET_INTERFACE,
155 ipmi::network::ROOT, ethdevice);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530156
157 networkInterfacePath = networkInterfaceObject.first;
158 }
159
160 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700161 bus, ipmi::network::SERVICE, networkInterfacePath,
162 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530163
Vernon Maueryf442e112019-04-09 11:44:36 -0700164 auto dhcpEnabled = std::get<bool>(variant);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530165 // As per IPMI spec 2=>DHCP, 1=STATIC
Patrick Venture0b02be92018-08-31 11:55:55 -0700166 auto ipsrc = dhcpEnabled ? ipmi::network::IPOrigin::DHCP
167 : ipmi::network::IPOrigin::STATIC;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530168
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700169 std::memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530170 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800171 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530172 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700173 std::memcpy(data, &(channelConf->ipsrc),
174 ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530175 }
176 }
177 break;
178
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800179 case LanParam::SUBNET:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530180 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700181 unsigned long mask{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800182 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530183 {
184 try
185 {
Johnathan Mantey88416832019-01-30 15:51:04 -0800186 auto ipObjectInfo =
187 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
188 ipmi::network::ROOT, ethIP);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530189
190 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700191 bus, ipObjectInfo.second, ipObjectInfo.first,
192 ipmi::network::IP_INTERFACE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530193
Vernon Maueryf442e112019-04-09 11:44:36 -0700194 auto prefix =
195 std::get<uint8_t>(properties["PrefixLength"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530196 mask = ipmi::network::MASK_32_BIT;
197 mask = htonl(mask << (ipmi::network::BITS_32 - prefix));
198 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500199 // ignore the exception, as it is a valid condition that
200 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530201 catch (InternalFailure& e)
202 {
203 // nothing to do
204 }
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700205 std::memcpy(data, &mask,
206 ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530207 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800208 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530209 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800210 inet_pton(AF_INET, channelConf->netmask.c_str(),
Ratan Guptab8e99552017-07-27 07:07:48 +0530211 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530212 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530213 }
214 break;
215
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800216 case LanParam::GATEWAY:
Ratan Guptab8e99552017-07-27 07:07:48 +0530217 {
218 std::string gateway;
219
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800220 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530221 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530222 try
223 {
224 auto systemObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700225 bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
226 ipmi::network::ROOT);
Ratan Guptab8e99552017-07-27 07:07:48 +0530227
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530228 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700229 bus, systemObject.second, systemObject.first,
230 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530231
Vernon Maueryf442e112019-04-09 11:44:36 -0700232 gateway = std::get<std::string>(
William A. Kennington III4c008022018-10-12 17:18:14 -0700233 systemProperties["DefaultGateway"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530234 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500235 // ignore the exception, as it is a valid condition that
236 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530237 catch (InternalFailure& e)
238 {
239 // nothing to do
240 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530241 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800242 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530243 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800244 gateway = channelConf->gateway;
Ratan Guptab8e99552017-07-27 07:07:48 +0530245 }
246
247 inet_pton(AF_INET, gateway.c_str(),
248 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530249 }
250 break;
251
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800252 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530253 {
254 std::string macAddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800255 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530256 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700257 auto macObjectInfo =
258 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
259 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530260
261 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700262 bus, macObjectInfo.second, macObjectInfo.first,
263 ipmi::network::MAC_INTERFACE, "MACAddress");
Ratan Guptab8e99552017-07-27 07:07:48 +0530264
Vernon Maueryf442e112019-04-09 11:44:36 -0700265 macAddress = std::get<std::string>(variant);
Ratan Guptab8e99552017-07-27 07:07:48 +0530266 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800267 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530268 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800269 macAddress = channelConf->macAddress;
Ratan Guptab8e99552017-07-27 07:07:48 +0530270 }
271
272 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700273 (data), (data + 1), (data + 2), (data + 3), (data + 4),
Ratan Guptab8e99552017-07-27 07:07:48 +0530274 (data + 5));
275 }
276 break;
277
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800278 case LanParam::VLAN:
Ratan Gupta533d03b2017-07-30 10:39:22 +0530279 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700280 uint16_t vlanID{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800281 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530282 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530283 try
Ratan Gupta533d03b2017-07-30 10:39:22 +0530284 {
Ratan Guptadd646202017-11-21 17:46:59 +0530285 auto ipObjectInfo = ipmi::getIPObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700286 bus, ipmi::network::IP_INTERFACE,
287 ipmi::network::ROOT, ipmi::network::IP_TYPE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530288
289 vlanID = static_cast<uint16_t>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700290 ipmi::network::getVLAN(ipObjectInfo.first));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530291
292 vlanID = htole16(vlanID);
293
294 if (vlanID)
295 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700296 // Enable the 16th bit
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530297 vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK);
298 }
299 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500300 // ignore the exception, as it is a valid condition that
301 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530302 catch (InternalFailure& e)
303 {
304 // nothing to do
Ratan Gupta533d03b2017-07-30 10:39:22 +0530305 }
306
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700307 std::memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530308 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800309 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530310 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700311 std::memcpy(data, &(channelConf->vlanID),
312 ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530313 }
314 }
315 break;
316
Ratan Guptab8e99552017-07-27 07:07:48 +0530317 default:
318 rc = IPMI_CC_PARM_OUT_OF_RANGE;
tomjose26e17732016-03-03 08:52:51 -0600319 }
320 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530321 catch (InternalFailure& e)
tomjose26e17732016-03-03 08:52:51 -0600322 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530323 commit<InternalFailure>();
324 rc = IPMI_CC_UNSPECIFIED_ERROR;
325 return rc;
tomjose26e17732016-03-03 08:52:51 -0600326 }
tomjose26e17732016-03-03 08:52:51 -0600327 return rc;
328}
329
Tom Josepha30c8d32018-03-22 02:15:03 +0530330namespace cipher
331{
332
333std::vector<uint8_t> getCipherList()
334{
335 std::vector<uint8_t> cipherList;
336
337 std::ifstream jsonFile(configFile);
338 if (!jsonFile.is_open())
339 {
340 log<level::ERR>("Channel Cipher suites file not found");
341 elog<InternalFailure>();
342 }
343
344 auto data = Json::parse(jsonFile, nullptr, false);
345 if (data.is_discarded())
346 {
347 log<level::ERR>("Parsing channel cipher suites JSON failed");
348 elog<InternalFailure>();
349 }
350
351 // Byte 1 is reserved
352 cipherList.push_back(0x00);
353
354 for (const auto& record : data)
355 {
356 cipherList.push_back(record.value(cipher, 0));
357 }
358
359 return cipherList;
360}
361
Patrick Venture0b02be92018-08-31 11:55:55 -0700362} // namespace cipher
Tom Josepha30c8d32018-03-22 02:15:03 +0530363
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500364ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700365 ipmi_request_t request,
366 ipmi_response_t response,
367 ipmi_data_len_t data_len,
368 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500369{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500370 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800371 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500372 *data_len = 0;
373 return rc;
374}
375
Ratan Guptab8e99552017-07-27 07:07:48 +0530376struct set_lan_t
377{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500378 uint8_t channel;
379 uint8_t parameter;
380 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
Patrick Venture0b02be92018-08-31 11:55:55 -0700381} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500382
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530383ipmi_ret_t checkAndUpdateNetwork(int channel)
384{
385 auto channelConf = getChannelConfig(channel);
386 using namespace std::chrono_literals;
387 // time to wait before applying the network changes.
388 constexpr auto networkTimeout = 10000000us; // 10 sec
389
390 // Skip the timer. Expecting more update as we are in SET_IN_PROGRESS
391 if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
392 {
393 return IPMI_CC_OK;
394 }
395
396 // Start the timer, if it is direct single param update without
397 // SET_IN_PROGRESS or many params updated through SET_IN_PROGRESS to
398 // SET_COMPLETE Note: Even for update with SET_IN_PROGRESS, don't apply the
399 // changes immediately, as ipmitool sends each param individually
400 // through SET_IN_PROGRESS to SET_COMPLETE.
401 channelConf->flush = true;
402 if (!networkTimer)
403 {
404 log<level::ERR>("Network timer is not instantiated");
405 return IPMI_CC_UNSPECIFIED_ERROR;
406 }
407 // start the timer.
408 networkTimer->start(networkTimeout);
409 return IPMI_CC_OK;
410}
411
Patrick Venture0b02be92018-08-31 11:55:55 -0700412ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530413 ipmi_request_t request,
414 ipmi_response_t response,
415 ipmi_data_len_t data_len,
416 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500417{
418 ipmi_ret_t rc = IPMI_CC_OK;
Nan Li3d0df912016-10-18 19:51:41 +0800419
Ratan Guptab8e99552017-07-27 07:07:48 +0530420 char ipaddr[INET_ADDRSTRLEN];
421 char netmask[INET_ADDRSTRLEN];
422 char gateway[INET_ADDRSTRLEN];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500423
Ratan Guptab8e99552017-07-27 07:07:48 +0530424 auto reqptr = reinterpret_cast<const set_lan_t*>(request);
425 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500426
Suryakanth Sekar0a327e12019-08-08 14:30:19 +0530427 size_t reqLen = *data_len;
428 *data_len = 0;
429
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800430 // channel number is the lower nibble
431 int channel = reqptr->channel & CHANNEL_MASK;
Johnathan Mantey74a21022018-12-13 13:17:56 -0800432 auto ethdevice = ipmi::getChannelName(channel);
Suryakanth Sekare4054402019-08-08 15:16:52 +0530433 ipmi::ChannelInfo chInfo;
434 ipmi::getChannelInfo(channel, chInfo);
435
436 if (ethdevice.empty() ||
437 chInfo.mediumType !=
438 static_cast<uint8_t>(ipmi::EChannelMediumType::lan8032))
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800439 {
440 return IPMI_CC_INVALID_FIELD_REQUEST;
441 }
442 auto channelConf = getChannelConfig(channel);
443
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800444 switch (static_cast<LanParam>(reqptr->parameter))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500445 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800446 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600447 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700448 std::snprintf(ipaddr, INET_ADDRSTRLEN,
449 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
450 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500451
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800452 channelConf->ipaddr.assign(ipaddr);
Ratan Guptab8e99552017-07-27 07:07:48 +0530453 }
454 break;
455
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800456 case LanParam::IPSRC:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530457 {
458 uint8_t ipsrc{};
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700459 std::memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800460 channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530461 }
462 break;
463
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800464 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530465 {
466 char mac[SIZE_MAC];
467
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700468 std::snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
469 reqptr->data[0], reqptr->data[1], reqptr->data[2],
470 reqptr->data[3], reqptr->data[4], reqptr->data[5]);
Ratan Guptab8e99552017-07-27 07:07:48 +0530471
Patrick Venture0b02be92018-08-31 11:55:55 -0700472 auto macObjectInfo =
473 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
474 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530475
Patrick Venture0b02be92018-08-31 11:55:55 -0700476 ipmi::setDbusProperty(
477 bus, macObjectInfo.second, macObjectInfo.first,
478 ipmi::network::MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptab8e99552017-07-27 07:07:48 +0530479
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800480 channelConf->macAddress = mac;
Ratan Guptab8e99552017-07-27 07:07:48 +0530481 }
482 break;
483
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800484 case LanParam::SUBNET:
Ratan Guptab8e99552017-07-27 07:07:48 +0530485 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700486 std::snprintf(netmask, INET_ADDRSTRLEN,
487 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
488 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800489 channelConf->netmask.assign(netmask);
Ratan Guptab8e99552017-07-27 07:07:48 +0530490 }
491 break;
492
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800493 case LanParam::GATEWAY:
Ratan Guptab8e99552017-07-27 07:07:48 +0530494 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700495 std::snprintf(gateway, INET_ADDRSTRLEN,
496 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
497 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800498 channelConf->gateway.assign(gateway);
Ratan Guptab8e99552017-07-27 07:07:48 +0530499 }
500 break;
501
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800502 case LanParam::VLAN:
Ratan Gupta533d03b2017-07-30 10:39:22 +0530503 {
Suryakanth Sekar0a327e12019-08-08 14:30:19 +0530504 if (reqLen != lanParamVLANSize)
505 {
506 return IPMI_CC_REQ_DATA_LEN_INVALID;
507 }
508
Patrick Venture0b02be92018-08-31 11:55:55 -0700509 uint16_t vlan{};
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700510 std::memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530511 // We are not storing the enable bit
512 // We assume that ipmitool always send enable
513 // bit as 1.
514 vlan = le16toh(vlan);
Suryakanth Sekar0a327e12019-08-08 14:30:19 +0530515 if (vlan == 0 || vlan > maxValidVLANIDValue)
516 {
517 return IPMI_CC_INVALID_FIELD_REQUEST;
518 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800519 channelConf->vlanID = vlan;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530520 }
521 break;
522
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800523 case LanParam::INPROGRESS:
Ratan Guptab8e99552017-07-27 07:07:48 +0530524 {
525 if (reqptr->data[0] == SET_COMPLETE)
526 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800527 channelConf->lan_set_in_progress = SET_COMPLETE;
Ratan Guptab8e99552017-07-27 07:07:48 +0530528
Patrick Venture0b02be92018-08-31 11:55:55 -0700529 log<level::INFO>(
530 "Network data from Cache",
531 entry("PREFIX=%s", channelConf->netmask.c_str()),
532 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
533 entry("GATEWAY=%s", channelConf->gateway.c_str()),
534 entry("VLAN=%d", channelConf->vlanID));
Ratan Guptab8e99552017-07-27 07:07:48 +0530535 }
536 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
537 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800538 channelConf->lan_set_in_progress = SET_IN_PROGRESS;
Ratan Guptab8e99552017-07-27 07:07:48 +0530539 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530540 }
541 break;
542
543 default:
544 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530545 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530546 return rc;
Ratan Guptab8e99552017-07-27 07:07:48 +0530547 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530548 }
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530549 rc = checkAndUpdateNetwork(channel);
vishwa1eaea4f2016-02-26 11:57:40 -0600550
tomjose26e17732016-03-03 08:52:51 -0600551 return rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500552}
553
Ratan Guptab8e99552017-07-27 07:07:48 +0530554struct get_lan_t
555{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500556 uint8_t rev_channel;
557 uint8_t parameter;
558 uint8_t parameter_set;
559 uint8_t parameter_block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700560} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500561
Patrick Venture0b02be92018-08-31 11:55:55 -0700562ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530563 ipmi_request_t request,
564 ipmi_response_t response,
565 ipmi_data_len_t data_len,
566 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500567{
568 ipmi_ret_t rc = IPMI_CC_OK;
569 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500570 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500571
Patrick Venture0b02be92018-08-31 11:55:55 -0700572 get_lan_t* reqptr = (get_lan_t*)request;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800573 // channel number is the lower nibble
574 int channel = reqptr->rev_channel & CHANNEL_MASK;
Suryakanth Sekare4054402019-08-08 15:16:52 +0530575 ipmi::ChannelInfo chInfo;
576 ipmi::getChannelInfo(channel, chInfo);
577 if (chInfo.mediumType !=
578 static_cast<uint8_t>(ipmi::EChannelMediumType::lan8032))
579 {
580 return IPMI_CC_INVALID_FIELD_REQUEST;
581 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500582
583 if (reqptr->rev_channel & 0x80) // Revision is bit 7
584 {
585 // Only current revision was requested
586 *data_len = sizeof(current_revision);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700587 std::memcpy(response, &current_revision, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500588 return IPMI_CC_OK;
589 }
590
Tom Josepha30c8d32018-03-22 02:15:03 +0530591 static std::vector<uint8_t> cipherList;
592 static auto listInit = false;
593
594 if (!listInit)
595 {
596 try
597 {
598 cipherList = cipher::getCipherList();
599 listInit = true;
600 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700601 catch (const std::exception& e)
Tom Josepha30c8d32018-03-22 02:15:03 +0530602 {
603 return IPMI_CC_UNSPECIFIED_ERROR;
604 }
605 }
606
Johnathan Mantey74a21022018-12-13 13:17:56 -0800607 auto ethdevice = ipmi::getChannelName(channel);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800608 if (ethdevice.empty())
609 {
610 return IPMI_CC_INVALID_FIELD_REQUEST;
611 }
612 auto channelConf = getChannelConfig(channel);
613
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800614 LanParam param = static_cast<LanParam>(reqptr->parameter);
615 switch (param)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500616 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800617 case LanParam::INPROGRESS:
vishwa1eaea4f2016-02-26 11:57:40 -0600618 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800619 uint8_t buf[] = {current_revision,
620 channelConf->lan_set_in_progress};
621 *data_len = sizeof(buf);
622 std::memcpy(response, &buf, *data_len);
623 break;
624 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800625 case LanParam::AUTHSUPPORT:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800626 {
627 uint8_t buf[] = {current_revision, 0x04};
628 *data_len = sizeof(buf);
629 std::memcpy(response, &buf, *data_len);
630 break;
631 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800632 case LanParam::AUTHENABLES:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800633 {
634 uint8_t buf[] = {current_revision, 0x04, 0x04, 0x04, 0x04, 0x04};
635 *data_len = sizeof(buf);
636 std::memcpy(response, &buf, *data_len);
637 break;
638 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800639 case LanParam::IP:
640 case LanParam::SUBNET:
641 case LanParam::GATEWAY:
642 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800643 {
644 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1] = {};
645
646 *data_len = sizeof(current_revision);
647 std::memcpy(buf, &current_revision, *data_len);
648
649 if (getNetworkData(reqptr->parameter, &buf[1], channel) ==
650 IPMI_CC_OK)
Ratan Guptab8e99552017-07-27 07:07:48 +0530651 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800652 if (param == LanParam::MAC)
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800653 {
654 *data_len = sizeof(buf);
655 }
656 else
657 {
658 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1;
659 }
660 std::memcpy(response, &buf, *data_len);
Ratan Guptab8e99552017-07-27 07:07:48 +0530661 }
662 else
663 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800664 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptab8e99552017-07-27 07:07:48 +0530665 }
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800666 break;
Adriana Kobylak342df102016-02-10 13:48:16 -0600667 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800668 case LanParam::VLAN:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600669 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800670 uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530671
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800672 *data_len = sizeof(current_revision);
673 std::memcpy(buf, &current_revision, *data_len);
674 if (getNetworkData(reqptr->parameter, &buf[1], channel) ==
675 IPMI_CC_OK)
676 {
677 *data_len = sizeof(buf);
678 std::memcpy(response, &buf, *data_len);
679 }
680 break;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530681 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800682 case LanParam::IPSRC:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530683 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800684 uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {};
685 *data_len = sizeof(current_revision);
686 std::memcpy(buff, &current_revision, *data_len);
687 if (getNetworkData(reqptr->parameter, &buff[1], channel) ==
688 IPMI_CC_OK)
689 {
690 *data_len = sizeof(buff);
691 std::memcpy(response, &buff, *data_len);
692 }
693 break;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530694 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800695 case LanParam::CIPHER_SUITE_COUNT:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800696 {
697 *(static_cast<uint8_t*>(response)) = current_revision;
698 // Byte 1 is reserved byte and does not indicate a cipher suite ID,
699 // so no of cipher suite entry count is one less than the size of
700 // the vector
701 auto count = static_cast<uint8_t>(cipherList.size() - 1);
702 *(static_cast<uint8_t*>(response) + 1) = count;
703 *data_len = sizeof(current_revision) + sizeof(count);
704 break;
705 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800706 case LanParam::CIPHER_SUITE_ENTRIES:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800707 {
708 *(static_cast<uint8_t*>(response)) = current_revision;
709 // Byte 1 is reserved
710 std::copy_n(cipherList.data(), cipherList.size(),
711 static_cast<uint8_t*>(response) + 1);
712 *data_len = sizeof(current_revision) +
713 static_cast<uint8_t>(cipherList.size());
714 break;
715 }
716 default:
717 log<level::ERR>("Unsupported parameter",
718 entry("PARAMETER=0x%x", reqptr->parameter));
719 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500720 }
721
722 return rc;
723}
724
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530725void applyChanges(int channel)
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530726{
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530727 std::string ipaddress;
728 std::string gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700729 uint8_t prefix{};
730 uint32_t vlanID{};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530731 std::string networkInterfacePath;
732 ipmi::DbusObjectInfo ipObject;
733 ipmi::DbusObjectInfo systemObject;
734
Johnathan Mantey74a21022018-12-13 13:17:56 -0800735 auto ethdevice = ipmi::getChannelName(channel);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530736 if (ethdevice.empty())
737 {
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530738 log<level::ERR>("Unable to get the interface name",
739 entry("CHANNEL=%d", channel));
740 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530741 }
742 auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE;
743 auto channelConf = getChannelConfig(channel);
744
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530745 try
746 {
747 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
748
749 log<level::INFO>("Network data from Cache",
750 entry("PREFIX=%s", channelConf->netmask.c_str()),
751 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
752 entry("GATEWAY=%s", channelConf->gateway.c_str()),
753 entry("VLAN=%d", channelConf->vlanID),
754 entry("IPSRC=%d", channelConf->ipsrc));
755 if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK)
756 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700757 // get the first twelve bits which is vlan id
758 // not interested in rest of the bits.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530759 channelConf->vlanID = le32toh(channelConf->vlanID);
760 vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK;
761 }
762
763 // if the asked ip src is DHCP then not interested in
764 // any given data except vlan.
765 if (channelConf->ipsrc != ipmi::network::IPOrigin::DHCP)
766 {
767 // always get the system object
Patrick Venture0b02be92018-08-31 11:55:55 -0700768 systemObject =
769 ipmi::getDbusObject(bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
770 ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530771
772 // the below code is to determine the mode of the interface
773 // as the handling is same, if the system is configured with
774 // DHCP or user has given all the data.
775 try
776 {
777 ipmi::ObjectTree ancestorMap;
778
Patrick Venture0b02be92018-08-31 11:55:55 -0700779 ipmi::InterfaceList interfaces{
780 ipmi::network::ETHERNET_INTERFACE};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530781
782 // if the system is having ip object,then
783 // get the IP object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700784 ipObject = ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
785 ipmi::network::ROOT, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530786
787 // Get the parent interface of the IP object.
788 try
789 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700790 ancestorMap = ipmi::getAllAncestors(bus, ipObject.first,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530791 std::move(interfaces));
792 }
793 catch (InternalFailure& e)
794 {
795 // if unable to get the parent interface
796 // then commit the error and return.
797 log<level::ERR>("Unable to get the parent interface",
798 entry("PATH=%s", ipObject.first.c_str()),
799 entry("INTERFACE=%s",
800 ipmi::network::ETHERNET_INTERFACE));
801 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530802 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530803 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530804 }
805
806 networkInterfacePath = ancestorMap.begin()->first;
807 }
808 catch (InternalFailure& e)
809 {
810 // TODO Currently IPMI supports single interface,need to handle
811 // Multiple interface through
812 // https://github.com/openbmc/openbmc/issues/2138
813
814 // if there is no ip configured on the system,then
815 // get the network interface object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700816 auto networkInterfaceObject =
817 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
818 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530819
820 networkInterfacePath = std::move(networkInterfaceObject.first);
821 }
822
823 // get the configured mode on the system.
Vernon Maueryf442e112019-04-09 11:44:36 -0700824 auto enableDHCP = std::get<bool>(ipmi::getDbusProperty(
William A. Kennington III4c008022018-10-12 17:18:14 -0700825 bus, ipmi::network::SERVICE, networkInterfacePath,
826 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled"));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530827
828 // if ip address source is not given then get the ip source mode
829 // from the system so that it can be applied later.
830 if (channelConf->ipsrc == ipmi::network::IPOrigin::UNSPECIFIED)
831 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700832 channelConf->ipsrc = (enableDHCP)
833 ? ipmi::network::IPOrigin::DHCP
834 : ipmi::network::IPOrigin::STATIC;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530835 }
836
837 // check whether user has given all the data
838 // or the configured system interface is dhcp enabled,
839 // in both of the cases get the values from the cache.
840 if ((!channelConf->ipaddr.empty() &&
841 !channelConf->netmask.empty() &&
842 !channelConf->gateway.empty()) ||
843 (enableDHCP)) // configured system interface mode = DHCP
844 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700845 // convert mask into prefix
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530846 ipaddress = channelConf->ipaddr;
847 prefix = ipmi::network::toPrefix(AF_INET, channelConf->netmask);
848 gateway = channelConf->gateway;
849 }
850 else // asked ip src = static and configured system src = static
Patrick Venture0b02be92018-08-31 11:55:55 -0700851 // or partially given data.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530852 {
853 // We have partial filled cache so get the remaining
854 // info from the system.
855
856 // Get the network data from the system as user has
857 // not given all the data then use the data fetched from the
858 // system but it is implementation dependent,IPMI spec doesn't
859 // force it.
860
861 // if system is not having any ip object don't throw error,
862 try
863 {
864 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700865 bus, ipObject.second, ipObject.first,
866 ipmi::network::IP_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530867
Vernon Maueryf442e112019-04-09 11:44:36 -0700868 ipaddress =
869 channelConf->ipaddr.empty()
870 ? std::get<std::string>(properties["Address"])
871 : channelConf->ipaddr;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530872
Patrick Venture0b02be92018-08-31 11:55:55 -0700873 prefix = channelConf->netmask.empty()
Vernon Maueryf442e112019-04-09 11:44:36 -0700874 ? std::get<uint8_t>(properties["PrefixLength"])
Patrick Venture0b02be92018-08-31 11:55:55 -0700875 : ipmi::network::toPrefix(
876 AF_INET, channelConf->netmask);
877 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530878 catch (InternalFailure& e)
879 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700880 log<level::INFO>(
881 "Failed to get IP object which matches",
882 entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
883 entry("MATCH=%s", ethIp.c_str()));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530884 }
885
886 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700887 bus, systemObject.second, systemObject.first,
888 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530889
William A. Kennington III4c008022018-10-12 17:18:14 -0700890 gateway = channelConf->gateway.empty()
Vernon Maueryf442e112019-04-09 11:44:36 -0700891 ? std::get<std::string>(
William A. Kennington III4c008022018-10-12 17:18:14 -0700892 systemProperties["DefaultGateway"])
893 : channelConf->gateway;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530894 }
895 }
896
897 // Currently network manager doesn't support purging of all the
898 // ip addresses and the vlan interfaces from the parent interface,
899 // TODO once the support is there, will make the change here.
900 // https://github.com/openbmc/openbmc/issues/2141.
901
902 // TODO Currently IPMI supports single interface,need to handle
903 // Multiple interface through
904 // https://github.com/openbmc/openbmc/issues/2138
905
906 // instead of deleting all the vlan interfaces and
907 // all the ipv4 address,we will call reset method.
Patrick Venture0b02be92018-08-31 11:55:55 -0700908 // delete all the vlan interfaces
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530909
Patrick Venture0b02be92018-08-31 11:55:55 -0700910 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530911 ipmi::network::VLAN_INTERFACE);
912
913 // set the interface mode to static
Patrick Venture0b02be92018-08-31 11:55:55 -0700914 auto networkInterfaceObject =
915 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
916 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530917
918 // setting the physical interface mode to static.
Patrick Venture0b02be92018-08-31 11:55:55 -0700919 ipmi::setDbusProperty(
920 bus, ipmi::network::SERVICE, networkInterfaceObject.first,
921 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530922
923 networkInterfacePath = networkInterfaceObject.first;
924
Patrick Venture0b02be92018-08-31 11:55:55 -0700925 // delete all the ipv4 addresses
926 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
927 ipmi::network::IP_INTERFACE, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530928
929 if (vlanID)
930 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700931 ipmi::network::createVLAN(bus, ipmi::network::SERVICE,
932 ipmi::network::ROOT, ethdevice, vlanID);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530933
934 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700935 bus, ipmi::network::VLAN_INTERFACE, ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530936
Patrick Venture0b02be92018-08-31 11:55:55 -0700937 networkInterfacePath = networkInterfaceObject.first;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530938 }
939
940 if (channelConf->ipsrc == ipmi::network::IPOrigin::DHCP)
941 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700942 ipmi::setDbusProperty(
943 bus, ipmi::network::SERVICE, networkInterfacePath,
944 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", true);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530945 }
946 else
947 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700948 // change the mode to static
949 ipmi::setDbusProperty(
950 bus, ipmi::network::SERVICE, networkInterfacePath,
951 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530952
953 if (!ipaddress.empty())
954 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700955 ipmi::network::createIP(bus, ipmi::network::SERVICE,
956 networkInterfacePath, ipv4Protocol,
957 ipaddress, prefix);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530958 }
959
960 if (!gateway.empty())
961 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700962 ipmi::setDbusProperty(bus, systemObject.second,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530963 systemObject.first,
964 ipmi::network::SYSTEMCONFIG_INTERFACE,
Patrick Venture0b02be92018-08-31 11:55:55 -0700965 "DefaultGateway", std::string(gateway));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530966 }
967 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530968 }
Vernon Mauery7a614182018-11-27 12:54:52 -0800969 catch (sdbusplus::exception::exception& e)
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530970 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700971 log<level::ERR>(
972 "Failed to set network data", entry("PREFIX=%d", prefix),
973 entry("ADDRESS=%s", ipaddress.c_str()),
974 entry("GATEWAY=%s", gateway.c_str()), entry("VLANID=%d", vlanID),
975 entry("IPSRC=%d", channelConf->ipsrc));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530976
977 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530978 }
979
980 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530981}
982
983void commitNetworkChanges()
984{
Patrick Venture0b02be92018-08-31 11:55:55 -0700985 for (const auto& channel : channelConfig)
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530986 {
987 if (channel.second->flush)
988 {
989 applyChanges(channel.first);
990 }
991 }
992}
993
994void createNetworkTimer()
995{
996 if (!networkTimer)
997 {
998 std::function<void()> networkTimerCallback(
Patrick Venture0b02be92018-08-31 11:55:55 -0700999 std::bind(&commitNetworkChanges));
Ratan Gupta7a7f0122018-03-07 12:31:05 +05301000
Vernon Mauery1181af72018-10-08 12:05:00 -07001001 networkTimer = std::make_unique<phosphor::Timer>(networkTimerCallback);
Ratan Gupta7a7f0122018-03-07 12:31:05 +05301002 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +05301003}
1004
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001005void register_netfn_transport_functions()
1006{
Ratan Gupta7a7f0122018-03-07 12:31:05 +05301007 // As this timer is only for transport handler
1008 // so creating it here.
1009 createNetworkTimer();
Tom05732372016-09-06 17:21:23 +05301010 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -07001011 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL,
1012 ipmi_transport_wildcard, PRIVILEGE_USER);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001013
Tom05732372016-09-06 17:21:23 +05301014 // <Set LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -07001015 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL,
1016 ipmi_transport_set_lan, PRIVILEGE_ADMIN);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001017
Tom05732372016-09-06 17:21:23 +05301018 // <Get LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -07001019 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL,
1020 ipmi_transport_get_lan, PRIVILEGE_OPERATOR);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001021
1022 return;
1023}