Ed Tanous | fe41c38 | 2019-01-11 16:26:13 -0800 | [diff] [blame] | 1 | From 7a74bdc8d1b0b32c35dc83e130f687a52dfda1e8 Mon Sep 17 00:00:00 2001 |
| 2 | From: Jeremy Kerr <jk@ozlabs.org> |
| 3 | Date: Tue, 13 Oct 2015 09:17:21 +0800 |
| 4 | Subject: [PATCH] plugins: Add a backend for the OpenBMC dbus interface |
| 5 | |
| 6 | Signed-off-by: Jeremy Kerr <jk@ozlabs.org> |
| 7 | |
| 8 | Includes the following commits from the following authors |
| 9 | |
| 10 | plugins/dbus: Split netfn from lun, and ccode from data |
| 11 | |
| 12 | Signed-off-by: Jeremy Kerr <jk@ozlabs.org> |
| 13 | |
| 14 | plugins/dbus: fix missing semicolon |
| 15 | |
| 16 | Reported-by: Chris Austen <austenc@us.ibm.com> |
| 17 | |
| 18 | Signed-off-by: Jeremy Kerr <jk@ozlabs.org> |
| 19 | |
| 20 | plugins/dbus: Fix ccode response |
| 21 | |
| 22 | We need to copy it in from the dbus reply. |
| 23 | |
| 24 | Signed-off-by: Jeremy Kerr <jk@ozlabs.org> |
| 25 | |
| 26 | plugins/dbus: Use default dbus connection |
| 27 | |
| 28 | ... so we'll use the system bus if run as UID 0. |
| 29 | |
| 30 | Signed-off-by: Jeremy Kerr <jk@ozlabs.org> |
| 31 | |
| 32 | if no interface is specified, use the dbus interface by default |
| 33 | |
| 34 | This is a patch that should only be on openbmc, not sent upstream |
| 35 | because the dbus interface is really only an openbmc thing. |
| 36 | |
| 37 | Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com> |
| 38 | --- |
| 39 | configure.ac | 19 ++++ |
| 40 | src/plugins/Makefile.am | 4 +- |
| 41 | src/plugins/dbus/Makefile.am | 41 ++++++++ |
| 42 | src/plugins/dbus/dbus.c | 199 +++++++++++++++++++++++++++++++++++ |
| 43 | src/plugins/ipmi_intf.c | 6 ++ |
| 44 | 5 files changed, 267 insertions(+), 2 deletions(-) |
| 45 | create mode 100644 src/plugins/dbus/Makefile.am |
| 46 | create mode 100644 src/plugins/dbus/dbus.c |
| 47 | |
| 48 | diff --git a/configure.ac b/configure.ac |
| 49 | index f2fe1f3..81cc925 100644 |
| 50 | --- a/configure.ac |
| 51 | +++ b/configure.ac |
| 52 | @@ -60,6 +60,7 @@ xenable_all_options=yes |
| 53 | xenable_intf_bmc=no |
| 54 | xenable_intf_dummy=no |
| 55 | xenable_intf_imb=yes |
| 56 | +xenable_intf_dbus=yes |
| 57 | xenable_intf_lipmi=yes |
| 58 | xenable_intf_open=yes |
| 59 | #xenable_intf_serial=yes |
| 60 | @@ -222,6 +223,22 @@ if test "x$xenable_intf_usb" = "xyes"; then |
| 61 | IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB usb/libintf_usb.la" |
| 62 | fi |
| 63 | |
| 64 | +dnl enable IPMI dbus interface |
| 65 | +AC_ARG_ENABLE([intf-dbus], |
| 66 | + [AC_HELP_STRING([--enable-intf-dbus], |
| 67 | + [enable IPMI dbus interface [default=yes]])], |
| 68 | + [xenable_intf_dbus=$enableval], |
| 69 | + [xenable_intf_dbus=yes]) |
| 70 | +if test "x$xenable_intf_dbus" = "xstatic" || test "x$xenable_intf_dbus" = "xplugin"; then |
| 71 | + xenable_intf_dbus=yes |
| 72 | +fi |
| 73 | +if test "x$xenable_intf_dbus" = "xyes"; then |
| 74 | + AC_DEFINE(IPMI_INTF_DBUS, [1], [Define to 1 to enable dbus interface.]) |
| 75 | + AC_SUBST(INTF_DBUS, [dbus]) |
| 76 | + AC_SUBST(INTF_DBUS_LIB, [libintf_dbus.la]) |
| 77 | + IPMITOOL_INTF_LIB="$IPMITOOL_INTF_LIB dbus/libintf_dbus.la" |
| 78 | +fi |
| 79 | + |
| 80 | dnl enable IPMIv2.0 RMCP+ LAN interface |
| 81 | AC_ARG_ENABLE([intf-lanplus], |
| 82 | [AC_HELP_STRING([--enable-intf-lanplus], |
| 83 | @@ -664,6 +681,7 @@ AC_CONFIG_FILES([Makefile |
| 84 | src/plugins/imb/Makefile |
| 85 | src/plugins/bmc/Makefile |
| 86 | src/plugins/usb/Makefile |
| 87 | + src/plugins/dbus/Makefile |
| 88 | src/plugins/lipmi/Makefile |
| 89 | src/plugins/serial/Makefile |
| 90 | src/plugins/dummy/Makefile]) |
| 91 | @@ -681,6 +699,7 @@ AC_MSG_RESULT([ free : $xenable_intf_free]) |
| 92 | AC_MSG_RESULT([ imb : $xenable_intf_imb]) |
| 93 | AC_MSG_RESULT([ bmc : $xenable_intf_bmc]) |
| 94 | AC_MSG_RESULT([ usb : $xenable_intf_usb]) |
| 95 | +AC_MSG_RESULT([ dbus : $xenable_intf_dbus]) |
| 96 | AC_MSG_RESULT([ lipmi : $xenable_intf_lipmi]) |
| 97 | AC_MSG_RESULT([ serial : $xenable_intf_serial]) |
| 98 | AC_MSG_RESULT([ dummy : $xenable_intf_dummy]) |
| 99 | diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am |
| 100 | index 7ad8173..c0b0b29 100644 |
| 101 | --- a/src/plugins/Makefile.am |
| 102 | +++ b/src/plugins/Makefile.am |
| 103 | @@ -32,8 +32,8 @@ MAINTAINERCLEANFILES = Makefile.in |
| 104 | |
| 105 | AM_CPPFLAGS = -I$(top_srcdir)/include |
| 106 | |
| 107 | -SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ @INTF_USB@ |
| 108 | -DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy usb |
| 109 | +SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ @INTF_USB@ @INTF_DBUS@ |
| 110 | +DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy usb dbus |
| 111 | |
| 112 | noinst_LTLIBRARIES = libintf.la |
| 113 | libintf_la_SOURCES = ipmi_intf.c |
| 114 | diff --git a/src/plugins/dbus/Makefile.am b/src/plugins/dbus/Makefile.am |
| 115 | new file mode 100644 |
| 116 | index 0000000..3e92113 |
| 117 | --- /dev/null |
| 118 | +++ b/src/plugins/dbus/Makefile.am |
| 119 | @@ -0,0 +1,41 @@ |
| 120 | + # |
| 121 | + # Copyright (c) 2015 IBM Corporation |
| 122 | + # All rights reserved. |
| 123 | + # |
| 124 | + # Redistribution and use in source and binary forms, with or without |
| 125 | + # modification,are permitted provided that the following conditions are met: |
| 126 | + # |
| 127 | + # 1. Redistributions of source code must retain the above copyright notice, |
| 128 | + # this list of conditions and the following disclaimer. |
| 129 | + # |
| 130 | + # 2. Redistributions in binary form must reproduce the above copyright notice, |
| 131 | + # this list of conditions and the following disclaimer in the documentation |
| 132 | + # and/or other materials provided with the distribution. |
| 133 | + # |
| 134 | + # 3. Neither the name of the copyright holder nor the names of its contributors |
| 135 | + # may be used to endorse or promote products derived from this software |
| 136 | + # without specific prior written permission. |
| 137 | + # |
| 138 | + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 139 | + # AND ANY EXPRESS OR IMPLIED WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE |
| 140 | + # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 141 | + # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| 142 | + # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 143 | + # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 144 | + # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 145 | + # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 146 | + # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 147 | + # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 148 | + # POSSIBILITY OF SUCH DAMAGE. |
| 149 | + # |
| 150 | + |
| 151 | +MAINTAINERCLEANFILES = Makefile.in |
| 152 | + |
| 153 | +INCLUDES = -I$(top_srcdir)/include |
| 154 | + |
| 155 | +EXTRA_LTLIBRARIES = libintf_dbus.la |
| 156 | +noinst_LTLIBRARIES = @INTF_DBUS_LIB@ |
| 157 | +libintf_dbus_la_LDFLAGS = -lsystemd |
| 158 | +libintf_dbus_la_LIBADD = $(top_builddir)/lib/libipmitool.la |
| 159 | +libintf_dbus_la_SOURCES = dbus.c |
| 160 | + |
| 161 | diff --git a/src/plugins/dbus/dbus.c b/src/plugins/dbus/dbus.c |
| 162 | new file mode 100644 |
| 163 | index 0000000..c20545f |
| 164 | --- /dev/null |
| 165 | +++ b/src/plugins/dbus/dbus.c |
| 166 | @@ -0,0 +1,199 @@ |
| 167 | +/* |
| 168 | + * Copyright (c) 2015 IBM Corporation |
| 169 | + * All rights reserved. |
| 170 | + * |
| 171 | + * Redistribution and use in source and binary forms, with or without |
| 172 | + * modification, are permitted provided that the following conditions |
| 173 | + * are met: |
| 174 | + * |
| 175 | + * 1. Redistributions of source code must retain the above copyright notice, |
| 176 | + * this list of conditions and the following disclaimer. |
| 177 | + * |
| 178 | + * 2. Redistributions in binary form must reproduce the above copyright notice, |
| 179 | + * this list of conditions and the following disclaimer in the documentation |
| 180 | + * and/or other materials provided with the distribution. |
| 181 | + * |
| 182 | + * 3. Neither the name of the copyright holder nor the names of its |
| 183 | + * contributors may be used to endorse or promote products derived from this |
| 184 | + * software without specific prior written permission. |
| 185 | + * |
| 186 | + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 187 | + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 188 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 189 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| 190 | + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 191 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 192 | + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 193 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 194 | + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 195 | + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 196 | + * POSSIBILITY OF SUCH DAMAGE. |
| 197 | + */ |
| 198 | + |
| 199 | +#define _BSD_SOURCE |
| 200 | + |
| 201 | +#include <sys/file.h> |
| 202 | +#include <sys/stat.h> |
| 203 | +#include <sys/types.h> |
| 204 | +#include <fcntl.h> |
| 205 | +#include <errno.h> |
| 206 | +#include <unistd.h> |
| 207 | +#include <stdbool.h> |
| 208 | + |
| 209 | +#include <systemd/sd-bus.h> |
| 210 | +#include <systemd/sd-bus-vtable.h> |
| 211 | + |
| 212 | +#include <ipmitool/log.h> |
| 213 | +#include <ipmitool/ipmi.h> |
| 214 | +#include <ipmitool/ipmi_intf.h> |
| 215 | + |
| 216 | +static sd_bus *bus; |
| 217 | +static uint8_t seq; |
| 218 | +static struct ipmi_rs rsp; |
| 219 | +static bool reply_received; |
| 220 | + |
| 221 | +static const char *bus_name = "org.openbmc.HostIpmi.ipmitool"; |
| 222 | +static const char *object_path = "/org/openbmc/HostIpmi/ipmitool"; |
| 223 | +static const char *interface = "org.openbmc.HostIpmi"; |
| 224 | + |
| 225 | +static struct ipmi_rs *ipmi_dbus_sendrecv(struct ipmi_intf *intf, |
| 226 | + struct ipmi_rq *req) |
| 227 | +{ |
| 228 | + sd_bus_message *msg; |
| 229 | + int rc; |
| 230 | + |
| 231 | + (void)intf; |
| 232 | + |
| 233 | + rsp.ccode = 0xff; |
| 234 | + |
| 235 | + rc = sd_bus_message_new_signal(bus, &msg, object_path, |
| 236 | + interface, "ReceivedMessage"); |
| 237 | + if (rc < 0) { |
| 238 | + lprintf(LOG_ERR, "%s: failed to create message: %s\n", |
| 239 | + __func__, strerror(-rc)); |
| 240 | + goto out; |
| 241 | + } |
| 242 | + |
| 243 | + rc = sd_bus_message_append(msg, "yyyy", |
| 244 | + ++seq, |
| 245 | + req->msg.netfn, |
| 246 | + req->msg.lun, |
| 247 | + req->msg.cmd); |
| 248 | + if (rc < 0) { |
| 249 | + lprintf(LOG_ERR, "%s: failed to init bytes\n", __func__); |
| 250 | + goto out_free; |
| 251 | + } |
| 252 | + |
| 253 | + rc = sd_bus_message_append_array(msg, 'y', req->msg.data, |
| 254 | + req->msg.data_len); |
| 255 | + if (rc < 0) { |
| 256 | + lprintf(LOG_ERR, "%s: failed to init body\n", __func__); |
| 257 | + goto out_free; |
| 258 | + } |
| 259 | + |
| 260 | + rc = sd_bus_send(bus, msg, NULL); |
| 261 | + if (rc < 0) { |
| 262 | + lprintf(LOG_ERR, "%s: failed to send dbus message\n", |
| 263 | + __func__); |
| 264 | + goto out_free; |
| 265 | + } |
| 266 | + |
| 267 | + for (reply_received = false; !reply_received;) { |
| 268 | + rc = sd_bus_wait(bus, -1); |
| 269 | + sd_bus_process(bus, NULL); |
| 270 | + } |
| 271 | + |
| 272 | +out_free: |
| 273 | + sd_bus_message_unref(msg); |
| 274 | +out: |
| 275 | + return &rsp; |
| 276 | +} |
| 277 | + |
| 278 | +static int ipmi_dbus_method_send_message(sd_bus_message *msg, void *userdata, |
| 279 | + sd_bus_error *error) |
| 280 | +{ |
| 281 | + uint8_t recv_seq, recv_netfn, recv_lun, recv_cmd, recv_cc; |
| 282 | + const void *data; |
| 283 | + size_t n; |
| 284 | + int rc; |
| 285 | + |
| 286 | + (void)userdata; |
| 287 | + (void)error; |
| 288 | + |
| 289 | + rc = sd_bus_message_read(msg, "yyyyy", &recv_seq, &recv_netfn, |
| 290 | + &recv_lun, &recv_cmd, &recv_cc); |
| 291 | + if (rc < 0) { |
| 292 | + lprintf(LOG_ERR, "%s: failed to read reply\n", __func__); |
| 293 | + goto out; |
| 294 | + } |
| 295 | + |
| 296 | + rc = sd_bus_message_read_array(msg, 'y', &data, &n); |
| 297 | + if (rc < 0) { |
| 298 | + lprintf(LOG_ERR, "%s: failed to read reply data\n", __func__); |
| 299 | + goto out; |
| 300 | + } |
| 301 | + |
| 302 | + if (n > sizeof(rsp.data)) { |
| 303 | + lprintf(LOG_ERR, "%s: data too long!\n", __func__); |
| 304 | + goto out; |
| 305 | + } |
| 306 | + |
| 307 | + if (recv_seq == seq) { |
| 308 | + rsp.ccode = recv_cc; |
| 309 | + rsp.data_len = n; |
| 310 | + memcpy(rsp.data, data, rsp.data_len); |
| 311 | + reply_received = true; |
| 312 | + } |
| 313 | + |
| 314 | +out: |
| 315 | + sd_bus_reply_method_return(msg, "x", 0); |
| 316 | + return 0; |
| 317 | +} |
| 318 | + |
| 319 | +static const sd_bus_vtable dbus_vtable[] = { |
| 320 | + SD_BUS_VTABLE_START(0), |
| 321 | + SD_BUS_SIGNAL("ReceivedMessage", "yyyyay", 0), |
| 322 | + SD_BUS_METHOD("sendMessage", "yyyyyay", "x", |
| 323 | + ipmi_dbus_method_send_message, |
| 324 | + SD_BUS_VTABLE_UNPRIVILEGED), |
| 325 | + SD_BUS_VTABLE_END |
| 326 | +}; |
| 327 | + |
| 328 | +static int ipmi_dbus_setup(struct ipmi_intf *intf) |
| 329 | +{ |
| 330 | + const char *name; |
| 331 | + int rc; |
| 332 | + |
| 333 | + rc = sd_bus_default(&bus); |
| 334 | + if (rc < 0) { |
| 335 | + lprintf(LOG_ERR, "Can't connect to session bus: %s\n", |
| 336 | + strerror(-rc)); |
| 337 | + return -1; |
| 338 | + } |
| 339 | + |
| 340 | + sd_bus_add_object_vtable(bus, NULL, object_path, interface, |
| 341 | + dbus_vtable, NULL); |
| 342 | + |
| 343 | + sd_bus_request_name(bus, bus_name, SD_BUS_NAME_REPLACE_EXISTING); |
| 344 | + |
| 345 | + sd_bus_flush(bus); |
| 346 | + sd_bus_get_unique_name(bus, &name); |
| 347 | + intf->opened = 1; |
| 348 | + |
| 349 | + return 0; |
| 350 | +} |
| 351 | + |
| 352 | +static void ipmi_dbus_close(struct ipmi_intf *intf) |
| 353 | +{ |
| 354 | + if (intf->opened) |
| 355 | + sd_bus_close(bus); |
| 356 | + intf->opened = 0; |
| 357 | +} |
| 358 | + |
| 359 | +struct ipmi_intf ipmi_dbus_intf = { |
| 360 | + .name = "dbus", |
| 361 | + .desc = "OpenBMC dbus interface", |
| 362 | + .setup = ipmi_dbus_setup, |
| 363 | + .close = ipmi_dbus_close, |
| 364 | + .sendrecv = ipmi_dbus_sendrecv, |
| 365 | +}; |
| 366 | diff --git a/src/plugins/ipmi_intf.c b/src/plugins/ipmi_intf.c |
| 367 | index 9225a34..56c2543 100644 |
| 368 | --- a/src/plugins/ipmi_intf.c |
| 369 | +++ b/src/plugins/ipmi_intf.c |
| 370 | @@ -89,8 +89,14 @@ extern struct ipmi_intf ipmi_dummy_intf; |
| 371 | #ifdef IPMI_INTF_USB |
| 372 | extern struct ipmi_intf ipmi_usb_intf; |
| 373 | #endif |
| 374 | +#ifdef IPMI_INTF_DBUS |
| 375 | +extern struct ipmi_intf ipmi_dbus_intf; |
| 376 | +#endif |
| 377 | |
| 378 | struct ipmi_intf * ipmi_intf_table[] = { |
| 379 | +#ifdef IPMI_INTF_DBUS |
| 380 | + &ipmi_dbus_intf, |
| 381 | +#endif |
| 382 | #ifdef IPMI_INTF_OPEN |
| 383 | &ipmi_open_intf, |
| 384 | #endif |
| 385 | -- |
| 386 | 2.17.1 |
| 387 | |