int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) { _cleanup_netlink_message_unref_ sd_netlink_message *m = NULL; const NLType *nl_type; size_t size; int r; r = type_system_get_type(&type_system_root, &nl_type, type); if (r < 0) return r; if (type_get_type(nl_type) != NETLINK_TYPE_NESTED) return -EINVAL; r = message_new_empty(rtnl, &m); if (r < 0) return r; size = NLMSG_SPACE(type_get_size(nl_type)); assert(size >= sizeof(struct nlmsghdr)); m->hdr = malloc0(size); if (!m->hdr) return -ENOMEM; m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; type_get_type_system(nl_type, &m->containers[0].type_system); m->hdr->nlmsg_len = size; m->hdr->nlmsg_type = type; *ret = m; m = NULL; return 0; }
static int genl_message_new(sd_netlink *nl, sd_genl_family family, uint16_t nlmsg_type, uint8_t cmd, sd_netlink_message **ret) { int r; struct genlmsghdr *genl; const NLType *genl_cmd_type, *nl_type; const NLTypeSystem *type_system; size_t size; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; assert_return(nl->protocol == NETLINK_GENERIC, -EINVAL); r = type_system_get_type(&genl_family_type_system_root, &genl_cmd_type, family); if (r < 0) return r; r = message_new_empty(nl, &m); if (r < 0) return r; size = NLMSG_SPACE(sizeof(struct genlmsghdr)); m->hdr = malloc0(size); if (!m->hdr) return -ENOMEM; m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; type_get_type_system(genl_cmd_type, &type_system); r = type_system_get_type(type_system, &nl_type, cmd); if (r < 0) return r; m->hdr->nlmsg_len = size; m->hdr->nlmsg_type = nlmsg_type; type_get_type_system(nl_type, &m->containers[0].type_system); genl = NLMSG_DATA(m->hdr); genl->cmd = cmd; genl->version = genl_families[family].version; *ret = TAKE_PTR(m); return 0; }
int sd_netlink_message_rewind(sd_netlink_message *m) { const NLType *nl_type; uint16_t type; size_t size; unsigned i; int r; assert_return(m, -EINVAL); /* don't allow appending to message once parsed */ if (!m->sealed) rtnl_message_seal(m); for (i = 1; i <= m->n_containers; i++) m->containers[i].attributes = mfree(m->containers[i].attributes); m->n_containers = 0; if (m->containers[0].attributes) /* top-level attributes have already been parsed */ return 0; assert(m->hdr); r = type_system_get_type(&type_system_root, &nl_type, m->hdr->nlmsg_type); if (r < 0) return r; type = type_get_type(nl_type); size = type_get_size(nl_type); if (type == NETLINK_TYPE_NESTED) { const NLTypeSystem *type_system; type_get_type_system(nl_type, &type_system); m->containers[0].type_system = type_system; r = netlink_container_parse(m, &m->containers[m->n_containers], type_system_get_count(type_system), (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)), NLMSG_PAYLOAD(m->hdr, size)); if (r < 0) return r; } return 0; }