blob: 217468d73fd8fdfd75aa70196f4f5e14dd3c333c [file] [log] [blame]
Patrick Venture586d35b2018-09-07 19:56:18 -07001#include "transporthandler.hpp"
2
Patrick Venture0b02be92018-08-31 11:55:55 -07003#include <arpa/inet.h>
Patrick Venture0b02be92018-08-31 11:55:55 -07004
5#include <chrono>
6#include <fstream>
tomjose26e17732016-03-03 08:52:51 -06007#include <string>
Patrick Venture586d35b2018-09-07 19:56:18 -07008
Vernon Mauery185b9f82018-07-20 10:52:36 -07009#if __has_include(<filesystem>)
10#include <filesystem>
11#elif __has_include(<experimental/filesystem>)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053012#include <experimental/filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -070013namespace std
14{
15// splice experimental::filesystem into std
16namespace filesystem = std::experimental::filesystem;
17} // namespace std
Vernon Mauery185b9f82018-07-20 10:52:36 -070018#else
Patrick Venture0b02be92018-08-31 11:55:55 -070019#error filesystem not available
Vernon Mauery185b9f82018-07-20 10:52:36 -070020#endif
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050021
Tom Josepha30c8d32018-03-22 02:15:03 +053022#include "app/channel.hpp"
Patrick Williams53a360e2016-08-12 22:01:02 -050023#include "ipmid.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -070024#include "net.hpp"
Ratan Gupta7a7f0122018-03-07 12:31:05 +053025#include "timer.hpp"
Ratan Guptab8e99552017-07-27 07:07:48 +053026#include "utils.hpp"
27
Patrick Venture46470a32018-09-07 19:26:25 -070028#include <host-ipmid/ipmid-api.h>
29
Ratan Guptab8e99552017-07-27 07:07:48 +053030#include <phosphor-logging/elog-errors.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070031#include <phosphor-logging/log.hpp>
32#include <xyz/openbmc_project/Common/error.hpp>
33
Hariharasubramanian R83951912016-01-20 07:06:36 -060034#define SYSTEMD_NETWORKD_DBUS 1
35
36#ifdef SYSTEMD_NETWORKD_DBUS
Sergey Solomineb9b8142016-08-23 09:07:28 -050037#include <mapper.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070038#include <systemd/sd-bus.h>
Hariharasubramanian R83951912016-01-20 07:06:36 -060039#endif
40
Ratan Gupta7a7f0122018-03-07 12:31:05 +053041extern std::unique_ptr<phosphor::ipmi::Timer> networkTimer;
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;
Hariharasubramanian R83951912016-01-20 07:06:36 -060052
Adriana Kobylak5d6481f2015-10-29 21:44:55 -050053void register_netfn_transport_functions() __attribute__((constructor));
54
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080055struct ChannelConfig_t* getChannelConfig(int channel)
56{
57 auto item = channelConfig.find(channel);
58 if (item == channelConfig.end())
59 {
60 channelConfig[channel] = std::make_unique<struct ChannelConfig_t>();
61 }
62
63 return channelConfig[channel].get();
64}
65
Patrick Venture0b02be92018-08-31 11:55:55 -070066// Helper Function to get IP Address/NetMask/Gateway/MAC Address from Network
67// Manager or Cache based on Set-In-Progress State
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080068ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t* data, int channel)
tomjose26e17732016-03-03 08:52:51 -060069{
tomjose26e17732016-03-03 08:52:51 -060070 ipmi_ret_t rc = IPMI_CC_OK;
Ratan Guptab8e99552017-07-27 07:07:48 +053071 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Gupta533d03b2017-07-30 10:39:22 +053072
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080073 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
74 // if ethdevice is an empty string they weren't expecting this channel.
75 if (ethdevice.empty())
76 {
77 // TODO: return error from getNetworkData()
78 return IPMI_CC_INVALID_FIELD_REQUEST;
79 }
80 auto ethIP = ethdevice + "/" + ipmi::network::IP_TYPE;
81 auto channelConf = getChannelConfig(channel);
82
Ratan Guptab8e99552017-07-27 07:07:48 +053083 try
tomjose26e17732016-03-03 08:52:51 -060084 {
Ratan Guptab8e99552017-07-27 07:07:48 +053085 switch (lan_param)
tomjose26e17732016-03-03 08:52:51 -060086 {
Ratan Guptab8e99552017-07-27 07:07:48 +053087 case LAN_PARM_IP:
88 {
89 std::string ipaddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -080090 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +053091 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +053092 try
93 {
Patrick Venture0b02be92018-08-31 11:55:55 -070094 auto ipObjectInfo =
95 ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
96 ipmi::network::ROOT, ethIP);
Ratan Guptadd646202017-11-21 17:46:59 +053097
98 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -070099 bus, ipObjectInfo.second, ipObjectInfo.first,
100 ipmi::network::IP_INTERFACE);
Ratan Guptadd646202017-11-21 17:46:59 +0530101
102 ipaddress = properties["Address"].get<std::string>();
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530103 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500104 // ignore the exception, as it is a valid condition that
105 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530106 catch (InternalFailure& e)
107 {
108 // nothing to do.
109 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530110 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800111 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530112 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800113 ipaddress = channelConf->ipaddr;
Ratan Guptab8e99552017-07-27 07:07:48 +0530114 }
115
116 inet_pton(AF_INET, ipaddress.c_str(),
117 reinterpret_cast<void*>(data));
118 }
119 break;
120
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530121 case LAN_PARM_IPSRC:
Ratan Guptab8e99552017-07-27 07:07:48 +0530122 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530123 std::string networkInterfacePath;
124
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800125 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530126 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530127 try
128 {
129 ipmi::ObjectTree ancestorMap;
130 // if the system is having ip object,then
131 // get the IP object.
132 auto ipObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700133 bus, ipmi::network::IP_INTERFACE,
134 ipmi::network::ROOT, ethIP);
Ratan Guptab8e99552017-07-27 07:07:48 +0530135
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530136 // Get the parent interface of the IP object.
137 try
138 {
139 ipmi::InterfaceList interfaces;
140 interfaces.emplace_back(
Patrick Venture0b02be92018-08-31 11:55:55 -0700141 ipmi::network::ETHERNET_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530142
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530143 ancestorMap = ipmi::getAllAncestors(
Patrick Venture0b02be92018-08-31 11:55:55 -0700144 bus, ipObject.first, std::move(interfaces));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530145 }
146 catch (InternalFailure& e)
147 {
148 // if unable to get the parent interface
149 // then commit the error and return.
Patrick Venture0b02be92018-08-31 11:55:55 -0700150 log<level::ERR>(
151 "Unable to get the parent interface",
152 entry("PATH=%s", ipObject.first.c_str()),
153 entry("INTERFACE=%s",
154 ipmi::network::ETHERNET_INTERFACE));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530155 break;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530156 }
157 // for an ip object there would be single parent
158 // interface.
159 networkInterfacePath = ancestorMap.begin()->first;
160 }
161 catch (InternalFailure& e)
162 {
163 // if there is no ip configured on the system,then
164 // get the network interface object.
165 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700166 bus, ipmi::network::ETHERNET_INTERFACE,
167 ipmi::network::ROOT, ethdevice);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530168
169 networkInterfacePath = networkInterfaceObject.first;
170 }
171
172 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700173 bus, ipmi::network::SERVICE, networkInterfacePath,
174 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled");
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530175
176 auto dhcpEnabled = variant.get<bool>();
177 // As per IPMI spec 2=>DHCP, 1=STATIC
Patrick Venture0b02be92018-08-31 11:55:55 -0700178 auto ipsrc = dhcpEnabled ? ipmi::network::IPOrigin::DHCP
179 : ipmi::network::IPOrigin::STATIC;
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530180
181 memcpy(data, &ipsrc, ipmi::network::IPSRC_SIZE_BYTE);
182 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800183 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530184 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700185 memcpy(data, &(channelConf->ipsrc),
186 ipmi::network::IPSRC_SIZE_BYTE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530187 }
188 }
189 break;
190
191 case LAN_PARM_SUBNET:
192 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700193 unsigned long mask{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800194 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530195 {
196 try
197 {
Ratan Guptadd646202017-11-21 17:46:59 +0530198 auto ipObjectInfo = ipmi::getIPObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700199 bus, ipmi::network::IP_INTERFACE,
200 ipmi::network::ROOT, ipmi::network::IP_TYPE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530201
202 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700203 bus, ipObjectInfo.second, ipObjectInfo.first,
204 ipmi::network::IP_INTERFACE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530205
206 auto prefix = properties["PrefixLength"].get<uint8_t>();
207 mask = ipmi::network::MASK_32_BIT;
208 mask = htonl(mask << (ipmi::network::BITS_32 - prefix));
209 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500210 // ignore the exception, as it is a valid condition that
211 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530212 catch (InternalFailure& e)
213 {
214 // nothing to do
215 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530216 memcpy(data, &mask, ipmi::network::IPV4_ADDRESS_SIZE_BYTE);
217 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800218 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530219 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800220 inet_pton(AF_INET, channelConf->netmask.c_str(),
Ratan Guptab8e99552017-07-27 07:07:48 +0530221 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530222 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530223 }
224 break;
225
226 case LAN_PARM_GATEWAY:
227 {
228 std::string gateway;
229
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800230 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530231 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530232 try
233 {
234 auto systemObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700235 bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
236 ipmi::network::ROOT);
Ratan Guptab8e99552017-07-27 07:07:48 +0530237
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530238 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700239 bus, systemObject.second, systemObject.first,
240 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530241
Patrick Venture0b02be92018-08-31 11:55:55 -0700242 gateway = systemProperties["DefaultGateway"]
243 .get<std::string>();
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530244 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500245 // ignore the exception, as it is a valid condition that
246 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530247 catch (InternalFailure& e)
248 {
249 // nothing to do
250 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530251 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800252 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530253 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800254 gateway = channelConf->gateway;
Ratan Guptab8e99552017-07-27 07:07:48 +0530255 }
256
257 inet_pton(AF_INET, gateway.c_str(),
258 reinterpret_cast<void*>(data));
Ratan Guptab8e99552017-07-27 07:07:48 +0530259 }
260 break;
261
262 case LAN_PARM_MAC:
263 {
264 std::string macAddress;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800265 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Guptab8e99552017-07-27 07:07:48 +0530266 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700267 auto macObjectInfo =
268 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
269 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530270
271 auto variant = ipmi::getDbusProperty(
Patrick Venture0b02be92018-08-31 11:55:55 -0700272 bus, macObjectInfo.second, macObjectInfo.first,
273 ipmi::network::MAC_INTERFACE, "MACAddress");
Ratan Guptab8e99552017-07-27 07:07:48 +0530274
275 macAddress = variant.get<std::string>();
Ratan Guptab8e99552017-07-27 07:07:48 +0530276 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800277 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Guptab8e99552017-07-27 07:07:48 +0530278 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800279 macAddress = channelConf->macAddress;
Ratan Guptab8e99552017-07-27 07:07:48 +0530280 }
281
282 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700283 (data), (data + 1), (data + 2), (data + 3), (data + 4),
Ratan Guptab8e99552017-07-27 07:07:48 +0530284 (data + 5));
285 }
286 break;
287
Ratan Gupta533d03b2017-07-30 10:39:22 +0530288 case LAN_PARM_VLAN:
289 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700290 uint16_t vlanID{};
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800291 if (channelConf->lan_set_in_progress == SET_COMPLETE)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530292 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530293 try
Ratan Gupta533d03b2017-07-30 10:39:22 +0530294 {
Ratan Guptadd646202017-11-21 17:46:59 +0530295 auto ipObjectInfo = ipmi::getIPObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700296 bus, ipmi::network::IP_INTERFACE,
297 ipmi::network::ROOT, ipmi::network::IP_TYPE);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530298
299 vlanID = static_cast<uint16_t>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700300 ipmi::network::getVLAN(ipObjectInfo.first));
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530301
302 vlanID = htole16(vlanID);
303
304 if (vlanID)
305 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700306 // Enable the 16th bit
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530307 vlanID |= htole16(ipmi::network::VLAN_ENABLE_MASK);
308 }
309 }
Gunnar Millsc9fa69e2018-04-08 16:35:25 -0500310 // ignore the exception, as it is a valid condition that
311 // the system is not configured with any IP.
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530312 catch (InternalFailure& e)
313 {
314 // nothing to do
Ratan Gupta533d03b2017-07-30 10:39:22 +0530315 }
316
317 memcpy(data, &vlanID, ipmi::network::VLAN_SIZE_BYTE);
318 }
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800319 else if (channelConf->lan_set_in_progress == SET_IN_PROGRESS)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530320 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800321 memcpy(data, &(channelConf->vlanID),
Ratan Gupta533d03b2017-07-30 10:39:22 +0530322 ipmi::network::VLAN_SIZE_BYTE);
323 }
324 }
325 break;
326
Ratan Guptab8e99552017-07-27 07:07:48 +0530327 default:
328 rc = IPMI_CC_PARM_OUT_OF_RANGE;
tomjose26e17732016-03-03 08:52:51 -0600329 }
330 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530331 catch (InternalFailure& e)
tomjose26e17732016-03-03 08:52:51 -0600332 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530333 commit<InternalFailure>();
334 rc = IPMI_CC_UNSPECIFIED_ERROR;
335 return rc;
tomjose26e17732016-03-03 08:52:51 -0600336 }
tomjose26e17732016-03-03 08:52:51 -0600337 return rc;
338}
339
Tom Josepha30c8d32018-03-22 02:15:03 +0530340namespace cipher
341{
342
343std::vector<uint8_t> getCipherList()
344{
345 std::vector<uint8_t> cipherList;
346
347 std::ifstream jsonFile(configFile);
348 if (!jsonFile.is_open())
349 {
350 log<level::ERR>("Channel Cipher suites file not found");
351 elog<InternalFailure>();
352 }
353
354 auto data = Json::parse(jsonFile, nullptr, false);
355 if (data.is_discarded())
356 {
357 log<level::ERR>("Parsing channel cipher suites JSON failed");
358 elog<InternalFailure>();
359 }
360
361 // Byte 1 is reserved
362 cipherList.push_back(0x00);
363
364 for (const auto& record : data)
365 {
366 cipherList.push_back(record.value(cipher, 0));
367 }
368
369 return cipherList;
370}
371
Patrick Venture0b02be92018-08-31 11:55:55 -0700372} // namespace cipher
Tom Josepha30c8d32018-03-22 02:15:03 +0530373
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500374ipmi_ret_t ipmi_transport_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700375 ipmi_request_t request,
376 ipmi_response_t response,
377 ipmi_data_len_t data_len,
378 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500379{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500380 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800381 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500382 *data_len = 0;
383 return rc;
384}
385
Ratan Guptab8e99552017-07-27 07:07:48 +0530386struct set_lan_t
387{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500388 uint8_t channel;
389 uint8_t parameter;
390 uint8_t data[8]; // Per IPMI spec, not expecting more than this size
Patrick Venture0b02be92018-08-31 11:55:55 -0700391} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500392
Patrick Venture0b02be92018-08-31 11:55:55 -0700393ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530394 ipmi_request_t request,
395 ipmi_response_t response,
396 ipmi_data_len_t data_len,
397 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500398{
399 ipmi_ret_t rc = IPMI_CC_OK;
400 *data_len = 0;
Nan Li3d0df912016-10-18 19:51:41 +0800401
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530402 using namespace std::chrono_literals;
403
404 // time to wait before applying the network changes.
405 constexpr auto networkTimeout = 10000000us; // 10 sec
406
Ratan Guptab8e99552017-07-27 07:07:48 +0530407 char ipaddr[INET_ADDRSTRLEN];
408 char netmask[INET_ADDRSTRLEN];
409 char gateway[INET_ADDRSTRLEN];
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500410
Ratan Guptab8e99552017-07-27 07:07:48 +0530411 auto reqptr = reinterpret_cast<const set_lan_t*>(request);
412 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500413
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800414 // channel number is the lower nibble
415 int channel = reqptr->channel & CHANNEL_MASK;
416 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
417 if (ethdevice.empty())
418 {
419 return IPMI_CC_INVALID_FIELD_REQUEST;
420 }
421 auto channelConf = getChannelConfig(channel);
422
Ratan Guptab8e99552017-07-27 07:07:48 +0530423 switch (reqptr->parameter)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500424 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530425 case LAN_PARM_IP:
Hariharasubramanian R83951912016-01-20 07:06:36 -0600426 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530427 snprintf(ipaddr, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700428 reqptr->data[0], reqptr->data[1], reqptr->data[2],
429 reqptr->data[3]);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500430
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800431 channelConf->ipaddr.assign(ipaddr);
Ratan Guptab8e99552017-07-27 07:07:48 +0530432 }
433 break;
434
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530435 case LAN_PARM_IPSRC:
436 {
437 uint8_t ipsrc{};
438 memcpy(&ipsrc, reqptr->data, ipmi::network::IPSRC_SIZE_BYTE);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800439 channelConf->ipsrc = static_cast<ipmi::network::IPOrigin>(ipsrc);
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530440 }
441 break;
442
Ratan Guptab8e99552017-07-27 07:07:48 +0530443 case LAN_PARM_MAC:
444 {
445 char mac[SIZE_MAC];
446
447 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700448 reqptr->data[0], reqptr->data[1], reqptr->data[2],
449 reqptr->data[3], reqptr->data[4], reqptr->data[5]);
Ratan Guptab8e99552017-07-27 07:07:48 +0530450
Patrick Venture0b02be92018-08-31 11:55:55 -0700451 auto macObjectInfo =
452 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE,
453 ipmi::network::ROOT, ethdevice);
Ratan Guptab8e99552017-07-27 07:07:48 +0530454
Patrick Venture0b02be92018-08-31 11:55:55 -0700455 ipmi::setDbusProperty(
456 bus, macObjectInfo.second, macObjectInfo.first,
457 ipmi::network::MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptab8e99552017-07-27 07:07:48 +0530458
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800459 channelConf->macAddress = mac;
Ratan Guptab8e99552017-07-27 07:07:48 +0530460 }
461 break;
462
463 case LAN_PARM_SUBNET:
464 {
465 snprintf(netmask, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700466 reqptr->data[0], reqptr->data[1], reqptr->data[2],
467 reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800468 channelConf->netmask.assign(netmask);
Ratan Guptab8e99552017-07-27 07:07:48 +0530469 }
470 break;
471
472 case LAN_PARM_GATEWAY:
473 {
474 snprintf(gateway, INET_ADDRSTRLEN, ipmi::network::IP_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700475 reqptr->data[0], reqptr->data[1], reqptr->data[2],
476 reqptr->data[3]);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800477 channelConf->gateway.assign(gateway);
Ratan Guptab8e99552017-07-27 07:07:48 +0530478 }
479 break;
480
Ratan Gupta533d03b2017-07-30 10:39:22 +0530481 case LAN_PARM_VLAN:
482 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700483 uint16_t vlan{};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530484 memcpy(&vlan, reqptr->data, ipmi::network::VLAN_SIZE_BYTE);
485 // We are not storing the enable bit
486 // We assume that ipmitool always send enable
487 // bit as 1.
488 vlan = le16toh(vlan);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800489 channelConf->vlanID = vlan;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530490 }
491 break;
492
Ratan Guptab8e99552017-07-27 07:07:48 +0530493 case LAN_PARM_INPROGRESS:
494 {
495 if (reqptr->data[0] == SET_COMPLETE)
496 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800497 channelConf->lan_set_in_progress = SET_COMPLETE;
Ratan Guptab8e99552017-07-27 07:07:48 +0530498
Patrick Venture0b02be92018-08-31 11:55:55 -0700499 log<level::INFO>(
500 "Network data from Cache",
501 entry("PREFIX=%s", channelConf->netmask.c_str()),
502 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
503 entry("GATEWAY=%s", channelConf->gateway.c_str()),
504 entry("VLAN=%d", channelConf->vlanID));
Ratan Guptab8e99552017-07-27 07:07:48 +0530505
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530506 if (!networkTimer)
507 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700508 log<level::ERR>("Network timer is not instantiated");
509 return IPMI_CC_UNSPECIFIED_ERROR;
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530510 }
511
512 // start/restart the timer
513 networkTimer->startTimer(networkTimeout);
Ratan Guptab8e99552017-07-27 07:07:48 +0530514 }
515 else if (reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress
516 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800517 channelConf->lan_set_in_progress = SET_IN_PROGRESS;
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530518 channelConf->flush = true;
Ratan Guptab8e99552017-07-27 07:07:48 +0530519 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530520 }
521 break;
522
523 default:
524 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530525 rc = IPMI_CC_PARM_NOT_SUPPORTED;
526 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530527 }
vishwa1eaea4f2016-02-26 11:57:40 -0600528
tomjose26e17732016-03-03 08:52:51 -0600529 return rc;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500530}
531
Ratan Guptab8e99552017-07-27 07:07:48 +0530532struct get_lan_t
533{
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500534 uint8_t rev_channel;
535 uint8_t parameter;
536 uint8_t parameter_set;
537 uint8_t parameter_block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700538} __attribute__((packed));
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500539
Patrick Venture0b02be92018-08-31 11:55:55 -0700540ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Ratan Guptab8e99552017-07-27 07:07:48 +0530541 ipmi_request_t request,
542 ipmi_response_t response,
543 ipmi_data_len_t data_len,
544 ipmi_context_t context)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500545{
546 ipmi_ret_t rc = IPMI_CC_OK;
547 *data_len = 0;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500548 const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500549
Patrick Venture0b02be92018-08-31 11:55:55 -0700550 get_lan_t* reqptr = (get_lan_t*)request;
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800551 // channel number is the lower nibble
552 int channel = reqptr->rev_channel & CHANNEL_MASK;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500553
554 if (reqptr->rev_channel & 0x80) // Revision is bit 7
555 {
556 // Only current revision was requested
557 *data_len = sizeof(current_revision);
558 memcpy(response, &current_revision, *data_len);
559 return IPMI_CC_OK;
560 }
561
Tom Josepha30c8d32018-03-22 02:15:03 +0530562 static std::vector<uint8_t> cipherList;
563 static auto listInit = false;
564
565 if (!listInit)
566 {
567 try
568 {
569 cipherList = cipher::getCipherList();
570 listInit = true;
571 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700572 catch (const std::exception& e)
Tom Josepha30c8d32018-03-22 02:15:03 +0530573 {
574 return IPMI_CC_UNSPECIFIED_ERROR;
575 }
576 }
577
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800578 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
579 if (ethdevice.empty())
580 {
581 return IPMI_CC_INVALID_FIELD_REQUEST;
582 }
583 auto channelConf = getChannelConfig(channel);
584
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600585 if (reqptr->parameter == LAN_PARM_INPROGRESS)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500586 {
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800587 uint8_t buf[] = {current_revision, channelConf->lan_set_in_progress};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500588 *data_len = sizeof(buf);
589 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500590 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600591 else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500592 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700593 uint8_t buf[] = {current_revision, 0x04};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500594 *data_len = sizeof(buf);
595 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500596 }
Adriana Kobylake08fbc62016-02-09 16:17:23 -0600597 else if (reqptr->parameter == LAN_PARM_AUTHENABLES)
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500598 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700599 uint8_t buf[] = {current_revision, 0x04, 0x04, 0x04, 0x04, 0x04};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500600 *data_len = sizeof(buf);
601 memcpy(response, &buf, *data_len);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500602 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530603 else if ((reqptr->parameter == LAN_PARM_IP) ||
604 (reqptr->parameter == LAN_PARM_SUBNET) ||
605 (reqptr->parameter == LAN_PARM_GATEWAY) ||
606 (reqptr->parameter == LAN_PARM_MAC))
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500607 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530608 uint8_t buf[ipmi::network::MAC_ADDRESS_SIZE_BYTE + 1] = {};
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500609
tomjose26e17732016-03-03 08:52:51 -0600610 *data_len = sizeof(current_revision);
611 memcpy(buf, &current_revision, *data_len);
612
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800613 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
vishwa1eaea4f2016-02-26 11:57:40 -0600614 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530615 if (reqptr->parameter == LAN_PARM_MAC)
616 {
617 *data_len = sizeof(buf);
618 }
619 else
620 {
621 *data_len = ipmi::network::IPV4_ADDRESS_SIZE_BYTE + 1;
622 }
tomjose26e17732016-03-03 08:52:51 -0600623 memcpy(response, &buf, *data_len);
Adriana Kobylak342df102016-02-10 13:48:16 -0600624 }
tomjose26e17732016-03-03 08:52:51 -0600625 else
Hariharasubramanian R83951912016-01-20 07:06:36 -0600626 {
tomjose26e17732016-03-03 08:52:51 -0600627 rc = IPMI_CC_UNSPECIFIED_ERROR;
Hariharasubramanian R83951912016-01-20 07:06:36 -0600628 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500629 }
Ratan Gupta533d03b2017-07-30 10:39:22 +0530630 else if (reqptr->parameter == LAN_PARM_VLAN)
631 {
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530632 uint8_t buf[ipmi::network::VLAN_SIZE_BYTE + 1] = {};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530633
634 *data_len = sizeof(current_revision);
635 memcpy(buf, &current_revision, *data_len);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800636 if (getNetworkData(reqptr->parameter, &buf[1], channel) == IPMI_CC_OK)
Ratan Gupta533d03b2017-07-30 10:39:22 +0530637 {
638 *data_len = sizeof(buf);
639 memcpy(response, &buf, *data_len);
640 }
641 }
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530642 else if (reqptr->parameter == LAN_PARM_IPSRC)
643 {
644 uint8_t buff[ipmi::network::IPSRC_SIZE_BYTE + 1] = {};
645 *data_len = sizeof(current_revision);
646 memcpy(buff, &current_revision, *data_len);
Patrick Venturec7c1c3c2017-11-15 14:29:18 -0800647 if (getNetworkData(reqptr->parameter, &buff[1], channel) == IPMI_CC_OK)
Ratan Guptacc6cdbf2017-09-01 23:06:25 +0530648 {
649 *data_len = sizeof(buff);
650 memcpy(response, &buff, *data_len);
651 }
652 }
Tom Josepha30c8d32018-03-22 02:15:03 +0530653 else if (reqptr->parameter == CIPHER_SUITE_COUNT)
654 {
655 *(static_cast<uint8_t*>(response)) = current_revision;
656 // Byte 1 is reserved byte and does not indicate a cipher suite ID, so
657 // no of cipher suite entry count is one less than the size of the
658 // vector
659 auto count = static_cast<uint8_t>(cipherList.size() - 1);
660 *(static_cast<uint8_t*>(response) + 1) = count;
661 *data_len = sizeof(current_revision) + sizeof(count);
662 }
663 else if (reqptr->parameter == CIPHER_SUITE_ENTRIES)
664 {
665 *(static_cast<uint8_t*>(response)) = current_revision;
666 // Byte 1 is reserved
Patrick Venture0b02be92018-08-31 11:55:55 -0700667 std::copy_n(cipherList.data(), cipherList.size(),
Tom Josepha30c8d32018-03-22 02:15:03 +0530668 static_cast<uint8_t*>(response) + 1);
Patrick Venture0b02be92018-08-31 11:55:55 -0700669 *data_len =
670 sizeof(current_revision) + static_cast<uint8_t>(cipherList.size());
Tom Josepha30c8d32018-03-22 02:15:03 +0530671 }
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500672 else
673 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530674 log<level::ERR>("Unsupported parameter",
675 entry("PARAMETER=0x%x", reqptr->parameter));
vishwa1eaea4f2016-02-26 11:57:40 -0600676 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500677 }
678
679 return rc;
680}
681
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530682void applyChanges(int channel)
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530683{
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530684 std::string ipaddress;
685 std::string gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700686 uint8_t prefix{};
687 uint32_t vlanID{};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530688 std::string networkInterfacePath;
689 ipmi::DbusObjectInfo ipObject;
690 ipmi::DbusObjectInfo systemObject;
691
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530692 auto ethdevice = ipmi::network::ChanneltoEthernet(channel);
693 if (ethdevice.empty())
694 {
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530695 log<level::ERR>("Unable to get the interface name",
696 entry("CHANNEL=%d", channel));
697 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530698 }
699 auto ethIp = ethdevice + "/" + ipmi::network::IP_TYPE;
700 auto channelConf = getChannelConfig(channel);
701
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530702 try
703 {
704 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
705
706 log<level::INFO>("Network data from Cache",
707 entry("PREFIX=%s", channelConf->netmask.c_str()),
708 entry("ADDRESS=%s", channelConf->ipaddr.c_str()),
709 entry("GATEWAY=%s", channelConf->gateway.c_str()),
710 entry("VLAN=%d", channelConf->vlanID),
711 entry("IPSRC=%d", channelConf->ipsrc));
712 if (channelConf->vlanID != ipmi::network::VLAN_ID_MASK)
713 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700714 // get the first twelve bits which is vlan id
715 // not interested in rest of the bits.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530716 channelConf->vlanID = le32toh(channelConf->vlanID);
717 vlanID = channelConf->vlanID & ipmi::network::VLAN_ID_MASK;
718 }
719
720 // if the asked ip src is DHCP then not interested in
721 // any given data except vlan.
722 if (channelConf->ipsrc != ipmi::network::IPOrigin::DHCP)
723 {
724 // always get the system object
Patrick Venture0b02be92018-08-31 11:55:55 -0700725 systemObject =
726 ipmi::getDbusObject(bus, ipmi::network::SYSTEMCONFIG_INTERFACE,
727 ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530728
729 // the below code is to determine the mode of the interface
730 // as the handling is same, if the system is configured with
731 // DHCP or user has given all the data.
732 try
733 {
734 ipmi::ObjectTree ancestorMap;
735
Patrick Venture0b02be92018-08-31 11:55:55 -0700736 ipmi::InterfaceList interfaces{
737 ipmi::network::ETHERNET_INTERFACE};
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530738
739 // if the system is having ip object,then
740 // get the IP object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700741 ipObject = ipmi::getIPObject(bus, ipmi::network::IP_INTERFACE,
742 ipmi::network::ROOT, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530743
744 // Get the parent interface of the IP object.
745 try
746 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700747 ancestorMap = ipmi::getAllAncestors(bus, ipObject.first,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530748 std::move(interfaces));
749 }
750 catch (InternalFailure& e)
751 {
752 // if unable to get the parent interface
753 // then commit the error and return.
754 log<level::ERR>("Unable to get the parent interface",
755 entry("PATH=%s", ipObject.first.c_str()),
756 entry("INTERFACE=%s",
757 ipmi::network::ETHERNET_INTERFACE));
758 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530759 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530760 return;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530761 }
762
763 networkInterfacePath = ancestorMap.begin()->first;
764 }
765 catch (InternalFailure& e)
766 {
767 // TODO Currently IPMI supports single interface,need to handle
768 // Multiple interface through
769 // https://github.com/openbmc/openbmc/issues/2138
770
771 // if there is no ip configured on the system,then
772 // get the network interface object.
Patrick Venture0b02be92018-08-31 11:55:55 -0700773 auto networkInterfaceObject =
774 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
775 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530776
777 networkInterfacePath = std::move(networkInterfaceObject.first);
778 }
779
780 // get the configured mode on the system.
Patrick Venture0b02be92018-08-31 11:55:55 -0700781 auto enableDHCP =
782 ipmi::getDbusProperty(
783 bus, ipmi::network::SERVICE, networkInterfacePath,
784 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled")
785 .get<bool>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530786
787 // if ip address source is not given then get the ip source mode
788 // from the system so that it can be applied later.
789 if (channelConf->ipsrc == ipmi::network::IPOrigin::UNSPECIFIED)
790 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700791 channelConf->ipsrc = (enableDHCP)
792 ? ipmi::network::IPOrigin::DHCP
793 : ipmi::network::IPOrigin::STATIC;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530794 }
795
796 // check whether user has given all the data
797 // or the configured system interface is dhcp enabled,
798 // in both of the cases get the values from the cache.
799 if ((!channelConf->ipaddr.empty() &&
800 !channelConf->netmask.empty() &&
801 !channelConf->gateway.empty()) ||
802 (enableDHCP)) // configured system interface mode = DHCP
803 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700804 // convert mask into prefix
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530805 ipaddress = channelConf->ipaddr;
806 prefix = ipmi::network::toPrefix(AF_INET, channelConf->netmask);
807 gateway = channelConf->gateway;
808 }
809 else // asked ip src = static and configured system src = static
Patrick Venture0b02be92018-08-31 11:55:55 -0700810 // or partially given data.
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530811 {
812 // We have partial filled cache so get the remaining
813 // info from the system.
814
815 // Get the network data from the system as user has
816 // not given all the data then use the data fetched from the
817 // system but it is implementation dependent,IPMI spec doesn't
818 // force it.
819
820 // if system is not having any ip object don't throw error,
821 try
822 {
823 auto properties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700824 bus, ipObject.second, ipObject.first,
825 ipmi::network::IP_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530826
Patrick Venture0b02be92018-08-31 11:55:55 -0700827 ipaddress = channelConf->ipaddr.empty()
828 ? properties["Address"].get<std::string>()
829 : channelConf->ipaddr;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530830
Patrick Venture0b02be92018-08-31 11:55:55 -0700831 prefix = channelConf->netmask.empty()
832 ? properties["PrefixLength"].get<uint8_t>()
833 : ipmi::network::toPrefix(
834 AF_INET, channelConf->netmask);
835 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530836 catch (InternalFailure& e)
837 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700838 log<level::INFO>(
839 "Failed to get IP object which matches",
840 entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
841 entry("MATCH=%s", ethIp.c_str()));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530842 }
843
844 auto systemProperties = ipmi::getAllDbusProperties(
Patrick Venture0b02be92018-08-31 11:55:55 -0700845 bus, systemObject.second, systemObject.first,
846 ipmi::network::SYSTEMCONFIG_INTERFACE);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530847
Patrick Venture0b02be92018-08-31 11:55:55 -0700848 gateway =
849 channelConf->gateway.empty()
850 ? systemProperties["DefaultGateway"].get<std::string>()
851 : channelConf->gateway;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530852 }
853 }
854
855 // Currently network manager doesn't support purging of all the
856 // ip addresses and the vlan interfaces from the parent interface,
857 // TODO once the support is there, will make the change here.
858 // https://github.com/openbmc/openbmc/issues/2141.
859
860 // TODO Currently IPMI supports single interface,need to handle
861 // Multiple interface through
862 // https://github.com/openbmc/openbmc/issues/2138
863
864 // instead of deleting all the vlan interfaces and
865 // all the ipv4 address,we will call reset method.
Patrick Venture0b02be92018-08-31 11:55:55 -0700866 // delete all the vlan interfaces
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530867
Patrick Venture0b02be92018-08-31 11:55:55 -0700868 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530869 ipmi::network::VLAN_INTERFACE);
870
871 // set the interface mode to static
Patrick Venture0b02be92018-08-31 11:55:55 -0700872 auto networkInterfaceObject =
873 ipmi::getDbusObject(bus, ipmi::network::ETHERNET_INTERFACE,
874 ipmi::network::ROOT, ethdevice);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530875
876 // setting the physical interface mode to static.
Patrick Venture0b02be92018-08-31 11:55:55 -0700877 ipmi::setDbusProperty(
878 bus, ipmi::network::SERVICE, networkInterfaceObject.first,
879 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530880
881 networkInterfacePath = networkInterfaceObject.first;
882
Patrick Venture0b02be92018-08-31 11:55:55 -0700883 // delete all the ipv4 addresses
884 ipmi::deleteAllDbusObjects(bus, ipmi::network::ROOT,
885 ipmi::network::IP_INTERFACE, ethIp);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530886
887 if (vlanID)
888 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700889 ipmi::network::createVLAN(bus, ipmi::network::SERVICE,
890 ipmi::network::ROOT, ethdevice, vlanID);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530891
892 auto networkInterfaceObject = ipmi::getDbusObject(
Patrick Venture0b02be92018-08-31 11:55:55 -0700893 bus, ipmi::network::VLAN_INTERFACE, ipmi::network::ROOT);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530894
Patrick Venture0b02be92018-08-31 11:55:55 -0700895 networkInterfacePath = networkInterfaceObject.first;
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530896 }
897
898 if (channelConf->ipsrc == ipmi::network::IPOrigin::DHCP)
899 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700900 ipmi::setDbusProperty(
901 bus, ipmi::network::SERVICE, networkInterfacePath,
902 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", true);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530903 }
904 else
905 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700906 // change the mode to static
907 ipmi::setDbusProperty(
908 bus, ipmi::network::SERVICE, networkInterfacePath,
909 ipmi::network::ETHERNET_INTERFACE, "DHCPEnabled", false);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530910
911 if (!ipaddress.empty())
912 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700913 ipmi::network::createIP(bus, ipmi::network::SERVICE,
914 networkInterfacePath, ipv4Protocol,
915 ipaddress, prefix);
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530916 }
917
918 if (!gateway.empty())
919 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700920 ipmi::setDbusProperty(bus, systemObject.second,
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530921 systemObject.first,
922 ipmi::network::SYSTEMCONFIG_INTERFACE,
Patrick Venture0b02be92018-08-31 11:55:55 -0700923 "DefaultGateway", std::string(gateway));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530924 }
925 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530926 }
927 catch (InternalFailure& e)
928 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700929 log<level::ERR>(
930 "Failed to set network data", entry("PREFIX=%d", prefix),
931 entry("ADDRESS=%s", ipaddress.c_str()),
932 entry("GATEWAY=%s", gateway.c_str()), entry("VLANID=%d", vlanID),
933 entry("IPSRC=%d", channelConf->ipsrc));
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530934
935 commit<InternalFailure>();
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530936 }
937
938 channelConf->clear();
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530939}
940
941void commitNetworkChanges()
942{
Patrick Venture0b02be92018-08-31 11:55:55 -0700943 for (const auto& channel : channelConfig)
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530944 {
945 if (channel.second->flush)
946 {
947 applyChanges(channel.first);
948 }
949 }
950}
951
952void createNetworkTimer()
953{
954 if (!networkTimer)
955 {
956 std::function<void()> networkTimerCallback(
Patrick Venture0b02be92018-08-31 11:55:55 -0700957 std::bind(&commitNetworkChanges));
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530958
Patrick Venture0b02be92018-08-31 11:55:55 -0700959 networkTimer = std::make_unique<phosphor::ipmi::Timer>(
960 ipmid_get_sd_event_connection(), networkTimerCallback);
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530961 }
Ratan Gupta1247e0b2018-03-07 10:47:25 +0530962}
963
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500964void register_netfn_transport_functions()
965{
Ratan Gupta7a7f0122018-03-07 12:31:05 +0530966 // As this timer is only for transport handler
967 // so creating it here.
968 createNetworkTimer();
Tom05732372016-09-06 17:21:23 +0530969 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -0700970 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_WILDCARD, NULL,
971 ipmi_transport_wildcard, PRIVILEGE_USER);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500972
Tom05732372016-09-06 17:21:23 +0530973 // <Set LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700974 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_SET_LAN, NULL,
975 ipmi_transport_set_lan, PRIVILEGE_ADMIN);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500976
Tom05732372016-09-06 17:21:23 +0530977 // <Get LAN Configuration Parameters>
Patrick Venture0b02be92018-08-31 11:55:55 -0700978 ipmi_register_callback(NETFUN_TRANSPORT, IPMI_CMD_GET_LAN, NULL,
979 ipmi_transport_get_lan, PRIVILEGE_OPERATOR);
Adriana Kobylak5d6481f2015-10-29 21:44:55 -0500980
981 return;
982}