Added new dbus interface to query console info

obmc-console recipe configure consoles by setting the socket-id
field in the console server config file. obmc-console server use this
socket id to build a abract socket name and register new service
"xyz.openbmc_project.Console.Access". The leaf of the object path will
be socket-id configured. It also exposes the unix abstract socket name
through SocketName property. The socket name is sent as a byte stream as
abstract socket contains null character at the start.

*** For example if recipe configured socket-id as "console0" the
*** following object is exported through dbus interface

    # Tree for "console0" console.
    $ busctl tree xyz.openbmc_project.Console.console0
    `-/xyz
      `-/xyz/openbmc_project
        `-/xyz/openbmc_project/console
          `-/xyz/openbmc_project/console/console0

    # Get SocketName property for console0 object
    $ busctl get-property xyz.openbmc_project.Console.console0 /xyz/openbmc_project/console/console0 xyz.openbmc_project.Console.Access SocketName
    ay 22 0 111 98 109 99 45 99 111 110 115 111 108 101 46 99 111 110 115 111 108 101 48

    # Tree for "hypervisor" console
    $ busctl tree xyz.openbmc_project.Console.hypervisor
    `-/xyz
      `-/xyz/openbmc_project
        `-/xyz/openbmc_project/console
          `-/xyz/openbmc_project/console/hypervisor

    # Get SocketName property for hypervisor object
    $ busctl get-property xyz.openbmc_project.Console.hypervisor /xyz/openbmc_project/console/hypervisor xyz.openbmc_project.Console.Access SocketName
    ay 24 0 111 98 109 99 45 99 111 110 115 111 108 101 46 104 121 112 101 114 118 105 115 111 114

    # Note that this is an example of two consoles one is 'console0' and
    # second is 'hypervisor'. I have formated the output to easy viewing.
    # We also have one extra service for console that is coming from the
    # service exist today to get/set the tty device baud rate.
    $ busctl call  xyz.openbmc_project.ObjectMapper \
        /xyz/openbmc_project/object_mapper xyz.openbmc_project.ObjectMapper \
        GetSubTree sias /xyz/openbmc_project/console 0 1 \
        xyz.openbmc_project.Console.Access
    a{sa{sas}}
    2
    "/xyz/openbmc_project/console/console0" \
        1
        "xyz.openbmc_project.Console.console0"
           4 "org.freedesktop.DBus.Introspectable"
             "org.freedesktop.DBus.Peer"
             "org.freedesktop.DBus.Properties"
             "xyz.openbmc_project.Console.Access"
    "/xyz/openbmc_project/console/hypervisor"
        2
        "xyz.openbmc_project.Console.hypervisor"
           4 "org.freedesktop.DBus.Introspectable"
             "org.freedesktop.DBus.Peer"
             "org.freedesktop.DBus.Properties"
             "xyz.openbmc_project.Console.Access"
        "xyz.openbmc_project.console"
          4 "org.freedesktop.DBus.Introspectable"
            "org.freedesktop.DBus.Peer"
            "org.freedesktop.DBus.Properties"
            "xyz.openbmc_project.Console.Access"

Tested:
    Tested on the rainer system with busctl command and integration
    with bmcweb

Related commits:
    1) phosphor-dbus-interface: https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/61486
    2) obmc-console: https://gerrit.openbmc.org/c/openbmc/obmc-console/+/62496
    3) bmcweb: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/62525

Change-Id: Ifb70ce5585c3937f3abd904ffbae51ca67f58724
Signed-off-by: Ninad Palsule <ninadpalsule@us.ibm.com>
diff --git a/console-client.c b/console-client.c
index a9888cd..ea66b22 100644
--- a/console-client.c
+++ b/console-client.c
@@ -227,7 +227,7 @@
 
 	memset(&addr, 0, sizeof(addr));
 	addr.sun_family = AF_UNIX;
-	len = console_socket_path(&addr, socket_id);
+	len = console_socket_path(addr.sun_path, socket_id);
 	if (len < 0) {
 		if (errno) {
 			warn("Failed to configure socket: %s", strerror(errno));
diff --git a/console-dbus.c b/console-dbus.c
index 0672e5b..3b24061 100644
--- a/console-dbus.c
+++ b/console-dbus.c
@@ -22,10 +22,11 @@
 /* size of the dbus object path length */
 const size_t dbus_obj_path_len = 1024;
 
-#define DBUS_ERR  "org.openbmc.error"
-#define INTF_NAME "xyz.openbmc_project.Console"
-#define DBUS_NAME "xyz.openbmc_project.Console.%s"
-#define OBJ_NAME  "/xyz/openbmc_project/console/%s"
+#define DBUS_ERR    "org.openbmc.error"
+#define DBUS_NAME   "xyz.openbmc_project.Console.%s"
+#define OBJ_NAME    "/xyz/openbmc_project/console/%s"
+#define TTY_INTF    "xyz.openbmc_project.console"
+#define ACCESS_INTF "xyz.openbmc_project.Console.Access"
 
 static void tty_change_baudrate(struct console *console)
 {
@@ -101,7 +102,23 @@
 	return r;
 }
 
-static const sd_bus_vtable console_vtable[] = {
+static int get_socket_name(sd_bus *bus __attribute__((unused)),
+			   const char *path __attribute__((unused)),
+			   const char *interface __attribute__((unused)),
+			   const char *property __attribute__((unused)),
+			   sd_bus_message *reply, void *userdata,
+			   sd_bus_error *error __attribute__((unused)))
+{
+	struct console *console = userdata;
+
+	/* The abstract socket name starts with null character hence we need to
+	 * send it as a byte stream instead of regular string.
+	 */
+	return sd_bus_message_append_array(reply, 'y', console->socket_name,
+					   console->socket_name_len);
+}
+
+static const sd_bus_vtable console_tty_vtable[] = {
 	SD_BUS_VTABLE_START(0),
 	SD_BUS_METHOD("setBaudRate", "u", "x", method_set_baud_rate,
 		      SD_BUS_VTABLE_UNPRIVILEGED),
@@ -109,6 +126,12 @@
 	SD_BUS_VTABLE_END,
 };
 
+static const sd_bus_vtable console_access_vtable[] = {
+	SD_BUS_VTABLE_START(0),
+	SD_BUS_PROPERTY("SocketName", "ay", get_socket_name, 0, 0),
+	SD_BUS_VTABLE_END,
+};
+
 void dbus_init(struct console *console,
 	       struct config *config __attribute__((unused)))
 {
@@ -139,8 +162,17 @@
 		return;
 	}
 
-	r = sd_bus_add_object_vtable(console->bus, NULL, obj_name, INTF_NAME,
-				     console_vtable, console);
+	/* Register tty interface */
+	r = sd_bus_add_object_vtable(console->bus, NULL, obj_name, TTY_INTF,
+				     console_tty_vtable, console);
+	if (r < 0) {
+		warnx("Failed to issue method call: %s", strerror(-r));
+		return;
+	}
+
+	/* Register access interface */
+	r = sd_bus_add_object_vtable(console->bus, NULL, obj_name, ACCESS_INTF,
+				     console_access_vtable, console);
 	if (r < 0) {
 		warnx("Failed to issue method call: %s", strerror(-r));
 		return;
@@ -154,6 +186,7 @@
 		return;
 	}
 
+	/* Finally register the bus name */
 	r = sd_bus_request_name(console->bus, dbus_name,
 				SD_BUS_NAME_ALLOW_REPLACEMENT |
 					SD_BUS_NAME_REPLACE_EXISTING);
diff --git a/console-server.c b/console-server.c
index d06cc32..f52c719 100644
--- a/console-server.c
+++ b/console-server.c
@@ -34,6 +34,7 @@
 
 #include <sys/types.h>
 #include <sys/time.h>
+#include <sys/socket.h>
 #include <poll.h>
 
 #include "console-server.h"
@@ -302,6 +303,30 @@
 	return write_buf_to_fd(console->tty_fd, data, len);
 }
 
+/* Read console if from config and prepare a socket name */
+static int set_socket_info(struct console *console, struct config *config)
+{
+	ssize_t len;
+
+	console->console_id = config_get_value(config, "socket-id");
+	if (!console->console_id) {
+		warnx("Error: The socket-id is not set in the config file");
+		return EXIT_FAILURE;
+	}
+
+	/* Get the socket name/path */
+	len = console_socket_path(console->socket_name, console->console_id);
+	if (len < 0) {
+		warn("Failed to set socket path: %s", strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	/* Socket name is not a null terminated string hence save the length */
+	console->socket_name_len = len;
+
+	return 0;
+}
+
 static void handlers_init(struct console *console, struct config *config)
 {
 	/* NOLINTBEGIN(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) */
@@ -732,6 +757,10 @@
 		return EXIT_FAILURE;
 	}
 
+	if (set_socket_info(console, config)) {
+		return EXIT_FAILURE;
+	}
+
 	console->tty_kname = config_tty_kname;
 
 	console->console_id = config_get_value(config, "socket-id");
diff --git a/console-server.h b/console-server.h
index 9418e23..d275ad8 100644
--- a/console-server.h
+++ b/console-server.h
@@ -65,15 +65,14 @@
 
 int console_data_out(struct console *console, const uint8_t *data, size_t len);
 
-/* poller API */
-struct poller;
-
 enum poller_ret {
 	POLLER_OK = 0,
 	POLLER_REMOVE,
 	POLLER_EXIT,
 };
 
+typedef char(socket_path_t)[sizeof(((struct sockaddr_un *)NULL)->sun_path)];
+
 typedef enum poller_ret (*poller_event_fn_t)(struct handler *handler,
 					     int revents, void *data);
 typedef enum poller_ret (*poller_timeout_fn_t)(struct handler *handler,
@@ -90,6 +89,10 @@
 	speed_t tty_baud;
 	int tty_fd;
 
+	/* Socket name starts with null character hence we need length */
+	socket_path_t socket_name;
+	ssize_t socket_name_len;
+
 	struct ringbuffer *rb;
 
 	struct handler **handlers;
@@ -111,6 +114,7 @@
 	struct timeval timeout;
 	bool remove;
 };
+
 /* we have two extra entry in the pollfds array for the VUART tty */
 enum internal_pollfds {
 	POLLFD_HOSTTTY = 0,
@@ -197,9 +201,7 @@
 int config_parse_logsize(const char *size_str, size_t *size);
 
 /* socket paths */
-ssize_t console_socket_path(struct sockaddr_un *addr, const char *id);
-
-typedef char(socket_path_t)[sizeof(((struct sockaddr_un *)NULL)->sun_path)];
+ssize_t console_socket_path(socket_path_t path, const char *id);
 ssize_t console_socket_path_readable(const struct sockaddr_un *addr,
 				     size_t addrlen, socket_path_t path);
 
diff --git a/console-socket.c b/console-socket.c
index 792ca62..e78cfe0 100644
--- a/console-socket.c
+++ b/console-socket.c
@@ -27,18 +27,16 @@
 
 #define CONSOLE_SOCKET_PREFIX "obmc-console"
 
-ssize_t console_socket_path(struct sockaddr_un *addr, const char *id)
+/* Build the socket path. */
+ssize_t console_socket_path(socket_path_t sun_path, const char *id)
 {
-	char *sun_path;
 	ssize_t rc;
 
-	sun_path = (char *)addr + sizeof(*addr) - sizeof(addr->sun_path);
-
 	if (id) {
-		rc = snprintf(sun_path + 1, sizeof(addr->sun_path) - 1,
+		rc = snprintf(sun_path + 1, sizeof(socket_path_t) - 1,
 			      CONSOLE_SOCKET_PREFIX ".%s", id);
 	} else {
-		rc = snprintf(sun_path + 1, sizeof(addr->sun_path) - 1,
+		rc = snprintf(sun_path + 1, sizeof(socket_path_t) - 1,
 			      CONSOLE_SOCKET_PREFIX);
 	}
 
@@ -46,7 +44,7 @@
 		return rc;
 	}
 
-	if ((size_t)rc > (sizeof(addr->sun_path) - 1)) {
+	if ((size_t)rc > (sizeof(socket_path_t) - 1)) {
 		errno = 0;
 		return -1;
 	}
diff --git a/socket-handler.c b/socket-handler.c
index 4a53a51..1932b86 100644
--- a/socket-handler.c
+++ b/socket-handler.c
@@ -356,7 +356,8 @@
 
 	memset(&addr, 0, sizeof(addr));
 	addr.sun_family = AF_UNIX;
-	len = console_socket_path(&addr, config_get_value(config, "socket-id"));
+	len = console_socket_path(addr.sun_path,
+				  config_get_value(config, "socket-id"));
 	if (len < 0) {
 		if (errno) {
 			warn("Failed to configure socket: %s", strerror(errno));