blob: 7d678a81a4082f2e836ebf6817bebe2c2dbbc1d1 [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
Patrick Venture0b02be92018-08-31 11:55:55 -07007#include <arpa/inet.h>
William A. Kennington III194375f2018-12-14 02:14:33 -08008#include <ipmid/api.h>
Patrick Venture0b02be92018-08-31 11:55:55 -07009
10#include <chrono>
Vernon Mauerybdda8002019-02-26 10:18:51 -080011#include <filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -070012#include <fstream>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070013#include <ipmid/utils.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070014#include <phosphor-logging/elog-errors.hpp>
15#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070016#include <sdbusplus/message/types.hpp>
Vernon Mauery1181af72018-10-08 12:05:00 -070017#include <sdbusplus/timer.hpp>
tomjose26e17732016-03-03 08:52:51 -060018#include <string>
Patrick Venture3a5071a2018-09-12 13:27:42 -070019#include <xyz/openbmc_project/Common/error.hpp>
20
21#define SYSTEMD_NETWORKD_DBUS 1
22
23#ifdef SYSTEMD_NETWORKD_DBUS
24#include <mapper.h>
25#include <systemd/sd-bus.h>
26#endif
Patrick Venture586d35b2018-09-07 19:56:18 -070027
Vernon Mauery1b7f6f22019-03-13 13:11:25 -070028// timer for network changes
29std::unique_ptr<phosphor::Timer> networkTimer = nullptr;
Ratan Gupta1247e0b2018-03-07 10:47:25 +053030
Patrick Venture0b02be92018-08-31 11:55:55 -070031const int SIZE_MAC = 18; // xx:xx:xx:xx:xx:xx
Ratan Gupta1247e0b2018-03-07 10:47:25 +053032constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Adriana Kobylake08fbc62016-02-09 16:17:23 -060033
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080034std::map<int, std::unique_ptr<struct ChannelConfig_t>> channelConfig;
Hariharasubramanian R83951912016-01-20 07:06:36 -060035
Ratan Guptab8e99552017-07-27 07:07:48 +053036using namespace phosphor::logging;
37using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta7a7f0122018-03-07 12:31:05 +053038
Vernon Mauery185b9f82018-07-20 10:52:36 -070039namespace fs = std::filesystem;
William A. Kennington III4c008022018-10-12 17:18:14 -070040namespace variant_ns = sdbusplus::message::variant_ns;
Hariharasubramanian R83951912016-01-20 07:06:36 -060041
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050042void register_netfn_transport_functions() __attribute__((constructor));
43
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080044struct ChannelConfig_t* getChannelConfig(int channel)
45{
46 auto item = channelConfig.find(channel);
47 if (item == channelConfig.end())
48 {
49 channelConfig[channel] = std::make_unique<struct ChannelConfig_t>();
50 }
51
52 return channelConfig[channel].get();
53}
54
Patrick Venture0b02be92018-08-31 11:55:55 -070055// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network
56// Manager or Cache based on Set-In-Progress State
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080057ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel)
tomjose26e17732016-03-03 08:52:51 -060058{
tomjose26e17732016-03-03 08:52:51 -060059 ipmi_ret_t rc = IPMI_CC_OK;
Ratan Guptab8e99552017-07-27 07:07:48 +053060 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Gupta533d03b2017-07-30 10:39:22 +053061
Johnathan Mantey74a21022018-12-13 13:17:56 -080062 auto ethdevice = ipmi::getChannelName(channel);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080063 // if ethdevice is an empty string they weren't expecting this channel.
64 if (ethdevice.empty())
65 {
66 // TODO: return error from getNetworkData()
67 return IPMI_CC_INVALID_FIELD_REQUEST;
68 }
69 auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE;
70 auto channelConf = getChannelConfig(channel);
71
Ratan Guptab8e99552017-07-27 07:07:48 +053072 try
tomjose26e17732016-03-03 08:52:51 -060073 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -080074 switch (static_cast<LanParam>(lan_param))
tomjose26e17732016-03-03 08:52:51 -060075 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -080076 case LanParam::IP:
Ratan Guptab8e99552017-07-27 07:07:48 +053077 {
78 std::string ipaddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080079 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +053080 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053081 try
82 {
Patrick Venture0b02be92018-08-31 11:55:55 -070083 auto ipObjectInfo =
84 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
85 ipmi::network::ROOT, ethIP);
Ratan Guptadd646202017-11-21 17:46:59 +053086
87 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -070088 bus, ipObjectInfo.second, ipObjectInfo.first,
89 ipmi::network::IP_INTERFACE);
Ratan Guptadd646202017-11-21 17:46:59 +053090
William A. Kennington III4c008022018-10-12 17:18:14 -070091 ipaddress =
92 variant_ns::get<std::string>(properties["Address"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053093 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -050094 // ignore the exception, as it is a valid condition that
95 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053096 catch (InternalFailure& e)
97 {
98 // nothing to do.
99 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530100 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800101 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530102 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800103 ipaddress = channelConf->ipaddr;
Ratan Guptab8e99552017-07-27 07:07:48 +0530104 }
105
106 inet_pton(AF_INET, ipaddress.c_str(),
107 reinterpret_cast<void*>(data));
108 }
109 break;
110
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800111 case LanParam::IPSRC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530112 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530113 std::string networkInterfacePath;
114
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800115 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530116 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530117 try
118 {
119 ipmi::ObjectTree ancestorMap;
120 // if the system is having ip object,then
121 // get the IP object.
122 auto ipObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700123 bus, ipmi::network::IP_INTERFACE,
124 ipmi::network::ROOT, ethIP);
Ratan Guptab8e99552017-07-27 07:07:48 +0530125
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530126 // Get the parent interface of the IP object.
127 try
128 {
129 ipmi::InterfaceList interfaces;
130 interfaces.emplace_back(
Patrick Venture0b02be92018-08-31 11:55:55 -0700131 ipmi::network::ETHERNET_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530132
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530133 ancestorMap = ipmi::getAllAncestors(
Patrick Venture0b02be92018-08-31 11:55:55 -0700134 bus, ipObject.first, std::move(interfaces));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530135 }
136 catch (InternalFailure& e)
137 {
138 // if unable to get the parent interface
139 // then commit the error and return.
Patrick Venture0b02be92018-08-31 11:55:55 -0700140 log<level::ERR>(
141 "Unable to get the parent interface",
142 entry("PATH=%s", ipObject.first.c_str()),
143 entry("INTERFACE=%s",
144 ipmi::network::ETHERNET_INTERFACE));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530145 break;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530146 }
147 // for an ip object there would be single parent
148 // interface.
149 networkInterfacePath = ancestorMap.begin()->first;
150 }
151 catch (InternalFailure& e)
152 {
153 // if there is no ip configured on the system,then
154 // get the network interface object.
155 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700156 bus, ipmi::network::ETHERNET_INTERFACE,
157 ipmi::network::ROOT, ethdevice);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530158
159 networkInterfacePath = networkInterfaceObject.first;
160 }
161
162 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700163 bus, ipmi::network::SERVICE, networkInterfacePath,
164 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530165
William A. Kennington III4c008022018-10-12 17:18:14 -0700166 auto dhcpEnabled = variant_ns::get<bool>(variant);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530167 // As per IPMI spec 2=>DHCP, 1=STATIC
Patrick Venture0b02be92018-08-31 11:55:55 -0700168 auto ipsrc = dhcpEnabled ? ipmi::network::IPOrigin::DHCP
169 : ipmi::network::IPOrigin::STATIC;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530170
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700171 std::memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530172 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800173 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530174 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700175 std::memcpy(data, &(channelConf->ipsrc),
176 ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530177 }
178 }
179 break;
180
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800181 case LanParam::SUBNET:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530182 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700183 unsigned long mask{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800184 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530185 {
186 try
187 {
Johnathan Mantey88416832019-01-30 15:51:04 -0800188 auto ipObjectInfo =
189 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
190 ipmi::network::ROOT, ethIP);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530191
192 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700193 bus, ipObjectInfo.second, ipObjectInfo.first,
194 ipmi::network::IP_INTERFACE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530195
William A. Kennington III4c008022018-10-12 17:18:14 -0700196 auto prefix = variant_ns::get<uint8_t>(
197 properties["PrefixLength"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530198 mask = ipmi::network::MASK_32_BIT;
199 mask = htonl(mask << (ipmi::network::BITS_32 - prefix));
200 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500201 // ignore the exception, as it is a valid condition that
202 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530203 catch (InternalFailure& e)
204 {
205 // nothing to do
206 }
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700207 std::memcpy(data, &mask,
208 ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530209 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800210 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530211 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800212 inet_pton(AF_INET, channelConf->netmask.c_str(),
Ratan Guptab8e99552017-07-27 07:07:48 +0530213 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530214 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530215 }
216 break;
217
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800218 case LanParam::GATEWAY:
Ratan Guptab8e99552017-07-27 07:07:48 +0530219 {
220 std::string gateway;
221
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800222 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530223 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530224 try
225 {
226 auto systemObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700227 bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
228 ipmi::network::ROOT);
Ratan Guptab8e99552017-07-27 07:07:48 +0530229
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530230 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700231 bus, systemObject.second, systemObject.first,
232 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530233
William A. Kennington III4c008022018-10-12 17:18:14 -0700234 gateway = variant_ns::get<std::string>(
235 systemProperties["DefaultGateway"]);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530236 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500237 // ignore the exception, as it is a valid condition that
238 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530239 catch (InternalFailure& e)
240 {
241 // nothing to do
242 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530243 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800244 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530245 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800246 gateway = channelConf->gateway;
Ratan Guptab8e99552017-07-27 07:07:48 +0530247 }
248
249 inet_pton(AF_INET, gateway.c_str(),
250 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530251 }
252 break;
253
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800254 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530255 {
256 std::string macAddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800257 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530258 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700259 auto macObjectInfo =
260 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
261 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530262
263 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700264 bus, macObjectInfo.second, macObjectInfo.first,
265 ipmi::network::MAC_INTERFACE, "MACAddress");
Ratan Guptab8e99552017-07-27 07:07:48 +0530266
William A. Kennington III4c008022018-10-12 17:18:14 -0700267 macAddress = variant_ns::get<std::string>(variant);
Ratan Guptab8e99552017-07-27 07:07:48 +0530268 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800269 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530270 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800271 macAddress = channelConf->macAddress;
Ratan Guptab8e99552017-07-27 07:07:48 +0530272 }
273
274 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700275 (data), (data + 1), (data + 2), (data + 3), (data + 4),
Ratan Guptab8e99552017-07-27 07:07:48 +0530276 (data + 5));
277 }
278 break;
279
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800280 case LanParam::VLAN:
Ratan Gupta533d03b2017-07-30 10:39:22 +0530281 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700282 uint16_t vlanID{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800283 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530284 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530285 try
Ratan Gupta533d03b2017-07-30 10:39:22 +0530286 {
Ratan Guptadd646202017-11-21 17:46:59 +0530287 auto ipObjectInfo = ipmi::getIPObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700288 bus, ipmi::network::IP_INTERFACE,
289 ipmi::network::ROOT, ipmi::network::IP_TYPE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530290
291 vlanID = static_cast<uint16_t>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700292 ipmi::network::getVLAN(ipObjectInfo.first));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530293
294 vlanID = htole16(vlanID);
295
296 if (vlanID)
297 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700298 // Enable the 16th bit
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530299 vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK);
300 }
301 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500302 // ignore the exception, as it is a valid condition that
303 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530304 catch (InternalFailure& e)
305 {
306 // nothing to do
Ratan Gupta533d03b2017-07-30 10:39:22 +0530307 }
308
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700309 std::memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530310 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800311 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530312 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700313 std::memcpy(data, &(channelConf->vlanID),
314 ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530315 }
316 }
317 break;
318
Ratan Guptab8e99552017-07-27 07:07:48 +0530319 default:
320 rc = IPMI_CC_PARM_OUT_OF_RANGE;
tomjose26e17732016-03-03 08:52:51 -0600321 }
322 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530323 catch (InternalFailure& e)
tomjose26e17732016-03-03 08:52:51 -0600324 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530325 commit<InternalFailure>();
326 rc = IPMI_CC_UNSPECIFIED_ERROR;
327 return rc;
tomjose26e17732016-03-03 08:52:51 -0600328 }
tomjose26e17732016-03-03 08:52:51 -0600329 return rc;
330}
331
Tom Josepha30c8d32018-03-22 02:15:03 +0530332namespace cipher
333{
334
335std::vector<uint8_t> getCipherList()
336{
337 std::vector<uint8_t> cipherList;
338
339 std::ifstream jsonFile(configFile);
340 if (!jsonFile.is_open())
341 {
342 log<level::ERR>("Channel Cipher suites file not found");
343 elog<InternalFailure>();
344 }
345
346 auto data = Json::parse(jsonFile, nullptr, false);
347 if (data.is_discarded())
348 {
349 log<level::ERR>("Parsing channel cipher suites JSON failed");
350 elog<InternalFailure>();
351 }
352
353 // Byte 1 is reserved
354 cipherList.push_back(0x00);
355
356 for (const auto& record : data)
357 {
358 cipherList.push_back(record.value(cipher, 0));
359 }
360
361 return cipherList;
362}
363
Patrick Venture0b02be92018-08-31 11:55:55 -0700364} // namespace cipher
Tom Josepha30c8d32018-03-22 02:15:03 +0530365
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500366ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700367 ipmi_request_t request,
368 ipmi_response_t response,
369 ipmi_data_len_t data_len,
370 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500371{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500372 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800373 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500374 *data_len = 0;
375 return rc;
376}
377
Ratan Guptab8e99552017-07-27 07:07:48 +0530378struct set_lan_t
379{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500380 uint8_t channel;
381 uint8_t parameter;
382 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
Patrick Venture0b02be92018-08-31 11:55:55 -0700383} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500384
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530385ipmi_ret_t checkAndUpdateNetwork(int channel)
386{
387 auto channelConf = getChannelConfig(channel);
388 using namespace std::chrono_literals;
389 // time to wait before applying the network changes.
390 constexpr auto networkTimeout = 10000000us; // 10 sec
391
392 // Skip the timer. Expecting more update as we are in SET_IN_PROGRESS
393 if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
394 {
395 return IPMI_CC_OK;
396 }
397
398 // Start the timer, if it is direct single param update without
399 // SET_IN_PROGRESS or many params updated through SET_IN_PROGRESS to
400 // SET_COMPLETE Note: Even for update with SET_IN_PROGRESS, don't apply the
401 // changes immediately, as ipmitool sends each param individually
402 // through SET_IN_PROGRESS to SET_COMPLETE.
403 channelConf->flush = true;
404 if (!networkTimer)
405 {
406 log<level::ERR>("Network timer is not instantiated");
407 return IPMI_CC_UNSPECIFIED_ERROR;
408 }
409 // start the timer.
410 networkTimer->start(networkTimeout);
411 return IPMI_CC_OK;
412}
413
Patrick Venture0b02be92018-08-31 11:55:55 -0700414ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530415 ipmi_request_t request,
416 ipmi_response_t response,
417 ipmi_data_len_t data_len,
418 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500419{
420 ipmi_ret_t rc = IPMI_CC_OK;
421 *data_len = 0;
Nan Li3d0df912016-10-18 19:51:41 +0800422
Ratan Guptab8e99552017-07-27 07:07:48 +0530423 char ipaddr[INET_ADDRSTRLEN];
424 char netmask[INET_ADDRSTRLEN];
425 char gateway[INET_ADDRSTRLEN];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500426
Ratan Guptab8e99552017-07-27 07:07:48 +0530427 auto reqptr = reinterpret_cast<const set_lan_t*>(request);
428 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500429
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);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800433 if (ethdevice.empty())
434 {
435 return IPMI_CC_INVALID_FIELD_REQUEST;
436 }
437 auto channelConf = getChannelConfig(channel);
438
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800439 switch (static_cast<LanParam>(reqptr->parameter))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500440 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800441 case LanParam::IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600442 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700443 std::snprintf(ipaddr, INET_ADDRSTRLEN,
444 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
445 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500446
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800447 channelConf->ipaddr.assign(ipaddr);
Ratan Guptab8e99552017-07-27 07:07:48 +0530448 }
449 break;
450
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800451 case LanParam::IPSRC:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530452 {
453 uint8_t ipsrc{};
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700454 std::memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800455 channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530456 }
457 break;
458
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800459 case LanParam::MAC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530460 {
461 char mac[SIZE_MAC];
462
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700463 std::snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
464 reqptr->data[0], reqptr->data[1], reqptr->data[2],
465 reqptr->data[3], reqptr->data[4], reqptr->data[5]);
Ratan Guptab8e99552017-07-27 07:07:48 +0530466
Patrick Venture0b02be92018-08-31 11:55:55 -0700467 auto macObjectInfo =
468 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
469 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530470
Patrick Venture0b02be92018-08-31 11:55:55 -0700471 ipmi::setDbusProperty(
472 bus, macObjectInfo.second, macObjectInfo.first,
473 ipmi::network::MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptab8e99552017-07-27 07:07:48 +0530474
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800475 channelConf->macAddress = mac;
Ratan Guptab8e99552017-07-27 07:07:48 +0530476 }
477 break;
478
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800479 case LanParam::SUBNET:
Ratan Guptab8e99552017-07-27 07:07:48 +0530480 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700481 std::snprintf(netmask, INET_ADDRSTRLEN,
482 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
483 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800484 channelConf->netmask.assign(netmask);
Ratan Guptab8e99552017-07-27 07:07:48 +0530485 }
486 break;
487
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800488 case LanParam::GATEWAY:
Ratan Guptab8e99552017-07-27 07:07:48 +0530489 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700490 std::snprintf(gateway, INET_ADDRSTRLEN,
491 ipmi::network::IP_ADDRESS_FORMAT, reqptr->data[0],
492 reqptr->data[1], reqptr->data[2], reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800493 channelConf->gateway.assign(gateway);
Ratan Guptab8e99552017-07-27 07:07:48 +0530494 }
495 break;
496
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800497 case LanParam::VLAN:
Ratan Gupta533d03b2017-07-30 10:39:22 +0530498 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700499 uint16_t vlan{};
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700500 std::memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530501 // We are not storing the enable bit
502 // We assume that ipmitool always send enable
503 // bit as 1.
504 vlan = le16toh(vlan);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800505 channelConf->vlanID = vlan;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530506 }
507 break;
508
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800509 case LanParam::INPROGRESS:
Ratan Guptab8e99552017-07-27 07:07:48 +0530510 {
511 if (reqptr->data[0] == SET_COMPLETE)
512 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800513 channelConf->lan_set_in_progress = SET_COMPLETE;
Ratan Guptab8e99552017-07-27 07:07:48 +0530514
Patrick Venture0b02be92018-08-31 11:55:55 -0700515 log<level::INFO>(
516 "Network data from Cache",
517 entry("PREFIX=%s", channelConf->netmask.c_str()),
518 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
519 entry("GATEWAY=%s", channelConf->gateway.c_str()),
520 entry("VLAN=%d", channelConf->vlanID));
Ratan Guptab8e99552017-07-27 07:07:48 +0530521 }
522 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
523 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800524 channelConf->lan_set_in_progress = SET_IN_PROGRESS;
Ratan Guptab8e99552017-07-27 07:07:48 +0530525 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530526 }
527 break;
528
529 default:
530 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530531 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530532 return rc;
Ratan Guptab8e99552017-07-27 07:07:48 +0530533 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530534 }
Richard Marian Thomaiyar75b480b2019-01-22 00:20:15 +0530535 rc = checkAndUpdateNetwork(channel);
vishwa1eaea4f2016-02-26 11:57:40 -0600536
tomjose26e17732016-03-03 08:52:51 -0600537 return rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500538}
539
Ratan Guptab8e99552017-07-27 07:07:48 +0530540struct get_lan_t
541{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500542 uint8_t rev_channel;
543 uint8_t parameter;
544 uint8_t parameter_set;
545 uint8_t parameter_block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700546} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500547
Patrick Venture0b02be92018-08-31 11:55:55 -0700548ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530549 ipmi_request_t request,
550 ipmi_response_t response,
551 ipmi_data_len_t data_len,
552 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500553{
554 ipmi_ret_t rc = IPMI_CC_OK;
555 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500556 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500557
Patrick Venture0b02be92018-08-31 11:55:55 -0700558 get_lan_t* reqptr = (get_lan_t*)request;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800559 // channel number is the lower nibble
560 int channel = reqptr->rev_channel & CHANNEL_MASK;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500561
562 if (reqptr->rev_channel & 0x80) // Revision is bit 7
563 {
564 // Only current revision was requested
565 *data_len = sizeof(current_revision);
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700566 std::memcpy(response, &current_revision, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500567 return IPMI_CC_OK;
568 }
569
Tom Josepha30c8d32018-03-22 02:15:03 +0530570 static std::vector<uint8_t> cipherList;
571 static auto listInit = false;
572
573 if (!listInit)
574 {
575 try
576 {
577 cipherList = cipher::getCipherList();
578 listInit = true;
579 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700580 catch (const std::exception& e)
Tom Josepha30c8d32018-03-22 02:15:03 +0530581 {
582 return IPMI_CC_UNSPECIFIED_ERROR;
583 }
584 }
585
Johnathan Mantey74a21022018-12-13 13:17:56 -0800586 auto ethdevice = ipmi::getChannelName(channel);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800587 if (ethdevice.empty())
588 {
589 return IPMI_CC_INVALID_FIELD_REQUEST;
590 }
591 auto channelConf = getChannelConfig(channel);
592
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800593 LanParam param = static_cast<LanParam>(reqptr->parameter);
594 switch (param)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500595 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800596 case LanParam::INPROGRESS:
vishwa1eaea4f2016-02-26 11:57:40 -0600597 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800598 uint8_t buf[] = {current_revision,
599 channelConf->lan_set_in_progress};
600 *data_len = sizeof(buf);
601 std::memcpy(response, &buf, *data_len);
602 break;
603 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800604 case LanParam::AUTHSUPPORT:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800605 {
606 uint8_t buf[] = {current_revision, 0x04};
607 *data_len = sizeof(buf);
608 std::memcpy(response, &buf, *data_len);
609 break;
610 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800611 case LanParam::AUTHENABLES:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800612 {
613 uint8_t buf[] = {current_revision, 0x04, 0x04, 0x04, 0x04, 0x04};
614 *data_len = sizeof(buf);
615 std::memcpy(response, &buf, *data_len);
616 break;
617 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800618 case LanParam::IP:
619 case LanParam::SUBNET:
620 case LanParam::GATEWAY:
621 case LanParam::MAC:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800622 {
623 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1] = {};
624
625 *data_len = sizeof(current_revision);
626 std::memcpy(buf, &current_revision, *data_len);
627
628 if (getNetworkData(reqptr->parameter, &buf[1], channel) ==
629 IPMI_CC_OK)
Ratan Guptab8e99552017-07-27 07:07:48 +0530630 {
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800631 if (param == LanParam::MAC)
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800632 {
633 *data_len = sizeof(buf);
634 }
635 else
636 {
637 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1;
638 }
639 std::memcpy(response, &buf, *data_len);
Ratan Guptab8e99552017-07-27 07:07:48 +0530640 }
641 else
642 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800643 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptab8e99552017-07-27 07:07:48 +0530644 }
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800645 break;
Adriana Kobylak342df102016-02-10 13:48:16 -0600646 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800647 case LanParam::VLAN:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600648 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800649 uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530650
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800651 *data_len = sizeof(current_revision);
652 std::memcpy(buf, &current_revision, *data_len);
653 if (getNetworkData(reqptr->parameter, &buf[1], channel) ==
654 IPMI_CC_OK)
655 {
656 *data_len = sizeof(buf);
657 std::memcpy(response, &buf, *data_len);
658 }
659 break;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530660 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800661 case LanParam::IPSRC:
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530662 {
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800663 uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {};
664 *data_len = sizeof(current_revision);
665 std::memcpy(buff, &current_revision, *data_len);
666 if (getNetworkData(reqptr->parameter, &buff[1], channel) ==
667 IPMI_CC_OK)
668 {
669 *data_len = sizeof(buff);
670 std::memcpy(response, &buff, *data_len);
671 }
672 break;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530673 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800674 case LanParam::CIPHER_SUITE_COUNT:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800675 {
676 *(static_cast<uint8_t*>(response)) = current_revision;
677 // Byte 1 is reserved byte and does not indicate a cipher suite ID,
678 // so no of cipher suite entry count is one less than the size of
679 // the vector
680 auto count = static_cast<uint8_t>(cipherList.size() - 1);
681 *(static_cast<uint8_t*>(response) + 1) = count;
682 *data_len = sizeof(current_revision) + sizeof(count);
683 break;
684 }
William A. Kennington IIIaab20232018-11-19 18:20:39 -0800685 case LanParam::CIPHER_SUITE_ENTRIES:
William A. Kennington III39f94ef2018-11-19 22:36:16 -0800686 {
687 *(static_cast<uint8_t*>(response)) = current_revision;
688 // Byte 1 is reserved
689 std::copy_n(cipherList.data(), cipherList.size(),
690 static_cast<uint8_t*>(response) + 1);
691 *data_len = sizeof(current_revision) +
692 static_cast<uint8_t>(cipherList.size());
693 break;
694 }
695 default:
696 log<level::ERR>("Unsupported parameter",
697 entry("PARAMETER=0x%x", reqptr->parameter));
698 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500699 }
700
701 return rc;
702}
703
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530704void applyChanges(int channel)
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530705{
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530706 std::string ipaddress;
707 std::string gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700708 uint8_t prefix{};
709 uint32_t vlanID{};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530710 std::string networkInterfacePath;
711 ipmi::DbusObjectInfo ipObject;
712 ipmi::DbusObjectInfo systemObject;
713
Johnathan Mantey74a21022018-12-13 13:17:56 -0800714 auto ethdevice = ipmi::getChannelName(channel);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530715 if (ethdevice.empty())
716 {
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530717 log<level::ERR>("Unable to get the interface name",
718 entry("CHANNEL=%d", channel));
719 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530720 }
721 auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE;
722 auto channelConf = getChannelConfig(channel);
723
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530724 try
725 {
726 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
727
728 log<level::INFO>("Network data from Cache",
729 entry("PREFIX=%s", channelConf->netmask.c_str()),
730 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
731 entry("GATEWAY=%s", channelConf->gateway.c_str()),
732 entry("VLAN=%d", channelConf->vlanID),
733 entry("IPSRC=%d", channelConf->ipsrc));
734 if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK)
735 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700736 // get the first twelve bits which is vlan id
737 // not interested in rest of the bits.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530738 channelConf->vlanID = le32toh(channelConf->vlanID);
739 vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK;
740 }
741
742 // if the asked ip src is DHCP then not interested in
743 // any given data except vlan.
744 if (channelConf->ipsrc != ipmi::network::IPOrigin::DHCP)
745 {
746 // always get the system object
Patrick Venture0b02be92018-08-31 11:55:55 -0700747 systemObject =
748 ipmi::getDbusObject(bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
749 ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530750
751 // the below code is to determine the mode of the interface
752 // as the handling is same, if the system is configured with
753 // DHCP or user has given all the data.
754 try
755 {
756 ipmi::ObjectTree ancestorMap;
757
Patrick Venture0b02be92018-08-31 11:55:55 -0700758 ipmi::InterfaceList interfaces{
759 ipmi::network::ETHERNET_INTERFACE};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530760
761 // if the system is having ip object,then
762 // get the IP object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700763 ipObject = ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
764 ipmi::network::ROOT, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530765
766 // Get the parent interface of the IP object.
767 try
768 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700769 ancestorMap = ipmi::getAllAncestors(bus, ipObject.first,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530770 std::move(interfaces));
771 }
772 catch (InternalFailure& e)
773 {
774 // if unable to get the parent interface
775 // then commit the error and return.
776 log<level::ERR>("Unable to get the parent interface",
777 entry("PATH=%s", ipObject.first.c_str()),
778 entry("INTERFACE=%s",
779 ipmi::network::ETHERNET_INTERFACE));
780 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530781 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530782 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530783 }
784
785 networkInterfacePath = ancestorMap.begin()->first;
786 }
787 catch (InternalFailure& e)
788 {
789 // TODO Currently IPMI supports single interface,need to handle
790 // Multiple interface through
791 // https://github.com/openbmc/openbmc/issues/2138
792
793 // if there is no ip configured on the system,then
794 // get the network interface object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700795 auto networkInterfaceObject =
796 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
797 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530798
799 networkInterfacePath = std::move(networkInterfaceObject.first);
800 }
801
802 // get the configured mode on the system.
William A. Kennington III4c008022018-10-12 17:18:14 -0700803 auto enableDHCP = variant_ns::get<bool>(ipmi::getDbusProperty(
804 bus, ipmi::network::SERVICE, networkInterfacePath,
805 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled"));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530806
807 // if ip address source is not given then get the ip source mode
808 // from the system so that it can be applied later.
809 if (channelConf->ipsrc == ipmi::network::IPOrigin::UNSPECIFIED)
810 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700811 channelConf->ipsrc = (enableDHCP)
812 ? ipmi::network::IPOrigin::DHCP
813 : ipmi::network::IPOrigin::STATIC;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530814 }
815
816 // check whether user has given all the data
817 // or the configured system interface is dhcp enabled,
818 // in both of the cases get the values from the cache.
819 if ((!channelConf->ipaddr.empty() &&
820 !channelConf->netmask.empty() &&
821 !channelConf->gateway.empty()) ||
822 (enableDHCP)) // configured system interface mode = DHCP
823 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700824 // convert mask into prefix
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530825 ipaddress = channelConf->ipaddr;
826 prefix = ipmi::network::toPrefix(AF_INET, channelConf->netmask);
827 gateway = channelConf->gateway;
828 }
829 else // asked ip src = static and configured system src = static
Patrick Venture0b02be92018-08-31 11:55:55 -0700830 // or partially given data.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530831 {
832 // We have partial filled cache so get the remaining
833 // info from the system.
834
835 // Get the network data from the system as user has
836 // not given all the data then use the data fetched from the
837 // system but it is implementation dependent,IPMI spec doesn't
838 // force it.
839
840 // if system is not having any ip object don't throw error,
841 try
842 {
843 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700844 bus, ipObject.second, ipObject.first,
845 ipmi::network::IP_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530846
Patrick Venture0b02be92018-08-31 11:55:55 -0700847 ipaddress = channelConf->ipaddr.empty()
William A. Kennington III4c008022018-10-12 17:18:14 -0700848 ? variant_ns::get<std::string>(
849 properties["Address"])
Patrick Venture0b02be92018-08-31 11:55:55 -0700850 : channelConf->ipaddr;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530851
Patrick Venture0b02be92018-08-31 11:55:55 -0700852 prefix = channelConf->netmask.empty()
William A. Kennington III4c008022018-10-12 17:18:14 -0700853 ? variant_ns::get<uint8_t>(
854 properties["PrefixLength"])
Patrick Venture0b02be92018-08-31 11:55:55 -0700855 : ipmi::network::toPrefix(
856 AF_INET, channelConf->netmask);
857 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530858 catch (InternalFailure& e)
859 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700860 log<level::INFO>(
861 "Failed to get IP object which matches",
862 entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
863 entry("MATCH=%s", ethIp.c_str()));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530864 }
865
866 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700867 bus, systemObject.second, systemObject.first,
868 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530869
William A. Kennington III4c008022018-10-12 17:18:14 -0700870 gateway = channelConf->gateway.empty()
871 ? variant_ns::get<std::string>(
872 systemProperties["DefaultGateway"])
873 : channelConf->gateway;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530874 }
875 }
876
877 // Currently network manager doesn't support purging of all the
878 // ip addresses and the vlan interfaces from the parent interface,
879 // TODO once the support is there, will make the change here.
880 // https://github.com/openbmc/openbmc/issues/2141.
881
882 // TODO Currently IPMI supports single interface,need to handle
883 // Multiple interface through
884 // https://github.com/openbmc/openbmc/issues/2138
885
886 // instead of deleting all the vlan interfaces and
887 // all the ipv4 address,we will call reset method.
Patrick Venture0b02be92018-08-31 11:55:55 -0700888 // delete all the vlan interfaces
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530889
Patrick Venture0b02be92018-08-31 11:55:55 -0700890 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530891 ipmi::network::VLAN_INTERFACE);
892
893 // set the interface mode to static
Patrick Venture0b02be92018-08-31 11:55:55 -0700894 auto networkInterfaceObject =
895 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
896 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530897
898 // setting the physical interface mode to static.
Patrick Venture0b02be92018-08-31 11:55:55 -0700899 ipmi::setDbusProperty(
900 bus, ipmi::network::SERVICE, networkInterfaceObject.first,
901 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530902
903 networkInterfacePath = networkInterfaceObject.first;
904
Patrick Venture0b02be92018-08-31 11:55:55 -0700905 // delete all the ipv4 addresses
906 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
907 ipmi::network::IP_INTERFACE, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530908
909 if (vlanID)
910 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700911 ipmi::network::createVLAN(bus, ipmi::network::SERVICE,
912 ipmi::network::ROOT, ethdevice, vlanID);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530913
914 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700915 bus, ipmi::network::VLAN_INTERFACE, ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530916
Patrick Venture0b02be92018-08-31 11:55:55 -0700917 networkInterfacePath = networkInterfaceObject.first;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530918 }
919
920 if (channelConf->ipsrc == ipmi::network::IPOrigin::DHCP)
921 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700922 ipmi::setDbusProperty(
923 bus, ipmi::network::SERVICE, networkInterfacePath,
924 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", true);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530925 }
926 else
927 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700928 // change the mode to static
929 ipmi::setDbusProperty(
930 bus, ipmi::network::SERVICE, networkInterfacePath,
931 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530932
933 if (!ipaddress.empty())
934 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700935 ipmi::network::createIP(bus, ipmi::network::SERVICE,
936 networkInterfacePath, ipv4Protocol,
937 ipaddress, prefix);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530938 }
939
940 if (!gateway.empty())
941 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700942 ipmi::setDbusProperty(bus, systemObject.second,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530943 systemObject.first,
944 ipmi::network::SYSTEMCONFIG_INTERFACE,
Patrick Venture0b02be92018-08-31 11:55:55 -0700945 "DefaultGateway", std::string(gateway));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530946 }
947 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530948 }
949 catch (InternalFailure& e)
950 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700951 log<level::ERR>(
952 "Failed to set network data", entry("PREFIX=%d", prefix),
953 entry("ADDRESS=%s", ipaddress.c_str()),
954 entry("GATEWAY=%s", gateway.c_str()), entry("VLANID=%d", vlanID),
955 entry("IPSRC=%d", channelConf->ipsrc));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530956
957 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530958 }
959
960 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530961}
962
963void commitNetworkChanges()
964{
Patrick Venture0b02be92018-08-31 11:55:55 -0700965 for (const auto& channel : channelConfig)
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530966 {
967 if (channel.second->flush)
968 {
969 applyChanges(channel.first);
970 }
971 }
972}
973
974void createNetworkTimer()
975{
976 if (!networkTimer)
977 {
978 std::function<void()> networkTimerCallback(
Patrick Venture0b02be92018-08-31 11:55:55 -0700979 std::bind(&commitNetworkChanges));
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530980
Vernon Mauery1181af72018-10-08 12:05:00 -0700981 networkTimer = std::make_unique<phosphor::Timer>(networkTimerCallback);
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530982 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530983}
984
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500985void register_netfn_transport_functions()
986{
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530987 // As this timer is only for transport handler
988 // so creating it here.
989 createNetworkTimer();
Tom05732372016-09-06 17:21:23 +0530990 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -0700991 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL,
992 ipmi_transport_wildcard, PRIVILEGE_USER);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500993
Tom05732372016-09-06 17:21:23 +0530994 // <Set LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700995 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL,
996 ipmi_transport_set_lan, PRIVILEGE_ADMIN);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500997
Tom05732372016-09-06 17:21:23 +0530998 // <Get LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700999 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL,
1000 ipmi_transport_get_lan, PRIVILEGE_OPERATOR);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -05001001
1002 return;
1003}