char * virSystemdGetMachineNameByPID(pid_t pid) { DBusConnection *conn; DBusMessage *reply = NULL; char *name = NULL, *object = NULL; if (virSystemdHasMachined() < 0) goto cleanup; if (!(conn = virDBusGetSystemBus())) goto cleanup; if (virDBusCallMethod(conn, &reply, NULL, "org.freedesktop.machine1", "/org/freedesktop/machine1", "org.freedesktop.machine1.Manager", "GetMachineByPID", "u", pid) < 0) goto cleanup; if (virDBusMessageDecode(reply, "o", &object) < 0) goto cleanup; virDBusMessageUnref(reply); reply = NULL; VIR_DEBUG("Domain with pid %lld has object path '%s'", (long long) pid, object); if (virDBusCallMethod(conn, &reply, NULL, "org.freedesktop.machine1", object, "org.freedesktop.DBus.Properties", "Get", "ss", "org.freedesktop.machine1.Machine", "Name") < 0) goto cleanup; if (virDBusMessageDecode(reply, "v", "s", &name) < 0) goto cleanup; VIR_DEBUG("Domain with pid %lld has machine name '%s'", (long long) pid, name); cleanup: VIR_FREE(object); virDBusMessageUnref(reply); return name; }
VIR_MOCK_WRAP_RET_ARGS(dbus_connection_send_with_reply_and_block, DBusMessage *, DBusConnection *, connection, DBusMessage *, message, int, timeout_milliseconds, DBusError *, error) { DBusMessage *reply = NULL; const char *service = dbus_message_get_destination(message); const char *member = dbus_message_get_member(message); size_t i; size_t nargs = 0; char **args = NULL; char *type = NULL; VIR_MOCK_REAL_INIT(dbus_connection_send_with_reply_and_block); if (STREQ(service, "org.freedesktop.DBus") && STREQ(member, "ListNames")) { const char *svc1 = "org.foo.bar.wizz"; const char *svc2 = VIR_FIREWALL_FIREWALLD_SERVICE; DBusMessageIter iter; DBusMessageIter sub; reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); dbus_message_iter_init_append(reply, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub); if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &svc1)) goto error; if (!fwDisabled && !dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &svc2)) goto error; dbus_message_iter_close_container(&iter, &sub); } else if (STREQ(service, VIR_FIREWALL_FIREWALLD_SERVICE) && STREQ(member, "passthrough")) { bool isAdd = false; bool doError = false; if (virDBusMessageDecode(message, "sa&s", &type, &nargs, &args) < 0) goto error; for (i = 0; i < nargs; i++) { /* Fake failure on the command with this IP addr */ if (STREQ(args[i], "-A")) { isAdd = true; } else if (isAdd && STREQ(args[i], "192.168.122.255")) { doError = true; } } if (fwBuf) { if (STREQ(type, "ipv4")) virBufferAddLit(fwBuf, IPTABLES_PATH); else if (STREQ(type, "ipv4")) virBufferAddLit(fwBuf, IP6TABLES_PATH); else virBufferAddLit(fwBuf, EBTABLES_PATH); } for (i = 0; i < nargs; i++) { if (fwBuf) { virBufferAddLit(fwBuf, " "); virBufferEscapeShell(fwBuf, args[i]); } } if (fwBuf) virBufferAddLit(fwBuf, "\n"); if (doError) { dbus_set_error_const(error, "org.firewalld.error", "something bad happened"); } else { if (nargs == 1 && STREQ(type, "ipv4") && STREQ(args[0], "-L")) { if (virDBusCreateReply(&reply, "s", TEST_FILTER_TABLE_LIST) < 0) goto error; } else if (nargs == 3 && STREQ(type, "ipv4") && STREQ(args[0], "-t") && STREQ(args[1], "nat") && STREQ(args[2], "-L")) { if (virDBusCreateReply(&reply, "s", TEST_NAT_TABLE_LIST) < 0) goto error; } else { if (virDBusCreateReply(&reply, "s", "success") < 0) goto error; } } } else { reply = dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN); } cleanup: VIR_FREE(type); for (i = 0; i < nargs; i++) VIR_FREE(args[i]); VIR_FREE(args); return reply; error: virDBusMessageUnref(reply); reply = NULL; if (error && !dbus_error_is_set(error)) dbus_set_error_const(error, "org.firewalld.error", "something unexpected happened"); goto cleanup; }
void virSystemdNotifyStartup(void) { #ifdef HAVE_SYS_UN_H const char *path; const char *msg = "READY=1"; int fd; struct sockaddr_un un = { .sun_family = AF_UNIX, }; struct iovec iov = { .iov_base = (char *)msg, .iov_len = strlen(msg), }; struct msghdr mh = { .msg_name = &un, .msg_iov = &iov, .msg_iovlen = 1, }; if (!(path = virGetEnvBlockSUID("NOTIFY_SOCKET"))) { VIR_DEBUG("Skipping systemd notify, not requested"); return; } /* NB sun_path field is *not* NUL-terminated, hence >, not >= */ if (strlen(path) > sizeof(un.sun_path)) { VIR_WARN("Systemd notify socket path '%s' too long", path); return; } memcpy(un.sun_path, path, strlen(path)); if (un.sun_path[0] == '@') un.sun_path[0] = '\0'; mh.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(path); fd = socket(AF_UNIX, SOCK_DGRAM, 0); if (fd < 0) { VIR_WARN("Unable to create socket FD"); return; } if (sendmsg(fd, &mh, MSG_NOSIGNAL) < 0) VIR_WARN("Failed to notify systemd"); VIR_FORCE_CLOSE(fd); #endif /* HAVE_SYS_UN_H */ } static int virSystemdPMSupportTarget(const char *methodName, bool *result) { int ret; DBusConnection *conn; DBusMessage *message = NULL; char *response; ret = virDBusIsServiceEnabled("org.freedesktop.login1"); if (ret < 0) return ret; if ((ret = virDBusIsServiceRegistered("org.freedesktop.login1")) < 0) return ret; if (!(conn = virDBusGetSystemBus())) return -1; ret = -1; if (virDBusCallMethod(conn, &message, NULL, "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", methodName, NULL) < 0) return ret; if ((ret = virDBusMessageDecode(message, "s", &response)) < 0) goto cleanup; *result = STREQ("yes", response) || STREQ("challenge", response); ret = 0; cleanup: virDBusMessageUnref(message); VIR_FREE(response); return ret; } int virSystemdCanSuspend(bool *result) { return virSystemdPMSupportTarget("CanSuspend", result); } int virSystemdCanHibernate(bool *result) { return virSystemdPMSupportTarget("CanHibernate", result); } int virSystemdCanHybridSleep(bool *result) { return virSystemdPMSupportTarget("CanHybridSleep", result); }