//------------------------------------------------------ // Callback register function // ----------------------------------------------------- void register_host_services() { // Gets a hook onto SYSTEM bus used by host-ipmid sd_bus *bus = ipmid_get_sd_bus_connection(); // Gets a hook onto SYSTEM bus slot used by host-ipmid sd_bus_slot *ipmid_slot = ipmid_get_sd_bus_slot(); //start_host_service(bus, ipmid_slot); start_host_service(bus, ipmid_slot); }
int dbus_set_property(const char * name, const char *value) { sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus_message *m = NULL; sd_bus *bus = NULL; char *connection = NULL; int r; r = object_mapper_get_connection(&connection, settings_object_name); if (r < 0) { fprintf(stderr, "Failed to get connection, return value: %d.\n", r); goto finish; } printf("connection: %s\n", connection); // Get the system bus where most system services are provided. bus = ipmid_get_sd_bus_connection(); /* * Bus, service, object path, interface and method are provided to call * the method. * Signatures and input arguments are provided by the arguments at the * end. */ r = sd_bus_call_method(bus, connection, /* service to contact */ settings_object_name, /* object path */ settings_intf_name, /* interface name */ "Set", /* method name */ &error, /* object to return error in */ &m, /* return message on success */ "ssv", /* input signature */ host_intf_name, /* first argument */ name, /* second argument */ "s", /* third argument */ value); /* fourth argument */ if (r < 0) { fprintf(stderr, "Failed to issue method call: %s\n", error.message); goto finish; } printf("IPMID boot option property set: {%s}.\n", value); finish: sd_bus_error_free(&error); sd_bus_message_unref(m); free(connection); return r; }
//------------------------------------------------------------ // Calls into Chassis Control Dbus object to do the power off //------------------------------------------------------------ int ipmi_chassis_power_control(const char *method) { // sd_bus error int rc = 0; // SD Bus error report mechanism. sd_bus_error bus_error = SD_BUS_ERROR_NULL; // Response from the call. Although there is no response for this call, // obligated to mention this to make compiler happy. sd_bus_message *response = NULL; // Gets a hook onto either a SYSTEM or SESSION bus sd_bus *bus_type = ipmid_get_sd_bus_connection(); rc = sd_bus_call_method(bus_type, // On the System Bus chassis_bus_name, // Service to contact chassis_object_name, // Object path chassis_intf_name, // Interface name method, // Method to be called &bus_error, // object to return error &response, // Response buffer if any NULL); // No input arguments if(rc < 0) { fprintf(stderr,"ERROR initiating Power Off:[%s]\n",bus_error.message); } else { printf("Chassis Power Off initiated successfully\n"); } sd_bus_error_free(&bus_error); sd_bus_message_unref(response); return rc; }
// Helper Function to get IP Address/NetMask/Gateway from Network Manager or Cache // based on Set-In-Progress State ipmi_ret_t getNetworkData(uint8_t lan_param, uint8_t * data) { sd_bus *bus = ipmid_get_sd_bus_connection(); sd_bus_message *reply = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; int family; unsigned char prefixlen; char* ipaddr = NULL; unsigned long mask = 0xFFFFFFFF; char* gateway = NULL; int r = 0; ipmi_ret_t rc = IPMI_CC_OK; r = sd_bus_call_method(bus, app, obj, ifc, "GetAddress4", &error, &reply, "s", nwinterface); if(r < 0) { fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); rc = IPMI_CC_UNSPECIFIED_ERROR; goto cleanup; } r = sd_bus_message_read(reply, "iyss", &family, &prefixlen, &ipaddr, &gateway); if(r < 0) { fprintf(stderr, "Failed to get a response: %s\n", strerror(-rc)); rc = IPMI_CC_RESPONSE_ERROR; goto cleanup; } printf("N/W data from HW %s:%d:%s:%s\n", family==AF_INET?"IPv4":"IPv6", prefixlen, ipaddr,gateway); printf("N/W data from Cache: %s:%s:%s\n", new_ipaddr, new_netmask, new_gateway); if(lan_param == LAN_PARM_IP) { if(lan_set_in_progress == SET_COMPLETE) { std::string ipaddrstr(ipaddr); inet_pton(AF_INET, ipaddrstr.c_str(),(void *)data); } else if(lan_set_in_progress == SET_IN_PROGRESS) { inet_pton(AF_INET, new_ipaddr, (void *)data); } } else if(lan_param == LAN_PARM_SUBNET) { if(lan_set_in_progress == SET_COMPLETE) { mask = htonl(mask<<(32-prefixlen)); memcpy(data, &mask, 4); } else if(lan_set_in_progress == SET_IN_PROGRESS) { inet_pton(AF_INET, new_netmask, (void *)data); } } else if(lan_param == LAN_PARM_GATEWAY) { if(lan_set_in_progress == SET_COMPLETE) { std::string gatewaystr(gateway); inet_pton(AF_INET, gatewaystr.c_str(), (void *)data); } else if(lan_set_in_progress == SET_IN_PROGRESS) { inet_pton(AF_INET, new_gateway,(void *)data); } } else { rc = IPMI_CC_PARM_OUT_OF_RANGE; } cleanup: sd_bus_error_free(&error); reply = sd_bus_message_unref(reply); return rc; }
ipmi_ret_t ipmi_transport_get_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context) { ipmi_ret_t rc = IPMI_CC_OK; *data_len = 0; sd_bus *bus = ipmid_get_sd_bus_connection(); sd_bus_message *reply = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; int r = 0; const uint8_t current_revision = 0x11; // Current rev per IPMI Spec 2.0 int i = 0; printf("IPMI GET_LAN\n"); get_lan_t *reqptr = (get_lan_t*) request; if (reqptr->rev_channel & 0x80) // Revision is bit 7 { // Only current revision was requested *data_len = sizeof(current_revision); memcpy(response, ¤t_revision, *data_len); return IPMI_CC_OK; } // TODO Use dbus interface once available. For now use ip cmd. // TODO Add the rest of the parameters, like gateway if (reqptr->parameter == LAN_PARM_INPROGRESS) { uint8_t buf[] = {current_revision, lan_set_in_progress}; *data_len = sizeof(buf); memcpy(response, &buf, *data_len); } else if (reqptr->parameter == LAN_PARM_AUTHSUPPORT) { uint8_t buf[] = {current_revision,0x04}; *data_len = sizeof(buf); memcpy(response, &buf, *data_len); } else if (reqptr->parameter == LAN_PARM_AUTHENABLES) { uint8_t buf[] = {current_revision,0x04,0x04,0x04,0x04,0x04}; *data_len = sizeof(buf); memcpy(response, &buf, *data_len); } else if ((reqptr->parameter == LAN_PARM_IP) || (reqptr->parameter == LAN_PARM_SUBNET) || (reqptr->parameter == LAN_PARM_GATEWAY)) { uint8_t buf[5]; *data_len = sizeof(current_revision); memcpy(buf, ¤t_revision, *data_len); if(getNetworkData(reqptr->parameter, &buf[1]) == IPMI_CC_OK) { *data_len = sizeof(buf); memcpy(response, &buf, *data_len); } else { rc = IPMI_CC_UNSPECIFIED_ERROR; } } else if (reqptr->parameter == LAN_PARM_MAC) { //string to parse: link/ether xx:xx:xx:xx:xx:xx uint8_t buf[7]; char *eaddr1 = NULL; r = sd_bus_call_method(bus, app, obj, ifc, "GetHwAddress", &error, &reply, "s", nwinterface); if(r < 0) { fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); rc = IPMI_CC_UNSPECIFIED_ERROR; goto cleanup; } r = sd_bus_message_read(reply, "s", &eaddr1); if (r < 0) { fprintf(stderr, "Failed to get a response: %s", strerror(-r)); rc = IPMI_CC_UNSPECIFIED_ERROR; goto cleanup; } if (eaddr1 == NULL) { fprintf(stderr, "Failed to get a valid response: %s", strerror(-r)); rc = IPMI_CC_UNSPECIFIED_ERROR; goto cleanup; } memcpy((void*)&buf[0], ¤t_revision, 1); char *tokptr = NULL; char* digit = strtok_r(eaddr1, ":", &tokptr); if (digit == NULL) { fprintf(stderr, "Unexpected MAC format: %s", eaddr1); rc = IPMI_CC_RESPONSE_ERROR; goto cleanup; } i=0; while (digit != NULL) { int resp_byte = strtoul(digit, NULL, 16); memcpy((void*)&buf[i+1], &resp_byte, 1); i++; digit = strtok_r(NULL, ":", &tokptr); } *data_len = sizeof(buf); memcpy(response, &buf, *data_len); } else { fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); rc = IPMI_CC_PARM_NOT_SUPPORTED; } cleanup: sd_bus_error_free(&error); reply = sd_bus_message_unref(reply); return rc; }
ipmi_ret_t ipmi_transport_set_lan(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context) { ipmi_ret_t rc = IPMI_CC_OK; *data_len = 0; sd_bus *bus = ipmid_get_sd_bus_connection(); sd_bus_message *reply = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; int r = 0; printf("IPMI SET_LAN\n"); set_lan_t *reqptr = (set_lan_t*) request; // TODO Use dbus interface once available. For now use cmd line. // TODO Add the rest of the parameters like setting auth type // TODO Add error handling if (reqptr->parameter == LAN_PARM_IP) { snprintf(new_ipaddr, INET_ADDRSTRLEN, "%d.%d.%d.%d", reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); } else if (reqptr->parameter == LAN_PARM_MAC) { char mac[SIZE_MAC]; snprintf(mac, SIZE_MAC, "%02x:%02x:%02x:%02x:%02x:%02x", reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3], reqptr->data[4], reqptr->data[5]); r = sd_bus_call_method(bus, app, obj, ifc, "SetHwAddress", &error, &reply, "ss", nwinterface, mac); if(r < 0) { fprintf(stderr, "Failed to call the method: %s\n", strerror(-r)); rc = IPMI_CC_UNSPECIFIED_ERROR; } } else if (reqptr->parameter == LAN_PARM_SUBNET) { snprintf(new_netmask, INET_ADDRSTRLEN, "%d.%d.%d.%d", reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); } else if (reqptr->parameter == LAN_PARM_GATEWAY) { snprintf(new_gateway, INET_ADDRSTRLEN, "%d.%d.%d.%d", reqptr->data[0], reqptr->data[1], reqptr->data[2], reqptr->data[3]); } else if (reqptr->parameter == LAN_PARM_INPROGRESS) { if(reqptr->data[0] == SET_COMPLETE) // Set Complete { lan_set_in_progress = SET_COMPLETE; // Apply the IP settings once IP Address, Netmask and Gateway is set if (!strcmp(new_ipaddr, "") || !strcmp (new_netmask, "") || !strcmp (new_gateway, "")) { printf("ERROR: Incomplete LAN Parameters\n"); } else { r = sd_bus_call_method(bus, // On the System Bus app, // Service to contact obj, // Object path ifc, // Interface name "SetAddress4", // Method to be called &error, // object to return error &reply, // Response message on success "ssss", // input message (Interface, IP Address, Netmask, Gateway) nwinterface, // eth0 new_ipaddr, new_netmask, new_gateway); if(r < 0) { fprintf(stderr, "Failed to set network data %s:%s:%s %s\n", new_ipaddr, new_netmask, new_gateway, error.message); rc = IPMI_CC_UNSPECIFIED_ERROR; } memset(new_ipaddr, 0, INET_ADDRSTRLEN); memset(new_netmask, 0, INET_ADDRSTRLEN); memset(new_gateway, 0, INET_ADDRSTRLEN); } } else if(reqptr->data[0] == SET_IN_PROGRESS) // Set In Progress { lan_set_in_progress = SET_IN_PROGRESS; } } else { fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter); rc = IPMI_CC_PARM_NOT_SUPPORTED; } sd_bus_error_free(&error); reply = sd_bus_message_unref(reply); return rc; }
int object_mapper_get_connection(char **buf, const char *obj_path) { sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus_message *m = NULL; sd_bus *bus = NULL; char *temp_buf = NULL, *intf = NULL; size_t buf_size = 0; int r; // Get the system bus where most system services are provided. bus = ipmid_get_sd_bus_connection(); /* * Bus, service, object path, interface and method are provided to call * the method. * Signatures and input arguments are provided by the arguments at the * end. */ r = sd_bus_call_method(bus, objmapper_service_name, /* service to contact */ objmapper_object_name, /* object path */ objmapper_intf_name, /* interface name */ "GetObject", /* method name */ &error, /* object to return error in */ &m, /* return message on success */ "s", /* input signature */ obj_path /* first argument */ ); if (r < 0) { fprintf(stderr, "Failed to issue method call: %s\n", error.message); goto finish; } // Get the key, aka, the connection name sd_bus_message_read(m, "a{sas}", 1, &temp_buf, 1, &intf); /* * TODO: check the return code. Currently for no reason the message * parsing of object mapper is always complaining about * "Device or resource busy", but the result seems OK for now. Need * further checks. * TODO: The following code is preserved in the comments so that it can be * resumed after the problem aforementioned is resolved. *r = sd_bus_message_read(m, "a{sas}", 1, &temp_buf, 1, &intf); *if (r < 0) { * fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r)); * goto finish; *} */ buf_size = strlen(temp_buf) + 1; printf("IPMID connection name: %s\n", temp_buf); *buf = (char *)malloc(buf_size); if (*buf == NULL) { fprintf(stderr, "Malloc failed for get_sys_boot_options"); r = -1; goto finish; } memcpy(*buf, temp_buf, buf_size); finish: sd_bus_error_free(&error); sd_bus_message_unref(m); return r; }
int dbus_get_property(const char *name, char **buf) { sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus_message *m = NULL; sd_bus *bus = NULL; char *temp_buf = NULL; char *connection = NULL; int r; r = object_mapper_get_connection(&connection, settings_object_name); if (r < 0) { fprintf(stderr, "Failed to get connection, return value: %d.\n", r); goto finish; } printf("connection: %s\n", connection); // Get the system bus where most system services are provided. bus = ipmid_get_sd_bus_connection(); /* * Bus, service, object path, interface and method are provided to call * the method. * Signatures and input arguments are provided by the arguments at the * end. */ r = sd_bus_call_method(bus, connection, /* service to contact */ settings_object_name, /* object path */ settings_intf_name, /* interface name */ "Get", /* method name */ &error, /* object to return error in */ &m, /* return message on success */ "ss", /* input signature */ host_intf_name, /* first argument */ name); /* second argument */ if (r < 0) { fprintf(stderr, "Failed to issue method call: %s\n", error.message); goto finish; } /* * The output should be parsed exactly the same as the output formatting * specified. */ r = sd_bus_message_read(m, "v", "s", &temp_buf); if (r < 0) { fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r)); goto finish; } asprintf(buf, "%s", temp_buf); /* *buf = (char*) malloc(strlen(temp_buf)); if (*buf) { strcpy(*buf, temp_buf); } */ printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf); finish: sd_bus_error_free(&error); sd_bus_message_unref(m); free(connection); return r; }
//------------------------------------------------------------------- // Gets called by PowerOff handler when a Soft Power off is requested //------------------------------------------------------------------- static int soft_power_off(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { int64_t bt_resp = -1; int rc = 0; char *bus_name = NULL; // Steps to be taken when we get this. // 1: Send a SMS_ATN to the Host // 2: Host receives it and sends a GetMsgFlags IPMI command // 3: IPMID app handler will respond to that with a MSgFlag with bit:0x2 // set indicating we have a message for Host // 4: Host sends a GetMsgBuffer command and app handler will respond to // that with a OEM-SEL with certain fields packed indicating to the // host that it do a shutdown of the partitions. // 5: Host does the partition shutdown and calls Chassis Power off command // 6: App handler handles the command by making a call to ChassisManager // Dbus // Now the job is to send the SMS_ATTN. // Req message contains the specifics about which method etc that we want to // access on which bus, object sd_bus_message *response = NULL; // Error return mechanism sd_bus_error bus_error = SD_BUS_ERROR_NULL; // Gets a hook onto either a SYSTEM or SESSION bus sd_bus *bus = ipmid_get_sd_bus_connection(); rc = mapper_get_service(bus, object_name, &bus_name); if (rc < 0) { fprintf(stderr, "Failed to get %s bus name: %s\n", object_name, strerror(-rc)); goto finish; } rc = sd_bus_call_method(bus, // In the System Bus bus_name, // Service to contact object_name, // Object path intf_name, // Interface name "setAttention", // Method to be called &bus_error, // object to return error &response, // Response buffer if any NULL); // No input arguments if(rc < 0) { fprintf(stderr,"ERROR initiating Power Off:[%s]\n",bus_error.message); goto finish; } // See if we were able to successfully raise SMS_ATN rc = sd_bus_message_read(response, "x", &bt_resp); if (rc < 0) { fprintf(stderr, "Failed to get a rc from BT for SMS_ATN: %s\n", strerror(-rc)); goto finish; } finish: sd_bus_error_free(&bus_error); response = sd_bus_message_unref(response); free(bus_name); if(rc < 0) { return sd_bus_reply_method_return(m, "x", rc); } else { return sd_bus_reply_method_return(m, "x", bt_resp); } }
ipmi_ret_t ipmi_sen_get_sensor_reading(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request, ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context) { sensor_data_t *reqptr = (sensor_data_t*)request; ipmi_ret_t rc = IPMI_CC_SENSOR_INVALID; uint8_t type; sensorreadingresp_t *resp = (sensorreadingresp_t*) response; int r; dbus_interface_t a; sd_bus *bus = ipmid_get_sd_bus_connection(); sd_bus_message *reply = NULL; int reading = 0; printf("IPMI GET_SENSOR_READING [0x%02x]\n",reqptr->sennum); r = find_openbmc_path("SENSOR", reqptr->sennum, &a); if (r < 0) { fprintf(stderr, "Failed to find Sensor 0x%02x\n", reqptr->sennum); return IPMI_CC_SENSOR_INVALID; } type = find_sensor(reqptr->sennum); fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", a.bus, a.path, a.interface); *data_len=0; switch(type) { case 0xC3: case 0xC2: r = sd_bus_get_property(bus,a.bus, a.path, a.interface, "value", NULL, &reply, "i"); if (r < 0) { fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r)); fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n", a.bus, a.path, a.interface); break; } r = sd_bus_message_read(reply, "i", &reading); if (r < 0) { fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r)); break; } printf("Contents of a 0x%02x is 0x%02x\n", type, reading); rc = IPMI_CC_OK; *data_len=sizeof(sensorreadingresp_t); resp->value = (uint8_t)reading; resp->operation = 0; resp->indication[0] = 0; resp->indication[1] = 0; break; default: *data_len=0; rc = IPMI_CC_SENSOR_INVALID; break; } reply = sd_bus_message_unref(reply); return rc; }
//------------------------------------------------------------------------ // Takes FRU data, invokes Parser for each fru record area and updates // Inventory //------------------------------------------------------------------------ int ipmi_update_inventory(const uint8_t fruid, const uint8_t *fru_data, fru_area_vec_t & area_vec) { // Now, use this fru dictionary object and connect with FRU Inventory Dbus // and update the data for this FRU ID. int rc = 0; // Dictionary object to hold Name:Value pair sd_bus_message *fru_dict = NULL; // SD Bus error report mechanism. sd_bus_error bus_error = SD_BUS_ERROR_NULL; // Gets a hook onto either a SYSTEM or SESSION bus sd_bus *bus_type = ipmid_get_sd_bus_connection(); // Req message contains the specifics about which method etc that we want to // access on which bus, object sd_bus_message *response = NULL; // For each FRU area, extract the needed data , get it parsed and update // the Inventory. for(auto& iter : area_vec) { uint8_t area_type = (iter).type; uint8_t area_data[(iter).len]; memset(area_data, 0x0, sizeof(area_data)); // Grab area specific data memmove(area_data, (iter).offset, (iter).len); // Need this to get respective DBUS objects const char *area_name = NULL; if(area_type == IPMI_FRU_AREA_CHASSIS_INFO) { area_name = "CHASSIS_"; } else if(area_type == IPMI_FRU_AREA_BOARD_INFO) { area_name = "BOARD_"; } else if(area_type == IPMI_FRU_AREA_PRODUCT_INFO) { area_name = "PRODUCT_"; } else { fprintf(stderr, "ERROR: Invalid Area type :[%d]",area_type); break; } // What we need is BOARD_1, PRODUCT_1, CHASSIS_1 etc.. char fru_area_name[16] = {0}; sprintf(fru_area_name,"%s%d",area_name, fruid); #ifdef __IPMI_DEBUG__ printf("Updating Inventory with :[%s]\n",fru_area_name); #endif // Each area needs a clean set. sd_bus_error_free(&bus_error); sd_bus_message_unref(response); sd_bus_message_unref(fru_dict); // We want to call a method "getObjectFromId" on System Bus that is // made available over OpenBmc system services. rc = sd_bus_call_method(bus_type, // On the System Bus bus_name, // Service to contact object_name, // Object path intf_name, // Interface name "getObjectFromId", // Method to be called &bus_error, // object to return error &response, // Response message on success "ss", // input message (string,byte) "FRU_STR", // First argument to getObjectFromId fru_area_name); // Second Argument if(rc < 0) { fprintf(stderr, "Failed to issue method call: %s\n", bus_error.message); break; } // Method getObjectFromId returns 3 parameters and all are strings, namely // bus_name , object_path and interface name for accessing that particular // FRU over Inventory SDBUS manager. 'sss' here mentions that format. char *inv_bus_name, *inv_obj_path, *inv_intf_name; rc = sd_bus_message_read(response, "(sss)", &inv_bus_name, &inv_obj_path, &inv_intf_name); if(rc < 0) { fprintf(stderr, "Failed to parse response message:[%s]\n", strerror(-rc)); break; } #ifdef __IPMI_DEBUG__ printf("fru_area=[%s], inv_bus_name=[%s], inv_obj_path=[%s],inv_intf_name=[%s]\n", fru_area_name, inv_bus_name, inv_obj_path, inv_intf_name); #endif // Constructor to allow further initializations and customization. rc = sd_bus_message_new_method_call(bus_type, &fru_dict, inv_bus_name, inv_obj_path, inv_intf_name, "update"); if(rc < 0) { fprintf(stderr,"ERROR: creating a update method call\n"); break; } // A Dictionary ({}) having (string, variant) rc = sd_bus_message_open_container(fru_dict, 'a', "{sv}"); if(rc < 0) { fprintf(stderr,"ERROR:[%d] creating a dict container:\n",errno); break; } // Fill the container with information rc = parse_fru_area((iter).type, (void *)area_data, (iter).len, fru_dict); if(rc < 0) { fprintf(stderr,"ERROR parsing FRU records\n"); break; } sd_bus_message_close_container(fru_dict); // Now, Make the actual call to update the FRU inventory database with the // dictionary given by FRU Parser. There is no response message expected for // this. rc = sd_bus_call(bus_type, // On the System Bus fru_dict, // With the Name:value dictionary array 0, // &bus_error, // Object to return error. &response); // Response message if any. if(rc < 0) { fprintf(stderr, "ERROR:[%s] updating FRU inventory for ID:[0x%X]\n", bus_error.message, fruid); } else { printf("SUCCESS: Updated:[%s] successfully\n",fru_area_name); } } // END walking the vector of areas and updating sd_bus_error_free(&bus_error); sd_bus_message_unref(response); sd_bus_message_unref(fru_dict); sd_bus_unref(bus_type); return rc; }