static int bus_append_cgroup_property(sd_bus_message *m, const char *field, const char *eq) {
        int r;

        if (STR_IN_SET(field, "DevicePolicy", "Slice"))

                return bus_append_string(m, field, eq);

        if (STR_IN_SET(field,
                       "CPUAccounting", "MemoryAccounting", "IOAccounting", "BlockIOAccounting",
                       "TasksAccounting", "IPAccounting"))

                return bus_append_parse_boolean(m, field, eq);

        if (STR_IN_SET(field, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight"))

                return bus_append_cg_weight_parse(m, field, eq);

        if (STR_IN_SET(field, "CPUShares", "StartupCPUShares"))

                return bus_append_cg_cpu_shares_parse(m, field, eq);

        if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight"))

                return bus_append_cg_blkio_weight_parse(m, field, eq);

        if (streq(field, "Delegate")) {

                r = parse_boolean(eq);
                if (r < 0)
                        return bus_append_strv(m, "DelegateControllers", eq, EXTRACT_QUOTES);

                r = sd_bus_message_append(m, "(sv)", "Delegate", "b", r);
                if (r < 0)
                        return bus_log_create_error(r);

                return 1;
        }

        if (STR_IN_SET(field, "MemoryMin", "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit", "TasksMax")) {

                if (isempty(eq) || streq(eq, "infinity")) {
                        r = sd_bus_message_append(m, "(sv)", field, "t", CGROUP_LIMIT_MAX);
                        if (r < 0)
                                return bus_log_create_error(r);
                        return 1;
                }

                r = parse_permille(eq);
                if (r >= 0) {
                        char *n;

                        /* When this is a percentage we'll convert this into a relative value in the range 0…UINT32_MAX
                         * and pass it in the MemoryLowScale property (and related ones). This way the physical memory
                         * size can be determined server-side. */

                        n = strjoina(field, "Scale");
                        r = sd_bus_message_append(m, "(sv)", n, "u", (uint32_t) (((uint64_t) r * UINT32_MAX) / 1000U));
                        if (r < 0)
                                return bus_log_create_error(r);

                        return 1;
                }

                if (streq(field, "TasksMax"))
                        return bus_append_safe_atou64(m, field, eq);

                return bus_append_parse_size(m, field, eq, 1024);
        }

        if (streq(field, "CPUQuota")) {

                if (isempty(eq))
                        r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", USEC_INFINITY);
                else {
                        r = parse_permille_unbounded(eq);
                        if (r == 0)
                                return log_error_errno(SYNTHETIC_ERRNO(ERANGE),
                                                       "CPU quota too small.");
                        if (r < 0)
                                return log_error_errno(r, "CPU quota '%s' invalid.", eq);

                        r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", (((uint64_t) r * USEC_PER_SEC) / 1000U));
                }

                if (r < 0)
                        return bus_log_create_error(r);

                return 1;
        }

        if (streq(field, "CPUQuotaPeriodSec")) {
                usec_t u = USEC_INFINITY;

                r = parse_sec_def_infinity(eq, &u);
                if (r < 0)
                        return log_error_errno(r, "CPU quota period '%s' invalid.", eq);

                r = sd_bus_message_append(m, "(sv)", "CPUQuotaPeriodUSec", "t", u);
                if (r < 0)
                        return bus_log_create_error(r);

                return 1;
        }

        if (streq(field, "DeviceAllow")) {

                if (isempty(eq))
                        r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 0);
                else {
                        const char *path = eq, *rwm = NULL, *e;

                        e = strchr(eq, ' ');
                        if (e) {
                                path = strndupa(eq, e - eq);
                                rwm = e+1;
                        }

                        r = sd_bus_message_append(m, "(sv)", field, "a(ss)", 1, path, strempty(rwm));
                }

                if (r < 0)
                        return bus_log_create_error(r);

                return 1;
        }

        if (cgroup_io_limit_type_from_string(field) >= 0 || STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {

                if (isempty(eq))
                        r = sd_bus_message_append(m, "(sv)", field, "a(st)", 0);
                else {
                        const char *path, *bandwidth, *e;
                        uint64_t bytes;

                        e = strchr(eq, ' ');
                        if (!e)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Failed to parse %s value %s.",
                                                       field, eq);

                        path = strndupa(eq, e - eq);
                        bandwidth = e+1;

                        if (streq(bandwidth, "infinity"))
                                bytes = CGROUP_LIMIT_MAX;
                        else {
                                r = parse_size(bandwidth, 1000, &bytes);
                                if (r < 0)
                                        return log_error_errno(r, "Failed to parse byte value %s: %m", bandwidth);
                        }

                        r = sd_bus_message_append(m, "(sv)", field, "a(st)", 1, path, bytes);
                }

                if (r < 0)
                        return bus_log_create_error(r);

                return 1;
        }

        if (STR_IN_SET(field, "IODeviceWeight", "BlockIODeviceWeight")) {

                if (isempty(eq))
                        r = sd_bus_message_append(m, "(sv)", field, "a(st)", 0);
                else {
                        const char *path, *weight, *e;
                        uint64_t u;

                        e = strchr(eq, ' ');
                        if (!e)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Failed to parse %s value %s.",
                                                       field, eq);

                        path = strndupa(eq, e - eq);
                        weight = e+1;

                        r = safe_atou64(weight, &u);
                        if (r < 0)
                                return log_error_errno(r, "Failed to parse %s value %s: %m", field, weight);

                        r = sd_bus_message_append(m, "(sv)", field, "a(st)", 1, path, u);
                }

                if (r < 0)
                        return bus_log_create_error(r);

                return 1;
        }

        if (streq(field, "IODeviceLatencyTargetSec")) {
                const char *field_usec = "IODeviceLatencyTargetUSec";

                if (isempty(eq))
                        r = sd_bus_message_append(m, "(sv)", field_usec, "a(st)", USEC_INFINITY);
                else {
                        const char *path, *target, *e;
                        usec_t usec;

                        e = strchr(eq, ' ');
                        if (!e)
                                return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                       "Failed to parse %s value %s.",
                                                       field, eq);

                        path = strndupa(eq, e - eq);
                        target = e+1;

                        r = parse_sec(target, &usec);
                        if (r < 0)
                                return log_error_errno(r, "Failed to parse %s value %s: %m", field, target);

                        r = sd_bus_message_append(m, "(sv)", field_usec, "a(st)", 1, path, usec);
                }

                if (r < 0)
                        return bus_log_create_error(r);

                return 1;
        }

        if (STR_IN_SET(field, "IPAddressAllow", "IPAddressDeny")) {
                unsigned char prefixlen;
                union in_addr_union prefix = {};
                int family;

                if (isempty(eq)) {
                        r = sd_bus_message_append(m, "(sv)", field, "a(iayu)", 0);
                        if (r < 0)
                                return bus_log_create_error(r);

                        return 1;
                }

                r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_open_container(m, 'v', "a(iayu)");
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_open_container(m, 'a', "(iayu)");
                if (r < 0)
                        return bus_log_create_error(r);

                if (streq(eq, "any")) {
                        /* "any" is a shortcut for 0.0.0.0/0 and ::/0 */

                        r = bus_append_ip_address_access(m, AF_INET, &prefix, 0);
                        if (r < 0)
                                return bus_log_create_error(r);

                        r = bus_append_ip_address_access(m, AF_INET6, &prefix, 0);
                        if (r < 0)
                                return bus_log_create_error(r);

                } else if (is_localhost(eq)) {
                        /* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */

                        prefix.in.s_addr = htobe32(0x7f000000);
                        r = bus_append_ip_address_access(m, AF_INET, &prefix, 8);
                        if (r < 0)
                                return bus_log_create_error(r);

                        prefix.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
                        r = bus_append_ip_address_access(m, AF_INET6, &prefix, 128);
                        if (r < 0)
                                return r;

                } else if (streq(eq, "link-local")) {
                        /* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */

                        prefix.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16));
                        r = bus_append_ip_address_access(m, AF_INET, &prefix, 16);
                        if (r < 0)
                                return bus_log_create_error(r);

                        prefix.in6 = (struct in6_addr) {
                                .s6_addr32[0] = htobe32(0xfe800000)
                        };
                        r = bus_append_ip_address_access(m, AF_INET6, &prefix, 64);
                        if (r < 0)
                                return bus_log_create_error(r);

                } else if (streq(eq, "multicast")) {
                        /* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */

                        prefix.in.s_addr = htobe32((UINT32_C(224) << 24));
                        r = bus_append_ip_address_access(m, AF_INET, &prefix, 4);
                        if (r < 0)
                                return bus_log_create_error(r);

                        prefix.in6 = (struct in6_addr) {
                                .s6_addr32[0] = htobe32(0xff000000)
                        };
                        r = bus_append_ip_address_access(m, AF_INET6, &prefix, 8);
                        if (r < 0)
                                return bus_log_create_error(r);

                } else {
                        for (;;) {
                                _cleanup_free_ char *word = NULL;

                                r = extract_first_word(&eq, &word, NULL, 0);
                                if (r == 0)
                                        break;
                                if (r == -ENOMEM)
                                        return log_oom();
                                if (r < 0)
                                        return log_error_errno(r, "Failed to parse %s: %s", field, eq);

                                r = in_addr_prefix_from_string_auto(word, &family, &prefix, &prefixlen);
                                if (r < 0)
                                        return log_error_errno(r, "Failed to parse IP address prefix: %s", word);

                                r = bus_append_ip_address_access(m, family, &prefix, prefixlen);
                                if (r < 0)
                                        return bus_log_create_error(r);
                        }
                }

                r = sd_bus_message_close_container(m);
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_close_container(m);
                if (r < 0)
                        return bus_log_create_error(r);

                r = sd_bus_message_close_container(m);
                if (r < 0)
                        return bus_log_create_error(r);

                return 1;
        }

        return 0;
}