blob: f1cd2dd809ebd74402c0c2fdbfd6d465c474d9b9 [file] [log] [blame]
vishwabmcba0bd5f2015-09-30 16:50:23 +05301#include "apphandler.h"
Patrick Venture5e6ac712017-10-25 12:16:19 -07002#include "app/watchdog.hpp"
Patrick Williams37af7332016-09-02 21:21:42 -05003#include "host-ipmid/ipmid-api.h"
Patrick Williams53a360e2016-08-12 22:01:02 -05004#include "ipmid.hpp"
Ratan Guptab8e99552017-07-27 07:07:48 +05305#include "types.hpp"
6#include "utils.hpp"
7
vishwabmcba0bd5f2015-09-30 16:50:23 +05308#include <stdio.h>
9#include <string.h>
Chris Austen6caf28b2015-10-13 12:40:40 -050010#include <stdint.h>
Adriana Kobylak3a552e12015-10-19 16:11:00 -050011#include <systemd/sd-bus.h>
Sergey Solomineb9b8142016-08-23 09:07:28 -050012#include <mapper.h>
Nan Liee0cb902016-07-11 15:38:03 +080013#include <array>
Tom Joseph69fabfe2017-08-04 10:15:01 +053014#include <vector>
Ratan Gupta62736ec2017-09-02 12:02:47 +053015#include <experimental/filesystem>
16
Nan Li3d0df912016-10-18 19:51:41 +080017#include <arpa/inet.h>
Ratan Guptab8e99552017-07-27 07:07:48 +053018#include "transporthandler.hpp"
19
20#include <phosphor-logging/log.hpp>
21#include <phosphor-logging/elog-errors.hpp>
22#include "xyz/openbmc_project/Common/error.hpp"
23
Adriana Kobylak3a552e12015-10-19 16:11:00 -050024extern sd_bus *bus;
vishwabmcba0bd5f2015-09-30 16:50:23 +053025
Nan Li3d0df912016-10-18 19:51:41 +080026constexpr auto app_obj = "/org/openbmc/NetworkManager/Interface";
27constexpr auto app_ifc = "org.openbmc.NetworkManager";
28constexpr auto app_nwinterface = "eth0";
29
Ratan Guptab8e99552017-07-27 07:07:48 +053030constexpr auto ipv4Protocol = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
31
Chris Austen6caf28b2015-10-13 12:40:40 -050032void register_netfn_app_functions() __attribute__((constructor));
vishwabmcba0bd5f2015-09-30 16:50:23 +053033
Ratan Guptab8e99552017-07-27 07:07:48 +053034using namespace phosphor::logging;
35using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Ratan Gupta62736ec2017-09-02 12:02:47 +053036namespace fs = std::experimental::filesystem;
Ratan Guptab8e99552017-07-27 07:07:48 +053037
Nan Liee0cb902016-07-11 15:38:03 +080038// Offset in get device id command.
39typedef struct
40{
41 uint8_t id;
42 uint8_t revision;
43 uint8_t fw[2];
44 uint8_t ipmi_ver;
45 uint8_t addn_dev_support;
46 uint8_t manuf_id[3];
47 uint8_t prod_id[2];
48 uint8_t aux[4];
49}__attribute__((packed)) ipmi_device_id_t;
Chris Austen7303bdc2016-04-17 11:50:54 -050050
Adriana Kobylak3a552e12015-10-19 16:11:00 -050051ipmi_ret_t ipmi_app_set_acpi_power_state(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
52 ipmi_request_t request, ipmi_response_t response,
Chris Austen6caf28b2015-10-13 12:40:40 -050053 ipmi_data_len_t data_len, ipmi_context_t context)
54{
55 ipmi_ret_t rc = IPMI_CC_OK;
56 *data_len = 0;
57
58 printf("IPMI SET ACPI STATE Ignoring for now\n");
59 return rc;
60}
61
Chris Austen7303bdc2016-04-17 11:50:54 -050062
63typedef struct
64{
65 char major;
66 char minor;
Chris Austen176c9652016-04-30 16:32:17 -050067 uint16_t d[2];
Chris Austen7303bdc2016-04-17 11:50:54 -050068} rev_t;
69
70
71/* Currently only supports the vx.x-x-[-x] format Will return -1 if not in */
72/* the format this routine knows how to parse */
73/* version = v0.6-19-gf363f61-dirty */
74/* ^ ^ ^^ ^ */
75/* | | |----------|-- additional details */
76/* | |---------------- Minor */
77/* |------------------ Major */
78/* Additional details : If the option group exists it will force Auxiliary */
79/* Firmware Revision Information 4th byte to 1 indicating the build was */
80/* derived with additional edits */
81int convert_version(const char *p, rev_t *rev)
82{
83 char *s, *token;
Chris Austen176c9652016-04-30 16:32:17 -050084 uint16_t commits;
Chris Austen7303bdc2016-04-17 11:50:54 -050085
86 if (*p != 'v')
87 return -1;
88 p++;
89
90 s = strdup(p);
91 token = strtok(s,".-");
92
93 rev->major = (int8_t) atoi(token);
94
95 token = strtok(NULL, ".-");
96 rev->minor = (int8_t) atoi(token);
97
98 // Capture the number of commits on top of the minor tag.
99 // I'm using BE format like the ipmi spec asked for
100 token = strtok(NULL,".-");
Chris Austen7303bdc2016-04-17 11:50:54 -0500101
Chris Austen176c9652016-04-30 16:32:17 -0500102 if (token) {
103 commits = (int16_t) atoi(token);
104 rev->d[0] = (commits>>8) | (commits<<8);
Chris Austen7303bdc2016-04-17 11:50:54 -0500105
Chris Austen176c9652016-04-30 16:32:17 -0500106 // commit number we skip
107 token = strtok(NULL,".-");
Chris Austen7303bdc2016-04-17 11:50:54 -0500108
Chris Austen176c9652016-04-30 16:32:17 -0500109 } else {
110 rev->d[0] = 0;
111 }
Chris Austen7303bdc2016-04-17 11:50:54 -0500112
113 // Any value of the optional parameter forces it to 1
Chris Austen176c9652016-04-30 16:32:17 -0500114 if (token)
115 token = strtok(NULL,".-");
116
117 rev->d[1] = (token != NULL) ? 1 : 0;
Chris Austen7303bdc2016-04-17 11:50:54 -0500118
119 free(s);
120 return 0;
121}
122
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500123ipmi_ret_t ipmi_app_get_device_id(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
124 ipmi_request_t request, ipmi_response_t response,
Chris Austen6caf28b2015-10-13 12:40:40 -0500125 ipmi_data_len_t data_len, ipmi_context_t context)
126{
127 ipmi_ret_t rc = IPMI_CC_OK;
Chris Austen7303bdc2016-04-17 11:50:54 -0500128 const char *objname = "/org/openbmc/inventory/system/chassis/motherboard/bmc";
129 const char *iface = "org.openbmc.InventoryItem";
130 char *ver = NULL;
Sergey Solomineb9b8142016-08-23 09:07:28 -0500131 char *busname = NULL;
Chris Austen7303bdc2016-04-17 11:50:54 -0500132 int r;
133 rev_t rev = {0};
Nan Liee0cb902016-07-11 15:38:03 +0800134 ipmi_device_id_t dev_id{};
Chris Austen6caf28b2015-10-13 12:40:40 -0500135
136 // Data length
Chris Austen7303bdc2016-04-17 11:50:54 -0500137 *data_len = sizeof(dev_id);
138
Nan Liee0cb902016-07-11 15:38:03 +0800139 // From IPMI spec, controller that have different application commands, or different
140 // definitions of OEM fields, are expected to have different Device ID values.
141 // Set to 0 now.
142
143 // Device Revision is set to 0 now.
144 // Bit7 identifies if device provide Device SDRs, obmc don't have SDR,we use ipmi to
145 // simulate SDR, hence the value:
146 dev_id.revision = 0x80;
147
148 // Firmware revision is already implemented, so get it from appropriate position.
Sergey Solomineb9b8142016-08-23 09:07:28 -0500149 r = mapper_get_service(bus, objname, &busname);
150 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400151 fprintf(stderr, "Failed to get %s bus name: %s\n",
152 objname, strerror(-r));
Sergey Solomineb9b8142016-08-23 09:07:28 -0500153 goto finish;
154 }
Chris Austen7303bdc2016-04-17 11:50:54 -0500155 r = sd_bus_get_property_string(bus,busname,objname,iface,"version", NULL, &ver);
156 if ( r < 0 ) {
157 fprintf(stderr, "Failed to obtain version property: %s\n", strerror(-r));
158 } else {
159 r = convert_version(ver, &rev);
160 if( r >= 0 ) {
Nan Liee0cb902016-07-11 15:38:03 +0800161 // bit7 identifies if the device is available, 0=normal operation,
162 // 1=device firmware, SDR update or self-initialization in progress.
163 // our SDR is normal working condition, so mask:
164 dev_id.fw[0] = 0x7F & rev.major;
Adriana Kobylak0e912642016-06-22 16:54:39 -0500165
166 rev.minor = (rev.minor > 99 ? 99 : rev.minor);
Nan Liee0cb902016-07-11 15:38:03 +0800167 dev_id.fw[1] = rev.minor % 10 + (rev.minor / 10) * 16;
168 memcpy(&dev_id.aux, rev.d, 4);
Chris Austen7303bdc2016-04-17 11:50:54 -0500169 }
170 }
Chris Austen6caf28b2015-10-13 12:40:40 -0500171
Nan Liee0cb902016-07-11 15:38:03 +0800172 // IPMI Spec verison 2.0
173 dev_id.ipmi_ver = 2;
174
175 // Additional device Support.
176 // List the 'logical device' commands and functions that the controller supports
177 // that are in addition to the mandatory IPM and Application commands.
178 // [7] Chassis Device (device functions as chassis device per ICMB spec.)
179 // [6] Bridge (device responds to Bridge NetFn commands)
180 // [5] IPMB Event Generator
181 // [4] IPMB Event Receiver
182 // [3] FRU Inventory Device
183 // [2] SEL Device
184 // [1] SDR Repository Device
185 // [0] Sensor Device
186 // We support FRU/SEL/Sensor now:
187 dev_id.addn_dev_support = 0x8D;
188
189 // This value is the IANA number assigned to "IBM Platform Firmware
190 // Division", which is also used by our service processor. We may want
191 // a different number or at least a different version?
192 dev_id.manuf_id[0] = 0x41;
193 dev_id.manuf_id[1] = 0xA7;
194 dev_id.manuf_id[2] = 0x00;
195
196 // Witherspoon's product ID is hardcoded to 4F42(ASCII 'OB').
197 // TODO: openbmc/openbmc#495
198 dev_id.prod_id[0] = 0x4F;
199 dev_id.prod_id[1] = 0x42;
200
Chris Austen6caf28b2015-10-13 12:40:40 -0500201 // Pack the actual response
Chris Austen7303bdc2016-04-17 11:50:54 -0500202 memcpy(response, &dev_id, *data_len);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500203finish:
204 free(busname);
Xo Wange5536382017-07-20 20:14:00 -0700205 free(ver);
Chris Austen6caf28b2015-10-13 12:40:40 -0500206 return rc;
207}
208
Nan Li41fa24a2016-11-10 20:12:37 +0800209ipmi_ret_t ipmi_app_get_self_test_results(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
210 ipmi_request_t request, ipmi_response_t response,
211 ipmi_data_len_t data_len, ipmi_context_t context)
212{
213 ipmi_ret_t rc = IPMI_CC_OK;
214
215 // Byte 2:
216 // 55h - No error.
217 // 56h - Self Test funciton not implemented in this controller.
218 // 57h - Corrupted or inaccesssible data or devices.
219 // 58h - Fatal hardware error.
220 // FFh - reserved.
221 // all other: Device-specific 'internal failure'.
222 // Byte 3:
223 // For byte 2 = 55h, 56h, FFh: 00h
224 // For byte 2 = 58h, all other: Device-specific
225 // For byte 2 = 57h: self-test error bitfield.
226 // Note: returning 57h does not imply that all test were run.
227 // [7] 1b = Cannot access SEL device.
228 // [6] 1b = Cannot access SDR Repository.
229 // [5] 1b = Cannot access BMC FRU device.
230 // [4] 1b = IPMB signal lines do not respond.
231 // [3] 1b = SDR Repository empty.
232 // [2] 1b = Internal Use Area of BMC FRU corrupted.
233 // [1] 1b = controller update 'boot block' firmware corrupted.
234 // [0] 1b = controller operational firmware corrupted.
235
236 char selftestresults[2] = {0};
237
238 *data_len = 2;
239
240 selftestresults[0] = 0x56;
241 selftestresults[1] = 0;
242
243 memcpy(response, selftestresults, *data_len);
244
245 return rc;
246}
247
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500248ipmi_ret_t ipmi_app_get_device_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
249 ipmi_request_t request, ipmi_response_t response,
250 ipmi_data_len_t data_len, ipmi_context_t context)
251{
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500252 const char *objname = "/org/openbmc/control/chassis0";
Adriana Kobylak31bccae2015-11-05 13:31:06 -0600253 const char *iface = "org.freedesktop.DBus.Properties";
254 const char *chassis_iface = "org.openbmc.control.Chassis";
vishwa1eaea4f2016-02-26 11:57:40 -0600255 sd_bus_message *reply = NULL;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500256 sd_bus_error error = SD_BUS_ERROR_NULL;
257 int r = 0;
258 char *uuid = NULL;
Sergey Solomineb9b8142016-08-23 09:07:28 -0500259 char *busname = NULL;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500260
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500261 // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
262 // Per IPMI Spec 2.0 need to convert to 16 hex bytes and reverse the byte order
263 // Ex: 0x2332fc2c40e66298e511f2782395a361
264
265 const int resp_size = 16; // Response is 16 hex bytes per IPMI Spec
266 uint8_t resp_uuid[resp_size]; // Array to hold the formatted response
267 int resp_loc = resp_size-1; // Point resp end of array to save in reverse order
268 int i = 0;
269 char *tokptr = NULL;
vishwa1eaea4f2016-02-26 11:57:40 -0600270 char *id_octet = NULL;
271
272 // Status code.
273 ipmi_ret_t rc = IPMI_CC_OK;
274 *data_len = 0;
275
276 printf("IPMI GET DEVICE GUID\n");
277
278 // Call Get properties method with the interface and property name
Sergey Solomineb9b8142016-08-23 09:07:28 -0500279 r = mapper_get_service(bus, objname, &busname);
280 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400281 fprintf(stderr, "Failed to get %s bus name: %s\n",
282 objname, strerror(-r));
Sergey Solomineb9b8142016-08-23 09:07:28 -0500283 goto finish;
284 }
vishwa1eaea4f2016-02-26 11:57:40 -0600285 r = sd_bus_call_method(bus,busname,objname,iface,
286 "Get",&error, &reply, "ss",
287 chassis_iface, "uuid");
288 if (r < 0)
289 {
290 fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r));
291 rc = IPMI_CC_UNSPECIFIED_ERROR;
292 goto finish;
293 }
294
295 r = sd_bus_message_read(reply, "v", "s", &uuid);
296 if (r < 0 || uuid == NULL)
297 {
298 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
299 rc = IPMI_CC_RESPONSE_ERROR;
300 goto finish;
301 }
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500302
303 // Traverse the UUID
vishwa1eaea4f2016-02-26 11:57:40 -0600304 id_octet = strtok_r(uuid, "-", &tokptr); // Get the UUID octects separated by dash
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500305
306 if (id_octet == NULL)
vishwa1eaea4f2016-02-26 11:57:40 -0600307 {
308 // Error
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500309 fprintf(stderr, "Unexpected UUID format: %s", uuid);
vishwa1eaea4f2016-02-26 11:57:40 -0600310 rc = IPMI_CC_RESPONSE_ERROR;
311 goto finish;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500312 }
313
314 while (id_octet != NULL)
315 {
316 // Calculate the octet string size since it varies
317 // Divide it by 2 for the array size since 1 byte is built from 2 chars
318 int tmp_size = strlen(id_octet)/2;
319
320 for(i = 0; i < tmp_size; i++)
321 {
Joel Stanley38310cd2015-11-25 17:32:08 +1030322 char tmp_array[3] = {0}; // Holder of the 2 chars that will become a byte
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500323 strncpy(tmp_array, id_octet, 2); // 2 chars at a time
324
325 int resp_byte = strtoul(tmp_array, NULL, 16); // Convert to hex byte
326 memcpy((void*)&resp_uuid[resp_loc], &resp_byte, 1); // Copy end to first
327 resp_loc--;
328 id_octet+=2; // Finished with the 2 chars, advance
329 }
330 id_octet=strtok_r(NULL, "-", &tokptr); // Get next octet
331 }
332
333 // Data length
334 *data_len = resp_size;
335
336 // Pack the actual response
337 memcpy(response, &resp_uuid, *data_len);
338
vishwa1eaea4f2016-02-26 11:57:40 -0600339finish:
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500340 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600341 reply = sd_bus_message_unref(reply);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500342 free(busname);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500343
344 return rc;
345}
Chris Austen6caf28b2015-10-13 12:40:40 -0500346
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500347ipmi_ret_t ipmi_app_get_bt_capabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
348 ipmi_request_t request, ipmi_response_t response,
vishwabmcba0bd5f2015-09-30 16:50:23 +0530349 ipmi_data_len_t data_len, ipmi_context_t context)
350{
351 printf("Handling Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd);
352
353 // Status code.
354 ipmi_ret_t rc = IPMI_CC_OK;
355
Adriana Kobylak88ad8152016-12-13 10:09:08 -0600356 // Per IPMI 2.0 spec, the input and output buffer size must be the max
357 // buffer size minus one byte to allocate space for the length byte.
358 uint8_t str[] = {0x01, MAX_IPMI_BUFFER-1, MAX_IPMI_BUFFER-1, 0x0A, 0x01};
vishwabmcba0bd5f2015-09-30 16:50:23 +0530359
360 // Data length
361 *data_len = sizeof(str);
362
363 // Pack the actual response
364 memcpy(response, &str, *data_len);
365
366 return rc;
367}
368
Ratan Guptab8e99552017-07-27 07:07:48 +0530369extern struct ChannelConfig_t channelConfig;
Nan Li3d0df912016-10-18 19:51:41 +0800370
Ratan Guptab8e99552017-07-27 07:07:48 +0530371ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn,
372 ipmi_cmd_t cmd,
373 ipmi_request_t request,
374 ipmi_response_t response,
375 ipmi_data_len_t data_len,
376 ipmi_context_t context)
Nan Li3d0df912016-10-18 19:51:41 +0800377{
378 ipmi_ret_t rc = IPMI_CC_OK;
379
Ratan Guptab8e99552017-07-27 07:07:48 +0530380 std::string ipaddress;
381 std::string gateway;
382 uint8_t prefix {};
Ratan Gupta533d03b2017-07-30 10:39:22 +0530383 uint32_t vlanID {};
Ratan Gupta62736ec2017-09-02 12:02:47 +0530384 std::string networkInterfacePath;
385 ipmi::DbusObjectInfo ipObject;
386 ipmi::DbusObjectInfo systemObject;
Nan Li3d0df912016-10-18 19:51:41 +0800387
388 // Todo: parse the request data if needed.
Nan Li3d0df912016-10-18 19:51:41 +0800389 // Using Set Channel cmd to apply changes of Set Lan Cmd.
Ratan Guptab8e99552017-07-27 07:07:48 +0530390 try
391 {
Ratan Guptab8e99552017-07-27 07:07:48 +0530392 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
393
394 log<level::INFO>("Network data from Cache",
395 entry("PREFIX=%s", channelConfig.netmask.c_str()),
396 entry("ADDRESS=%s", channelConfig.ipaddr.c_str()),
Ratan Gupta62736ec2017-09-02 12:02:47 +0530397 entry("GATEWAY=%s", channelConfig.gateway.c_str()),
398 entry("VLAN=%d", channelConfig.vlanID),
399 entry("IPSRC=%d", channelConfig.ipsrc));
Ratan Guptab8e99552017-07-27 07:07:48 +0530400
Ratan Gupta62736ec2017-09-02 12:02:47 +0530401 if (channelConfig.vlanID != ipmi::network::VLAN_ID_MASK)
Ratan Guptab8e99552017-07-27 07:07:48 +0530402 {
Ratan Gupta62736ec2017-09-02 12:02:47 +0530403 //get the first twelve bits which is vlan id
404 //not interested in rest of the bits.
405 channelConfig.vlanID = le32toh(channelConfig.vlanID);
406 vlanID = channelConfig.vlanID & ipmi::network::VLAN_ID_MASK;
Ratan Guptab8e99552017-07-27 07:07:48 +0530407 }
Ratan Gupta62736ec2017-09-02 12:02:47 +0530408
409 // if the asked ip src is DHCP then not interested in
410 // any given data except vlan.
411 if (channelConfig.ipsrc != ipmi::network::IPOrigin::DHCP)
Ratan Guptab8e99552017-07-27 07:07:48 +0530412 {
Ratan Gupta62736ec2017-09-02 12:02:47 +0530413 // always get the system object
414 systemObject = ipmi::getDbusObject(
415 bus,
416 ipmi::network::SYSTEMCONFIG_INTERFACE,
417 ipmi::network::ROOT);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530418
Ratan Gupta62736ec2017-09-02 12:02:47 +0530419 // the below code is to determine the mode of the interface
420 // as the handling is same, if the system is configured with
421 // DHCP or user has given all the data.
Ratan Guptab8e99552017-07-27 07:07:48 +0530422 try
423 {
Ratan Gupta62736ec2017-09-02 12:02:47 +0530424 ipmi::ObjectTree ancestorMap;
425
426 ipmi::InterfaceList interfaces {
427 ipmi::network::ETHERNET_INTERFACE };
428
429 // if the system is having ip object,then
430 // get the IP object.
431 ipObject = ipmi::getDbusObject(bus,
432 ipmi::network::IP_INTERFACE,
433 ipmi::network::ROOT,
434 ipmi::network::IP_TYPE);
435
436 // Get the parent interface of the IP object.
437 try
438 {
439 ancestorMap = ipmi::getAllAncestors(bus,
440 ipObject.first,
441 std::move(interfaces));
442 }
443 catch (InternalFailure& e)
444 {
445 // if unable to get the parent interface
446 // then commit the error and return.
447 log<level::ERR>("Unable to get the parent interface",
448 entry("PATH=%s", ipObject.first.c_str()),
449 entry("INTERFACE=%s",
450 ipmi::network::ETHERNET_INTERFACE));
451 commit<InternalFailure>();
452 rc = IPMI_CC_UNSPECIFIED_ERROR;
453 channelConfig.clear();
454 return rc;
455 }
456
457 networkInterfacePath = ancestorMap.begin()->first;
458 }
459 catch (InternalFailure& e)
460 {
461 // TODO Currently IPMI supports single interface,need to handle
462 // Multiple interface through
463 // https://github.com/openbmc/openbmc/issues/2138
464
465 // if there is no ip configured on the system,then
466 // get the network interface object.
467 auto networkInterfaceObject = ipmi::getDbusObject(
468 bus,
469 ipmi::network::ETHERNET_INTERFACE,
Ratan Guptab8e99552017-07-27 07:07:48 +0530470 ipmi::network::ROOT,
Ratan Gupta62736ec2017-09-02 12:02:47 +0530471 ipmi::network::INTERFACE);
Ratan Guptab8e99552017-07-27 07:07:48 +0530472
Ratan Gupta62736ec2017-09-02 12:02:47 +0530473 networkInterfacePath = std::move(networkInterfaceObject.first);
474 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530475
Ratan Gupta62736ec2017-09-02 12:02:47 +0530476 // get the configured mode on the system.
477 auto enableDHCP = ipmi::getDbusProperty(
478 bus,
479 ipmi::network::SERVICE,
480 networkInterfacePath,
481 ipmi::network::ETHERNET_INTERFACE,
482 "DHCPEnabled").get<bool>();
Ratan Guptab8e99552017-07-27 07:07:48 +0530483
Ratan Gupta62736ec2017-09-02 12:02:47 +0530484 // check whether user has given all the data
485 // or the configured system interface is dhcp enabled,
486 // in both of the cases get the values from the cache.
487 if ((!channelConfig.ipaddr.empty() &&
488 !channelConfig.netmask.empty() &&
489 !channelConfig.gateway.empty()) ||
490 (enableDHCP)) // configured system interface mode = DHCP
491 {
492 //convert mask into prefix
493 ipaddress = channelConfig.ipaddr;
494 prefix = ipmi::network::toPrefix(AF_INET, channelConfig.netmask);
495 gateway = channelConfig.gateway;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530496 if (channelConfig.vlanID != ipmi::network::VLAN_ID_MASK)
497 {
498 //get the first twelve bits which is vlan id
499 //not interested in rest of the bits.
Ratan Gupta533d03b2017-07-30 10:39:22 +0530500 channelConfig.vlanID = le32toh(channelConfig.vlanID);
Ratan Gupta62736ec2017-09-02 12:02:47 +0530501 vlanID = channelConfig.vlanID & ipmi::network::VLAN_ID_MASK;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530502 }
503 else
504 {
Ratan Gupta62736ec2017-09-02 12:02:47 +0530505 vlanID = ipmi::network::getVLAN(networkInterfacePath);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530506 }
507
Ratan Guptab8e99552017-07-27 07:07:48 +0530508 }
Ratan Gupta62736ec2017-09-02 12:02:47 +0530509 else // asked ip src = static and configured system src = static
510 // or partially given data.
Ratan Guptab8e99552017-07-27 07:07:48 +0530511 {
Ratan Gupta62736ec2017-09-02 12:02:47 +0530512 // We have partial filled cache so get the remaining
513 // info from the system.
514
515 // Get the network data from the system as user has
516 // not given all the data then use the data fetched from the
517 // system but it is implementation dependent,IPMI spec doesn't
518 // force it.
519
520 // if system is not having any ip object don't throw error,
521 try
522 {
523 auto properties = ipmi::getAllDbusProperties(
524 bus,
525 ipObject.second,
526 ipObject.first,
527 ipmi::network::IP_INTERFACE);
528
529 ipaddress = channelConfig.ipaddr.empty() ?
Nagaraju Goruganti1fe5c832017-09-21 07:44:17 -0500530 ipmi::getIPAddress(bus,
531 ipmi::network::IP_INTERFACE,
532 ipmi::network::ROOT,
533 ipmi::network::IP_TYPE) :
534 channelConfig.ipaddr;
Ratan Gupta62736ec2017-09-02 12:02:47 +0530535
536 prefix = channelConfig.netmask.empty() ?
537 properties["PrefixLength"].get<uint8_t>() :
538 ipmi::network::toPrefix(AF_INET,
539 channelConfig.netmask);
540
541 }
542 catch (InternalFailure& e)
543 {
544 log<level::INFO>("Failed to get IP object which matches",
545 entry("INTERFACE=%s", ipmi::network::IP_INTERFACE),
546 entry("MATCH=%s", ipmi::network::IP_TYPE));
547 }
548
549 auto systemProperties = ipmi::getAllDbusProperties(
550 bus,
551 systemObject.second,
552 systemObject.first,
553 ipmi::network::SYSTEMCONFIG_INTERFACE);
554
555 gateway = channelConfig.gateway.empty() ?
556 systemProperties["DefaultGateway"].get<std::string>() :
557 channelConfig.gateway;
558
Ratan Guptab8e99552017-07-27 07:07:48 +0530559 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530560 }
561
562 // Currently network manager doesn't support purging of all the
Ratan Gupta533d03b2017-07-30 10:39:22 +0530563 // ip addresses and the vlan interfaces from the parent interface,
Ratan Guptab8e99552017-07-27 07:07:48 +0530564 // TODO once the support is there, will make the change here.
565 // https://github.com/openbmc/openbmc/issues/2141.
566
567 // TODO Currently IPMI supports single interface,need to handle
568 // Multiple interface through
569 // https://github.com/openbmc/openbmc/issues/2138
570
Ratan Gupta62736ec2017-09-02 12:02:47 +0530571 // instead of deleting all the vlan interfaces and
572 // all the ipv4 address,we will call reset method.
Ratan Gupta533d03b2017-07-30 10:39:22 +0530573 //delete all the vlan interfaces
Ratan Gupta62736ec2017-09-02 12:02:47 +0530574
575 ipmi::deleteAllDbusObjects(bus,
576 ipmi::network::ROOT,
Ratan Gupta533d03b2017-07-30 10:39:22 +0530577 ipmi::network::VLAN_INTERFACE);
Ratan Gupta62736ec2017-09-02 12:02:47 +0530578
579 // set the interface mode to static
580 auto networkInterfaceObject = ipmi::getDbusObject(
581 bus,
582 ipmi::network::ETHERNET_INTERFACE,
583 ipmi::network::ROOT,
584 ipmi::network::INTERFACE);
585
586 // setting the physical interface mode to static.
587 ipmi::setDbusProperty(bus,
588 ipmi::network::SERVICE,
589 networkInterfaceObject.first,
590 ipmi::network::ETHERNET_INTERFACE,
591 "DHCPEnabled",
592 false);
593
594 networkInterfacePath = networkInterfaceObject.first;
595
596 //delete all the ipv4 addresses
597 ipmi::deleteAllDbusObjects(bus,
598 ipmi::network::ROOT,
Ratan Guptab8e99552017-07-27 07:07:48 +0530599 ipmi::network::IP_INTERFACE,
600 ipmi::network::IP_TYPE);
Ratan Gupta62736ec2017-09-02 12:02:47 +0530601
Ratan Gupta533d03b2017-07-30 10:39:22 +0530602 if (vlanID)
603 {
Ratan Gupta62736ec2017-09-02 12:02:47 +0530604 ipmi::network::createVLAN(bus,
605 ipmi::network::SERVICE,
Ratan Gupta533d03b2017-07-30 10:39:22 +0530606 ipmi::network::ROOT,
Ratan Gupta62736ec2017-09-02 12:02:47 +0530607 ipmi::network::INTERFACE,
608 vlanID);
Ratan Gupta533d03b2017-07-30 10:39:22 +0530609
Ratan Gupta62736ec2017-09-02 12:02:47 +0530610 auto networkInterfaceObject = ipmi::getDbusObject(
Ratan Gupta533d03b2017-07-30 10:39:22 +0530611 bus,
612 ipmi::network::VLAN_INTERFACE,
613 ipmi::network::ROOT);
Ratan Gupta62736ec2017-09-02 12:02:47 +0530614
615 networkInterfacePath = networkInterfaceObject.first;
Ratan Gupta533d03b2017-07-30 10:39:22 +0530616 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530617
Ratan Gupta62736ec2017-09-02 12:02:47 +0530618 if (channelConfig.ipsrc == ipmi::network::IPOrigin::DHCP)
619 {
620 ipmi::setDbusProperty(bus,
621 ipmi::network::SERVICE,
622 networkInterfacePath,
623 ipmi::network::ETHERNET_INTERFACE,
624 "DHCPEnabled",
625 true);
626 }
627 else
628 {
629 //change the mode to static
630 ipmi::setDbusProperty(bus,
631 ipmi::network::SERVICE,
632 networkInterfacePath,
633 ipmi::network::ETHERNET_INTERFACE,
634 "DHCPEnabled",
635 false);
Ratan Guptab8e99552017-07-27 07:07:48 +0530636
Ratan Gupta62736ec2017-09-02 12:02:47 +0530637 if (!ipaddress.empty())
638 {
639 ipmi::network::createIP(bus,
640 ipmi::network::SERVICE,
641 networkInterfacePath,
642 ipv4Protocol,
643 ipaddress,
644 prefix);
645 }
646
647 if (!gateway.empty())
648 {
649 ipmi::setDbusProperty(bus,
650 systemObject.second,
651 systemObject.first,
652 ipmi::network::SYSTEMCONFIG_INTERFACE,
653 "DefaultGateway",
654 std::string(gateway));
655 }
656 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530657
Nan Li3d0df912016-10-18 19:51:41 +0800658 }
Ratan Guptab8e99552017-07-27 07:07:48 +0530659 catch (InternalFailure& e)
660 {
661 log<level::ERR>("Failed to set network data",
662 entry("PREFIX=%d", prefix),
Ratan Gupta62736ec2017-09-02 12:02:47 +0530663 entry("ADDRESS=%s", ipaddress.c_str()),
664 entry("GATEWAY=%s", gateway.c_str()),
665 entry("VLANID=%d", vlanID),
666 entry("IPSRC=%d", channelConfig.ipsrc));
Nan Li3d0df912016-10-18 19:51:41 +0800667
Ratan Guptab8e99552017-07-27 07:07:48 +0530668 commit<InternalFailure>();
Nan Li3d0df912016-10-18 19:51:41 +0800669 rc = IPMI_CC_UNSPECIFIED_ERROR;
670 }
671
Ratan Guptab8e99552017-07-27 07:07:48 +0530672 channelConfig.clear();
Nan Li3d0df912016-10-18 19:51:41 +0800673 return rc;
674}
675
Tom Joseph69fabfe2017-08-04 10:15:01 +0530676ipmi_ret_t getChannelAccess(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
677 ipmi_request_t request, ipmi_response_t response,
678 ipmi_data_len_t data_len, ipmi_context_t context)
679{
680 auto requestData = reinterpret_cast<const GetChannelAccessRequest*>
681 (request);
682 std::vector<uint8_t> outPayload(sizeof(GetChannelAccessResponse));
683 auto responseData = reinterpret_cast<GetChannelAccessResponse*>
684 (outPayload.data());
685
686 // Channel 1 is arbitrarily assigned to ETH0 channel
687 constexpr auto channelOne = 0x01;
688
689 /*
690 * The value Eh is used as a way to identify the current channel that
691 * the command is being received from.
692 */
693 constexpr auto channelE = 0x0E;
694
695 if (requestData->channelNumber != channelOne &&
696 requestData->channelNumber != channelE)
697 {
698 *data_len = 0;
699 return IPMI_CC_INVALID_FIELD_REQUEST;
700 }
701
702 /*
703 * [7:6] - reserved
704 * [5] - 1b = Alerting disabled
705 * [4] - 1b = per message authentication disabled
706 * [3] - 0b = User level authentication enabled
707 * [2:0] - 2h = always available
708 */
709 constexpr auto channelSetting = 0x32;
710
711 responseData->settings = channelSetting;
712 //Defaulting the channel privilege to administrator level.
713 responseData->privilegeLimit = PRIVILEGE_ADMIN;
714
715 *data_len = outPayload.size();
716 memcpy(response, outPayload.data(), *data_len);
717
718 return IPMI_CC_OK;
719}
Ratan Gupta533d03b2017-07-30 10:39:22 +0530720
Chris Austenc2cd29d2016-02-05 20:02:29 -0600721// ATTENTION: This ipmi function is very hardcoded on purpose
722// OpenBMC does not fully support IPMI. This command is useful
723// to have around because it enables testing of interfaces with
724// the IPMI tool.
725#define GET_CHANNEL_INFO_CHANNEL_OFFSET 0
726// IPMI Table 6-2
727#define IPMI_CHANNEL_TYPE_IPMB 1
728// IPMI Table 6-3
729#define IPMI_CHANNEL_MEDIUM_TYPE_OTHER 6
730
731ipmi_ret_t ipmi_app_channel_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
732 ipmi_request_t request, ipmi_response_t response,
733 ipmi_data_len_t data_len, ipmi_context_t context)
734{
735 ipmi_ret_t rc = IPMI_CC_OK;
736 uint8_t resp[] = {
737 1,
738 IPMI_CHANNEL_MEDIUM_TYPE_OTHER,
739 IPMI_CHANNEL_TYPE_IPMB,
740 1,0x41,0xA7,0x00,0,0};
741 uint8_t *p = (uint8_t*) request;
742
743 printf("IPMI APP GET CHANNEL INFO\n");
744
tomjose7ec0add2016-06-27 07:59:28 -0500745 // The supported channels numbers are 1 and 8.
746 // Channel Number E is used as way to identify the current channel
747 // that the command is being is received from.
tomjose13fb4412016-03-08 14:02:34 -0600748 if (*p == 0xe || *p == 1 || *p == 8) {
Chris Austenc2cd29d2016-02-05 20:02:29 -0600749
750 *data_len = sizeof(resp);
751 memcpy(response, resp, *data_len);
752
753 } else {
754 rc = IPMI_CC_PARM_OUT_OF_RANGE;
755 *data_len = 0;
756 }
757
758 return rc;
759}
760
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500761ipmi_ret_t ipmi_app_wildcard_handler(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
762 ipmi_request_t request, ipmi_response_t response,
vishwabmcba0bd5f2015-09-30 16:50:23 +0530763 ipmi_data_len_t data_len, ipmi_context_t context)
764{
765 printf("Handling WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
766
767 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800768 ipmi_ret_t rc = IPMI_CC_INVALID;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530769
770 *data_len = strlen("THIS IS WILDCARD");
771
772 // Now pack actual response
773 memcpy(response, "THIS IS WILDCARD", *data_len);
774
775 return rc;
776}
777
Chris Austen6caf28b2015-10-13 12:40:40 -0500778void register_netfn_app_functions()
vishwabmcba0bd5f2015-09-30 16:50:23 +0530779{
Tom05732372016-09-06 17:21:23 +0530780 // <Get BT Interface Capabilities>
vishwabmcba0bd5f2015-09-30 16:50:23 +0530781 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CAP_BIT);
Tom05732372016-09-06 17:21:23 +0530782 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CAP_BIT, NULL, ipmi_app_get_bt_capabilities,
783 PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500784
Tom05732372016-09-06 17:21:23 +0530785 // <Wildcard Command>
Chris Austen6caf28b2015-10-13 12:40:40 -0500786 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_WILDCARD);
Tom05732372016-09-06 17:21:23 +0530787 ipmi_register_callback(NETFUN_APP, IPMI_CMD_WILDCARD, NULL, ipmi_app_wildcard_handler,
788 PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500789
Tom05732372016-09-06 17:21:23 +0530790 // <Reset Watchdog Timer>
Chris Austen6caf28b2015-10-13 12:40:40 -0500791 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_RESET_WD);
Tom05732372016-09-06 17:21:23 +0530792 ipmi_register_callback(NETFUN_APP, IPMI_CMD_RESET_WD, NULL, ipmi_app_reset_watchdog,
793 PRIVILEGE_OPERATOR);
Chris Austen6caf28b2015-10-13 12:40:40 -0500794
Tom05732372016-09-06 17:21:23 +0530795 // <Set Watchdog Timer>
Chris Austen6caf28b2015-10-13 12:40:40 -0500796 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_SET_WD);
Tom05732372016-09-06 17:21:23 +0530797 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_WD, NULL, ipmi_app_set_watchdog,
798 PRIVILEGE_OPERATOR);
Chris Austen6caf28b2015-10-13 12:40:40 -0500799
Tom05732372016-09-06 17:21:23 +0530800 // <Get Device ID>
Chris Austen6caf28b2015-10-13 12:40:40 -0500801 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_DEVICE_ID);
Tom05732372016-09-06 17:21:23 +0530802 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_DEVICE_ID, NULL, ipmi_app_get_device_id,
803 PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500804
Tom05732372016-09-06 17:21:23 +0530805 // <Get Self Test Results>
Nan Li41fa24a2016-11-10 20:12:37 +0800806 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_SELF_TEST_RESULTS);
Tom05732372016-09-06 17:21:23 +0530807 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_SELF_TEST_RESULTS, NULL,
808 ipmi_app_get_self_test_results, PRIVILEGE_USER);
Nan Li41fa24a2016-11-10 20:12:37 +0800809
Tom05732372016-09-06 17:21:23 +0530810 // <Get Device GUID>
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500811 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_DEVICE_GUID);
Tom05732372016-09-06 17:21:23 +0530812 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_DEVICE_GUID, NULL, ipmi_app_get_device_guid,
813 PRIVILEGE_USER);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500814
Tom05732372016-09-06 17:21:23 +0530815 // <Set ACPI Power State>
Chris Austen6caf28b2015-10-13 12:40:40 -0500816 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_SET_ACPI);
Tom05732372016-09-06 17:21:23 +0530817 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_ACPI, NULL, ipmi_app_set_acpi_power_state,
818 PRIVILEGE_ADMIN);
Chris Austen6caf28b2015-10-13 12:40:40 -0500819
Tom05732372016-09-06 17:21:23 +0530820 // <Set Channel Access>
Nan Li3d0df912016-10-18 19:51:41 +0800821 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP,
822 IPMI_CMD_SET_CHAN_ACCESS);
823 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHAN_ACCESS, NULL,
Tom05732372016-09-06 17:21:23 +0530824 ipmi_set_channel_access, PRIVILEGE_ADMIN);
Chris Austenc2cd29d2016-02-05 20:02:29 -0600825
Tom Joseph69fabfe2017-08-04 10:15:01 +0530826 // <Get Channel Access>
827 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS);
828 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL,
829 getChannelAccess, PRIVILEGE_USER);
830
Tom05732372016-09-06 17:21:23 +0530831 // <Get Channel Info Command>
Chris Austenc2cd29d2016-02-05 20:02:29 -0600832 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CHAN_INFO);
Tom05732372016-09-06 17:21:23 +0530833 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_INFO, NULL, ipmi_app_channel_info,
834 PRIVILEGE_USER);
Chris Austenc2cd29d2016-02-05 20:02:29 -0600835
vishwabmcba0bd5f2015-09-30 16:50:23 +0530836 return;
837}
838
Chris Austen6caf28b2015-10-13 12:40:40 -0500839