blob: 24fea470636600d1ca8f1049729dbbfabf5303fc [file] [log] [blame]
Patrick Venture586d35b2018-09-07 19:56:18 -07001#include "transporthandler.hpp"
2
Patrick Venture3a5071a2018-09-12 13:27:42 -07003#include "app/channel.hpp"
4#include "ipmid.hpp"
Johnathan Mantey74a21022018-12-13 13:17:56 -08005#include "user_channel/channel_layer.hpp"
Patrick Venture3a5071a2018-09-12 13:27:42 -07006#include "utils.hpp"
7
Patrick Venture0b02be92018-08-31 11:55:55 -07008#include <arpa/inet.h>
William A. Kennington III194375f2018-12-14 02:14:33 -08009#include <ipmid/api.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070010
11#include <chrono>
12#include <fstream>
Patrick Venture3a5071a2018-09-12 13:27:42 -070013#include <phosphor-logging/elog-errors.hpp>
14#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070015#include <sdbusplus/message/types.hpp>
Vernon Mauery1181af72018-10-08 12:05:00 -070016#include <sdbusplus/timer.hpp>
tomjose26e17732016-03-03 08:52:51 -060017#include <string>
Patrick Venture3a5071a2018-09-12 13:27:42 -070018#include <xyz/openbmc_project/Common/error.hpp>
19
20#define SYSTEMD_NETWORKD_DBUS 1
21
22#ifdef SYSTEMD_NETWORKD_DBUS
23#include <mapper.h>
24#include <systemd/sd-bus.h>
25#endif
Patrick Venture586d35b2018-09-07 19:56:18 -070026
Vernon Mauery185b9f82018-07-20 10:52:36 -070027#if __has_include(<filesystem>)
28#include <filesystem>
29#elif __has_include(<experimental/filesystem>)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053030#include <experimental/filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -070031namespace std
32{
33// splice experimental::filesystem into std
34namespace filesystem = std::experimental::filesystem;
35} // namespace std
Vernon Mauery185b9f82018-07-20 10:52:36 -070036#else
Patrick Venture0b02be92018-08-31 11:55:55 -070037#error filesystem not available
Vernon Mauery185b9f82018-07-20 10:52:36 -070038#endif
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050039
Vernon Mauery1b7f6f22019-03-13 13:11:25 -070040// timer for network changes
41std::unique_ptr<phosphor::Timer> networkTimer = nullptr;
Ratan Gupta1247e0b2018-03-07 10:47:25 +053042
Patrick Venture0b02be92018-08-31 11:55:55 -070043const int SIZE_MAC = 18; // xx:xx:xx:xx:xx:xx
Ratan Gupta1247e0b2018-03-07 10:47:25 +053044constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Adriana Kobylake08fbc62016-02-09 16:17:23 -060045
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080046std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
Hariharasubramanian R83951912016-01-20 07:06:36 -060047
Ratan Guptab8e99552017-07-27 07:07:48 +053048using namespace phosphor::logging;
49using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta7a7f0122018-03-07 12:31:05 +053050
Vernon Mauery185b9f82018-07-20 10:52:36 -070051namespace fs = std::filesystem;
William A. Kennington III4c008022018-10-12 17:18:14 -070052namespace variant_ns = sdbusplus::message::variant_ns;
Hariharasubramanian R83951912016-01-20 07:06:36 -060053
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050054void register_netfn_transport_functions() __attribute__((constructor));
55
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080056struct ChannelConfig_t* getChannelConfig(int channel)
57{
58 auto item = channelConfig.find(channel);
59 if (item == channelConfig.end())
60 {
61 channelConfig[channel] = std::make_unique<struct ChannelConfig_t>();
62 }
63
64 return channelConfig[channel].get();
65}
66
Patrick Venture0b02be92018-08-31 11:55:55 -070067// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network
68// Manager or Cache based on Set-In-Progress State
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080069ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel)
tomjose26e17732016-03-03 08:52:51 -060070{
tomjose26e17732016-03-03 08:52:51 -060071 ipmi_ret_t rc = IPMI_CC_OK;
Ratan Guptab8e99552017-07-27 07:07:48 +053072 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Gupta533d03b2017-07-30 10:39:22 +053073
Johnathan Mantey74a21022018-12-13 13:17:56 -080074 auto ethdevice = ipmi::getChannelName(channel);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080075 // if ethdevice is an empty string they weren't expecting this channel.
76 if (ethdevice.empty())
77 {
78 // TODO: return error from getNetworkData()
79 return IPMI_CC_INVALID_FIELD_REQUEST;
80 }
81 auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE;
82 auto channelConf = getChannelConfig(channel);
83
Ratan Guptab8e99552017-07-27 07:07:48 +053084 try
tomjose26e17732016-03-03 08:52:51 -060085 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -080086 switch (static_cast<LanParam>(lan_param))
tomjose26e17732016-03-03 08:52:51 -060087 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -080088 case LanParam::IP:
Ratan Guptab8e99552017-07-27 07:07:48 +053089 {
90 std::string ipaddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080091 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +053092 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053093 try
94 {
Patrick Venture0b02be92018-08-31 11:55:55 -070095 auto ipObjectInfo =
96 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
97 ipmi::network::ROOT, ethIP);
Ratan Guptadd646202017-11-21 17:46:59 +053098
99 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700100 bus, ipObjectInfo.second, ipObjectInfo.first,
101 ipmi::network::IP_INTERFACE);
Ratan Guptadd646202017-11-21 17:46:59 +0530102
William A. Kennington III4c008022018-10-12 17:18:14 -0700103 ipaddress =
104 variant_ns::get<std::string>(properties["Address"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530105 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500106 // ignore the exception, as it is a valid condition that
107 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530108 catch (InternalFailure& e)
109 {
110 // nothing to do.
111 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530112 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800113 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530114 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800115 ipaddress = channelConf->ipaddr;
Ratan Guptab8e99552017-07-27 07:07:48 +0530116 }
117
118 inet_pton(AF_INET, ipaddress.c_str(),
119 reinterpret_cast<void*>(data));
120 }
121 break;
122
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800123 case LanParam::IPSRC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530124 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530125 std::string networkInterfacePath;
126
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800127 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530128 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530129 try
130 {
131 ipmi::ObjectTree ancestorMap;
132 // if the system is having ip object,then
133 // get the IP object.
134 auto ipObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700135 bus, ipmi::network::IP_INTERFACE,
136 ipmi::network::ROOT, ethIP);
Ratan Guptab8e99552017-07-27 07:07:48 +0530137
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530138 // Get the parent interface of the IP object.
139 try
140 {
141 ipmi::InterfaceList interfaces;
142 interfaces.emplace_back(
Patrick Venture0b02be92018-08-31 11:55:55 -0700143 ipmi::network::ETHERNET_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530144
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530145 ancestorMap = ipmi::getAllAncestors(
Patrick Venture0b02be92018-08-31 11:55:55 -0700146 bus, ipObject.first, std::move(interfaces));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530147 }
148 catch (InternalFailure& e)
149 {
150 // if unable to get the parent interface
151 // then commit the error and return.
Patrick Venture0b02be92018-08-31 11:55:55 -0700152 log<level::ERR>(
153 "Unable to get the parent interface",
154 entry("PATH=%s", ipObject.first.c_str()),
155 entry("INTERFACE=%s",
156 ipmi::network::ETHERNET_INTERFACE));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530157 break;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530158 }
159 // for an ip object there would be single parent
160 // interface.
161 networkInterfacePath = ancestorMap.begin()->first;
162 }
163 catch (InternalFailure& e)
164 {
165 // if there is no ip configured on the system,then
166 // get the network interface object.
167 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700168 bus, ipmi::network::ETHERNET_INTERFACE,
169 ipmi::network::ROOT, ethdevice);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530170
171 networkInterfacePath = networkInterfaceObject.first;
172 }
173
174 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700175 bus, ipmi::network::SERVICE, networkInterfacePath,
176 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530177
William A. Kennington III4c008022018-10-12 17:18:14 -0700178 auto dhcpEnabled = variant_ns::get<bool>(variant);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530179 // As per IPMI spec 2=>DHCP, 1=STATIC
Patrick Venture0b02be92018-08-31 11:55:55 -0700180 auto ipsrc = dhcpEnabled ? ipmi::network::IPOrigin::DHCP
181 : ipmi::network::IPOrigin::STATIC;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530182
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700183 std::memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530184 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800185 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530186 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700187 std::memcpy(data, &(channelConf->ipsrc),
188 ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530189 }
190 }
191 break;
192
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800193 case LanParam::SUBNET:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530194 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700195 unsigned long mask{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800196 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530197 {
198 try
199 {
Johnathan Mantey88416832019-01-30 15:51:04 -0800200 auto ipObjectInfo =
201 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
202 ipmi::network::ROOT, ethIP);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530203
204 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700205 bus, ipObjectInfo.second, ipObjectInfo.first,
206 ipmi::network::IP_INTERFACE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530207
William A. Kennington III4c008022018-10-12 17:18:14 -0700208 auto prefix = variant_ns::get<uint8_t>(
209 properties["PrefixLength"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530210 mask = ipmi::network::MASK_32_BIT;
211 mask = htonl(mask << (ipmi::network::BITS_32 - prefix));
212 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500213 // ignore the exception, as it is a valid condition that
214 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530215 catch (InternalFailure& e)
216 {
217 // nothing to do
218 }
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700219 std::memcpy(data, &mask,
220 ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530221 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800222 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530223 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800224 inet_pton(AF_INET, channelConf->netmask.c_str(),
Ratan Guptab8e99552017-07-27 07:07:48 +0530225 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530226 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530227 }
228 break;
229
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800230 case LanParam::GATEWAY:
Ratan Guptab8e99552017-07-27 07:07:48 +0530231 {
232 std::string gateway;
233
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800234 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530235 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530236 try
237 {
238 auto systemObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700239 bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
240 ipmi::network::ROOT);
Ratan Guptab8e99552017-07-27 07:07:48 +0530241
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530242 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700243 bus, systemObject.second, systemObject.first,
244 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530245
William A. Kennington III4c008022018-10-12 17:18:14 -0700246 gateway = variant_ns::get<std::string>(
247 systemProperties["DefaultGateway"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530248 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500249 // ignore the exception, as it is a valid condition that
250 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530251 catch (InternalFailure& e)
252 {
253 // nothing to do
254 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530255 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800256 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530257 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800258 gateway = channelConf->gateway;
Ratan Guptab8e99552017-07-27 07:07:48 +0530259 }
260
261 inet_pton(AF_INET, gateway.c_str(),
262 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530263 }
264 break;
265
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800266 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530267 {
268 std::string macAddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800269 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530270 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700271 auto macObjectInfo =
272 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
273 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530274
275 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700276 bus, macObjectInfo.second, macObjectInfo.first,
277 ipmi::network::MAC_INTERFACE, "MACAddress");
Ratan Guptab8e99552017-07-27 07:07:48 +0530278
William A. Kennington III4c008022018-10-12 17:18:14 -0700279 macAddress = variant_ns::get<std::string>(variant);
Ratan Guptab8e99552017-07-27 07:07:48 +0530280 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800281 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530282 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800283 macAddress = channelConf->macAddress;
Ratan Guptab8e99552017-07-27 07:07:48 +0530284 }
285
286 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700287 (data), (data + 1), (data + 2), (data + 3), (data + 4),
Ratan Guptab8e99552017-07-27 07:07:48 +0530288 (data + 5));
289 }
290 break;
291
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800292 case LanParam::VLAN:
Ratan Gupta533d03b2017-07-30 10:39:22 +0530293 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700294 uint16_t vlanID{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800295 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530296 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530297 try
Ratan Gupta533d03b2017-07-30 10:39:22 +0530298 {
Ratan Guptadd646202017-11-21 17:46:59 +0530299 auto ipObjectInfo = ipmi::getIPObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700300 bus, ipmi::network::IP_INTERFACE,
301 ipmi::network::ROOT, ipmi::network::IP_TYPE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530302
303 vlanID = static_cast<uint16_t>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700304 ipmi::network::getVLAN(ipObjectInfo.first));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530305
306 vlanID = htole16(vlanID);
307
308 if (vlanID)
309 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700310 // Enable the 16th bit
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530311 vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK);
312 }
313 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500314 // ignore the exception, as it is a valid condition that
315 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530316 catch (InternalFailure& e)
317 {
318 // nothing to do
Ratan Gupta533d03b2017-07-30 10:39:22 +0530319 }
320
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700321 std::memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530322 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800323 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530324 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700325 std::memcpy(data, &(channelConf->vlanID),
326 ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530327 }
328 }
329 break;
330
Ratan Guptab8e99552017-07-27 07:07:48 +0530331 default:
332 rc = IPMI_CC_PARM_OUT_OF_RANGE;
tomjose26e17732016-03-03 08:52:51 -0600333 }
334 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530335 catch (InternalFailure& e)
tomjose26e17732016-03-03 08:52:51 -0600336 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530337 commit<InternalFailure>();
338 rc = IPMI_CC_UNSPECIFIED_ERROR;
339 return rc;
tomjose26e17732016-03-03 08:52:51 -0600340 }
tomjose26e17732016-03-03 08:52:51 -0600341 return rc;
342}
343
Tom Josepha30c8d32018-03-22 02:15:03 +0530344namespace cipher
345{
346
347std::vector<uint8_t> getCipherList()
348{
349 std::vector<uint8_t> cipherList;
350
351 std::ifstream jsonFile(configFile);
352 if (!jsonFile.is_open())
353 {
354 log<level::ERR>("Channel Cipher suites file not found");
355 elog<InternalFailure>();
356 }
357
358 auto data = Json::parse(jsonFile, nullptr, false);
359 if (data.is_discarded())
360 {
361 log<level::ERR>("Parsing channel cipher suites JSON failed");
362 elog<InternalFailure>();
363 }
364
365 // Byte 1 is reserved
366 cipherList.push_back(0x00);
367
368 for (const auto& record : data)
369 {
370 cipherList.push_back(record.value(cipher, 0));
371 }
372
373 return cipherList;
374}
375
Patrick Venture0b02be92018-08-31 11:55:55 -0700376} // namespace cipher
Tom Josepha30c8d32018-03-22 02:15:03 +0530377
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500378ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700379 ipmi_request_t request,
380 ipmi_response_t response,
381 ipmi_data_len_t data_len,
382 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500383{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500384 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800385 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500386 *data_len = 0;
387 return rc;
388}
389
Ratan Guptab8e99552017-07-27 07:07:48 +0530390struct set_lan_t
391{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500392 uint8_t channel;
393 uint8_t parameter;
394 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
Patrick Venture0b02be92018-08-31 11:55:55 -0700395} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500396
Patrick Venture0b02be92018-08-31 11:55:55 -0700397ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530398 ipmi_request_t request,
399 ipmi_response_t response,
400 ipmi_data_len_t data_len,
401 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500402{
403 ipmi_ret_t rc = IPMI_CC_OK;
404 *data_len = 0;
Nan Li3d0df912016-10-18 19:51:41 +0800405
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530406 using namespace std::chrono_literals;
407
408 // time to wait before applying the network changes.
409 constexpr auto networkTimeout = 10000000us; // 10 sec
410
Ratan Guptab8e99552017-07-27 07:07:48 +0530411 char ipaddr[INET_ADDRSTRLEN];
412 char netmask[INET_ADDRSTRLEN];
413 char gateway[INET_ADDRSTRLEN];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500414
Ratan Guptab8e99552017-07-27 07:07:48 +0530415 auto reqptr = reinterpret_cast<const set_lan_t*>(request);
416 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500417
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800418 // channel number is the lower nibble
419 int channel = reqptr->channel & CHANNEL_MASK;
Johnathan Mantey74a21022018-12-13 13:17:56 -0800420 auto ethdevice = ipmi::getChannelName(channel);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800421 if (ethdevice.empty())
422 {
423 return IPMI_CC_INVALID_FIELD_REQUEST;
424 }
425 auto channelConf = getChannelConfig(channel);
426
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800427 switch (static_cast<LanParam>(reqptr->parameter))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500428 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800429 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600430 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700431 std::snprintf(ipaddr, INET_ADDRSTRLEN,
432 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
433 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500434
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800435 channelConf->ipaddr.assign(ipaddr);
Ratan Guptab8e99552017-07-27 07:07:48 +0530436 }
437 break;
438
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800439 case LanParam::IPSRC:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530440 {
441 uint8_t ipsrc{};
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700442 std::memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800443 channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530444 }
445 break;
446
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800447 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530448 {
449 char mac[SIZE_MAC];
450
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700451 std::snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
452 reqptr->data[0], reqptr->data[1], reqptr->data[2],
453 reqptr->data[3], reqptr->data[4], reqptr->data[5]);
Ratan Guptab8e99552017-07-27 07:07:48 +0530454
Patrick Venture0b02be92018-08-31 11:55:55 -0700455 auto macObjectInfo =
456 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
457 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530458
Patrick Venture0b02be92018-08-31 11:55:55 -0700459 ipmi::setDbusProperty(
460 bus, macObjectInfo.second, macObjectInfo.first,
461 ipmi::network::MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptab8e99552017-07-27 07:07:48 +0530462
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800463 channelConf->macAddress = mac;
Ratan Guptab8e99552017-07-27 07:07:48 +0530464 }
465 break;
466
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800467 case LanParam::SUBNET:
Ratan Guptab8e99552017-07-27 07:07:48 +0530468 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700469 std::snprintf(netmask, INET_ADDRSTRLEN,
470 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
471 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800472 channelConf->netmask.assign(netmask);
Ratan Guptab8e99552017-07-27 07:07:48 +0530473 }
474 break;
475
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800476 case LanParam::GATEWAY:
Ratan Guptab8e99552017-07-27 07:07:48 +0530477 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700478 std::snprintf(gateway, INET_ADDRSTRLEN,
479 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
480 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800481 channelConf->gateway.assign(gateway);
Ratan Guptab8e99552017-07-27 07:07:48 +0530482 }
483 break;
484
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800485 case LanParam::VLAN:
Ratan Gupta533d03b2017-07-30 10:39:22 +0530486 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700487 uint16_t vlan{};
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700488 std::memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530489 // We are not storing the enable bit
490 // We assume that ipmitool always send enable
491 // bit as 1.
492 vlan = le16toh(vlan);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800493 channelConf->vlanID = vlan;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530494 }
495 break;
496
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800497 case LanParam::INPROGRESS:
Ratan Guptab8e99552017-07-27 07:07:48 +0530498 {
499 if (reqptr->data[0] == SET_COMPLETE)
500 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800501 channelConf->lan_set_in_progress = SET_COMPLETE;
Ratan Guptab8e99552017-07-27 07:07:48 +0530502
Patrick Venture0b02be92018-08-31 11:55:55 -0700503 log<level::INFO>(
504 "Network data from Cache",
505 entry("PREFIX=%s", channelConf->netmask.c_str()),
506 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
507 entry("GATEWAY=%s", channelConf->gateway.c_str()),
508 entry("VLAN=%d", channelConf->vlanID));
Ratan Guptab8e99552017-07-27 07:07:48 +0530509
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530510 if (!networkTimer)
511 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700512 log<level::ERR>("Network timer is not instantiated");
513 return IPMI_CC_UNSPECIFIED_ERROR;
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530514 }
515
516 // start/restart the timer
Vernon Mauery1181af72018-10-08 12:05:00 -0700517 networkTimer->start(networkTimeout);
Ratan Guptab8e99552017-07-27 07:07:48 +0530518 }
519 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
520 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800521 channelConf->lan_set_in_progress = SET_IN_PROGRESS;
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530522 channelConf->flush = true;
Ratan Guptab8e99552017-07-27 07:07:48 +0530523 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530524 }
525 break;
526
527 default:
528 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530529 rc = IPMI_CC_PARM_NOT_SUPPORTED;
530 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530531 }
vishwa1eaea4f2016-02-26 11:57:40 -0600532
tomjose26e17732016-03-03 08:52:51 -0600533 return rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500534}
535
Ratan Guptab8e99552017-07-27 07:07:48 +0530536struct get_lan_t
537{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500538 uint8_t rev_channel;
539 uint8_t parameter;
540 uint8_t parameter_set;
541 uint8_t parameter_block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700542} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500543
Patrick Venture0b02be92018-08-31 11:55:55 -0700544ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530545 ipmi_request_t request,
546 ipmi_response_t response,
547 ipmi_data_len_t data_len,
548 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500549{
550 ipmi_ret_t rc = IPMI_CC_OK;
551 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500552 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500553
Patrick Venture0b02be92018-08-31 11:55:55 -0700554 get_lan_t* reqptr = (get_lan_t*)request;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800555 // channel number is the lower nibble
556 int channel = reqptr->rev_channel & CHANNEL_MASK;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500557
558 if (reqptr->rev_channel & 0x80) // Revision is bit 7
559 {
560 // Only current revision was requested
561 *data_len = sizeof(current_revision);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700562 std::memcpy(response, &current_revision, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500563 return IPMI_CC_OK;
564 }
565
Tom Josepha30c8d32018-03-22 02:15:03 +0530566 static std::vector<uint8_t> cipherList;
567 static auto listInit = false;
568
569 if (!listInit)
570 {
571 try
572 {
573 cipherList = cipher::getCipherList();
574 listInit = true;
575 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700576 catch (const std::exception& e)
Tom Josepha30c8d32018-03-22 02:15:03 +0530577 {
578 return IPMI_CC_UNSPECIFIED_ERROR;
579 }
580 }
581
Johnathan Mantey74a21022018-12-13 13:17:56 -0800582 auto ethdevice = ipmi::getChannelName(channel);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800583 if (ethdevice.empty())
584 {
585 return IPMI_CC_INVALID_FIELD_REQUEST;
586 }
587 auto channelConf = getChannelConfig(channel);
588
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800589 LanParam param = static_cast<LanParam>(reqptr->parameter);
590 switch (param)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500591 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800592 case LanParam::INPROGRESS:
vishwa1eaea4f2016-02-26 11:57:40 -0600593 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800594 uint8_t buf[] = {current_revision,
595 channelConf->lan_set_in_progress};
596 *data_len = sizeof(buf);
597 std::memcpy(response, &buf, *data_len);
598 break;
599 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800600 case LanParam::AUTHSUPPORT:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800601 {
602 uint8_t buf[] = {current_revision, 0x04};
603 *data_len = sizeof(buf);
604 std::memcpy(response, &buf, *data_len);
605 break;
606 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800607 case LanParam::AUTHENABLES:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800608 {
609 uint8_t buf[] = {current_revision, 0x04, 0x04, 0x04, 0x04, 0x04};
610 *data_len = sizeof(buf);
611 std::memcpy(response, &buf, *data_len);
612 break;
613 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800614 case LanParam::IP:
615 case LanParam::SUBNET:
616 case LanParam::GATEWAY:
617 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800618 {
619 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1] = {};
620
621 *data_len = sizeof(current_revision);
622 std::memcpy(buf, &current_revision, *data_len);
623
624 if (getNetworkData(reqptr->parameter, &buf[1], channel) ==
625 IPMI_CC_OK)
Ratan Guptab8e99552017-07-27 07:07:48 +0530626 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800627 if (param == LanParam::MAC)
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800628 {
629 *data_len = sizeof(buf);
630 }
631 else
632 {
633 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1;
634 }
635 std::memcpy(response, &buf, *data_len);
Ratan Guptab8e99552017-07-27 07:07:48 +0530636 }
637 else
638 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800639 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptab8e99552017-07-27 07:07:48 +0530640 }
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800641 break;
Adriana Kobylak342df102016-02-10 13:48:16 -0600642 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800643 case LanParam::VLAN:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600644 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800645 uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530646
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800647 *data_len = sizeof(current_revision);
648 std::memcpy(buf, &current_revision, *data_len);
649 if (getNetworkData(reqptr->parameter, &buf[1], channel) ==
650 IPMI_CC_OK)
651 {
652 *data_len = sizeof(buf);
653 std::memcpy(response, &buf, *data_len);
654 }
655 break;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530656 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800657 case LanParam::IPSRC:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530658 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800659 uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {};
660 *data_len = sizeof(current_revision);
661 std::memcpy(buff, &current_revision, *data_len);
662 if (getNetworkData(reqptr->parameter, &buff[1], channel) ==
663 IPMI_CC_OK)
664 {
665 *data_len = sizeof(buff);
666 std::memcpy(response, &buff, *data_len);
667 }
668 break;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530669 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800670 case LanParam::CIPHER_SUITE_COUNT:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800671 {
672 *(static_cast<uint8_t*>(response)) = current_revision;
673 // Byte 1 is reserved byte and does not indicate a cipher suite ID,
674 // so no of cipher suite entry count is one less than the size of
675 // the vector
676 auto count = static_cast<uint8_t>(cipherList.size() - 1);
677 *(static_cast<uint8_t*>(response) + 1) = count;
678 *data_len = sizeof(current_revision) + sizeof(count);
679 break;
680 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800681 case LanParam::CIPHER_SUITE_ENTRIES:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800682 {
683 *(static_cast<uint8_t*>(response)) = current_revision;
684 // Byte 1 is reserved
685 std::copy_n(cipherList.data(), cipherList.size(),
686 static_cast<uint8_t*>(response) + 1);
687 *data_len = sizeof(current_revision) +
688 static_cast<uint8_t>(cipherList.size());
689 break;
690 }
691 default:
692 log<level::ERR>("Unsupported parameter",
693 entry("PARAMETER=0x%x", reqptr->parameter));
694 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500695 }
696
697 return rc;
698}
699
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530700void applyChanges(int channel)
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530701{
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530702 std::string ipaddress;
703 std::string gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700704 uint8_t prefix{};
705 uint32_t vlanID{};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530706 std::string networkInterfacePath;
707 ipmi::DbusObjectInfo ipObject;
708 ipmi::DbusObjectInfo systemObject;
709
Johnathan Mantey74a21022018-12-13 13:17:56 -0800710 auto ethdevice = ipmi::getChannelName(channel);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530711 if (ethdevice.empty())
712 {
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530713 log<level::ERR>("Unable to get the interface name",
714 entry("CHANNEL=%d", channel));
715 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530716 }
717 auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE;
718 auto channelConf = getChannelConfig(channel);
719
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530720 try
721 {
722 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
723
724 log<level::INFO>("Network data from Cache",
725 entry("PREFIX=%s", channelConf->netmask.c_str()),
726 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
727 entry("GATEWAY=%s", channelConf->gateway.c_str()),
728 entry("VLAN=%d", channelConf->vlanID),
729 entry("IPSRC=%d", channelConf->ipsrc));
730 if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK)
731 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700732 // get the first twelve bits which is vlan id
733 // not interested in rest of the bits.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530734 channelConf->vlanID = le32toh(channelConf->vlanID);
735 vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK;
736 }
737
738 // if the asked ip src is DHCP then not interested in
739 // any given data except vlan.
740 if (channelConf->ipsrc != ipmi::network::IPOrigin::DHCP)
741 {
742 // always get the system object
Patrick Venture0b02be92018-08-31 11:55:55 -0700743 systemObject =
744 ipmi::getDbusObject(bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
745 ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530746
747 // the below code is to determine the mode of the interface
748 // as the handling is same, if the system is configured with
749 // DHCP or user has given all the data.
750 try
751 {
752 ipmi::ObjectTree ancestorMap;
753
Patrick Venture0b02be92018-08-31 11:55:55 -0700754 ipmi::InterfaceList interfaces{
755 ipmi::network::ETHERNET_INTERFACE};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530756
757 // if the system is having ip object,then
758 // get the IP object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700759 ipObject = ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
760 ipmi::network::ROOT, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530761
762 // Get the parent interface of the IP object.
763 try
764 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700765 ancestorMap = ipmi::getAllAncestors(bus, ipObject.first,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530766 std::move(interfaces));
767 }
768 catch (InternalFailure& e)
769 {
770 // if unable to get the parent interface
771 // then commit the error and return.
772 log<level::ERR>("Unable to get the parent interface",
773 entry("PATH=%s", ipObject.first.c_str()),
774 entry("INTERFACE=%s",
775 ipmi::network::ETHERNET_INTERFACE));
776 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530777 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530778 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530779 }
780
781 networkInterfacePath = ancestorMap.begin()->first;
782 }
783 catch (InternalFailure& e)
784 {
785 // TODO Currently IPMI supports single interface,need to handle
786 // Multiple interface through
787 // https://github.com/openbmc/openbmc/issues/2138
788
789 // if there is no ip configured on the system,then
790 // get the network interface object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700791 auto networkInterfaceObject =
792 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
793 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530794
795 networkInterfacePath = std::move(networkInterfaceObject.first);
796 }
797
798 // get the configured mode on the system.
William A. Kennington III4c008022018-10-12 17:18:14 -0700799 auto enableDHCP = variant_ns::get<bool>(ipmi::getDbusProperty(
800 bus, ipmi::network::SERVICE, networkInterfacePath,
801 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled"));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530802
803 // if ip address source is not given then get the ip source mode
804 // from the system so that it can be applied later.
805 if (channelConf->ipsrc == ipmi::network::IPOrigin::UNSPECIFIED)
806 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700807 channelConf->ipsrc = (enableDHCP)
808 ? ipmi::network::IPOrigin::DHCP
809 : ipmi::network::IPOrigin::STATIC;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530810 }
811
812 // check whether user has given all the data
813 // or the configured system interface is dhcp enabled,
814 // in both of the cases get the values from the cache.
815 if ((!channelConf->ipaddr.empty() &&
816 !channelConf->netmask.empty() &&
817 !channelConf->gateway.empty()) ||
818 (enableDHCP)) // configured system interface mode = DHCP
819 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700820 // convert mask into prefix
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530821 ipaddress = channelConf->ipaddr;
822 prefix = ipmi::network::toPrefix(AF_INET, channelConf->netmask);
823 gateway = channelConf->gateway;
824 }
825 else // asked ip src = static and configured system src = static
Patrick Venture0b02be92018-08-31 11:55:55 -0700826 // or partially given data.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530827 {
828 // We have partial filled cache so get the remaining
829 // info from the system.
830
831 // Get the network data from the system as user has
832 // not given all the data then use the data fetched from the
833 // system but it is implementation dependent,IPMI spec doesn't
834 // force it.
835
836 // if system is not having any ip object don't throw error,
837 try
838 {
839 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700840 bus, ipObject.second, ipObject.first,
841 ipmi::network::IP_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530842
Patrick Venture0b02be92018-08-31 11:55:55 -0700843 ipaddress = channelConf->ipaddr.empty()
William A. Kennington III4c008022018-10-12 17:18:14 -0700844 ? variant_ns::get<std::string>(
845 properties["Address"])
Patrick Venture0b02be92018-08-31 11:55:55 -0700846 : channelConf->ipaddr;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530847
Patrick Venture0b02be92018-08-31 11:55:55 -0700848 prefix = channelConf->netmask.empty()
William A. Kennington III4c008022018-10-12 17:18:14 -0700849 ? variant_ns::get<uint8_t>(
850 properties["PrefixLength"])
Patrick Venture0b02be92018-08-31 11:55:55 -0700851 : ipmi::network::toPrefix(
852 AF_INET, channelConf->netmask);
853 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530854 catch (InternalFailure& e)
855 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700856 log<level::INFO>(
857 "Failed to get IP object which matches",
858 entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
859 entry("MATCH=%s", ethIp.c_str()));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530860 }
861
862 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700863 bus, systemObject.second, systemObject.first,
864 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530865
William A. Kennington III4c008022018-10-12 17:18:14 -0700866 gateway = channelConf->gateway.empty()
867 ? variant_ns::get<std::string>(
868 systemProperties["DefaultGateway"])
869 : channelConf->gateway;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530870 }
871 }
872
873 // Currently network manager doesn't support purging of all the
874 // ip addresses and the vlan interfaces from the parent interface,
875 // TODO once the support is there, will make the change here.
876 // https://github.com/openbmc/openbmc/issues/2141.
877
878 // TODO Currently IPMI supports single interface,need to handle
879 // Multiple interface through
880 // https://github.com/openbmc/openbmc/issues/2138
881
882 // instead of deleting all the vlan interfaces and
883 // all the ipv4 address,we will call reset method.
Patrick Venture0b02be92018-08-31 11:55:55 -0700884 // delete all the vlan interfaces
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530885
Patrick Venture0b02be92018-08-31 11:55:55 -0700886 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530887 ipmi::network::VLAN_INTERFACE);
888
889 // set the interface mode to static
Patrick Venture0b02be92018-08-31 11:55:55 -0700890 auto networkInterfaceObject =
891 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
892 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530893
894 // setting the physical interface mode to static.
Patrick Venture0b02be92018-08-31 11:55:55 -0700895 ipmi::setDbusProperty(
896 bus, ipmi::network::SERVICE, networkInterfaceObject.first,
897 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530898
899 networkInterfacePath = networkInterfaceObject.first;
900
Patrick Venture0b02be92018-08-31 11:55:55 -0700901 // delete all the ipv4 addresses
902 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
903 ipmi::network::IP_INTERFACE, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530904
905 if (vlanID)
906 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700907 ipmi::network::createVLAN(bus, ipmi::network::SERVICE,
908 ipmi::network::ROOT, ethdevice, vlanID);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530909
910 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700911 bus, ipmi::network::VLAN_INTERFACE, ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530912
Patrick Venture0b02be92018-08-31 11:55:55 -0700913 networkInterfacePath = networkInterfaceObject.first;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530914 }
915
916 if (channelConf->ipsrc == ipmi::network::IPOrigin::DHCP)
917 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700918 ipmi::setDbusProperty(
919 bus, ipmi::network::SERVICE, networkInterfacePath,
920 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", true);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530921 }
922 else
923 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700924 // change the mode to static
925 ipmi::setDbusProperty(
926 bus, ipmi::network::SERVICE, networkInterfacePath,
927 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530928
929 if (!ipaddress.empty())
930 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700931 ipmi::network::createIP(bus, ipmi::network::SERVICE,
932 networkInterfacePath, ipv4Protocol,
933 ipaddress, prefix);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530934 }
935
936 if (!gateway.empty())
937 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700938 ipmi::setDbusProperty(bus, systemObject.second,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530939 systemObject.first,
940 ipmi::network::SYSTEMCONFIG_INTERFACE,
Patrick Venture0b02be92018-08-31 11:55:55 -0700941 "DefaultGateway", std::string(gateway));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530942 }
943 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530944 }
945 catch (InternalFailure& e)
946 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700947 log<level::ERR>(
948 "Failed to set network data", entry("PREFIX=%d", prefix),
949 entry("ADDRESS=%s", ipaddress.c_str()),
950 entry("GATEWAY=%s", gateway.c_str()), entry("VLANID=%d", vlanID),
951 entry("IPSRC=%d", channelConf->ipsrc));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530952
953 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530954 }
955
956 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530957}
958
959void commitNetworkChanges()
960{
Patrick Venture0b02be92018-08-31 11:55:55 -0700961 for (const auto& channel : channelConfig)
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530962 {
963 if (channel.second->flush)
964 {
965 applyChanges(channel.first);
966 }
967 }
968}
969
970void createNetworkTimer()
971{
972 if (!networkTimer)
973 {
974 std::function<void()> networkTimerCallback(
Patrick Venture0b02be92018-08-31 11:55:55 -0700975 std::bind(&commitNetworkChanges));
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530976
Vernon Mauery1181af72018-10-08 12:05:00 -0700977 networkTimer = std::make_unique<phosphor::Timer>(networkTimerCallback);
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530978 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530979}
980
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500981void register_netfn_transport_functions()
982{
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530983 // As this timer is only for transport handler
984 // so creating it here.
985 createNetworkTimer();
Tom05732372016-09-06 17:21:23 +0530986 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -0700987 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL,
988 ipmi_transport_wildcard, PRIVILEGE_USER);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500989
Tom05732372016-09-06 17:21:23 +0530990 // <Set LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700991 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL,
992 ipmi_transport_set_lan, PRIVILEGE_ADMIN);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500993
Tom05732372016-09-06 17:21:23 +0530994 // <Get LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700995 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL,
996 ipmi_transport_get_lan, PRIVILEGE_OPERATOR);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500997
998 return;
999}