static void test_container(void) { _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; uint16_t type; uint32_t u32_data; void *data; int r; struct ifinfomsg *ifi; assert_se(sd_rtnl_message_new_link(NULL, &m, RTM_NEWLINK, 0) >= 0); assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) >= 0); assert_se(sd_rtnl_message_open_container(m, IFLA_LINKINFO) == -ENOTSUP); assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0); assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) >= 0); assert_se(sd_rtnl_message_open_container(m, IFLA_INFO_DATA) == -ENOTSUP); assert_se(sd_rtnl_message_append_u16(m, IFLA_VLAN_ID, 100) >= 0); assert_se(sd_rtnl_message_close_container(m) >= 0); assert_se(sd_rtnl_message_append_string(m, IFLA_INFO_KIND, "kind") >= 0); assert_se(sd_rtnl_message_close_container(m) >= 0); assert_se(sd_rtnl_message_close_container(m) == -EINVAL); assert_se(rtnl_message_seal(NULL, m) >= 0); assert_se(sd_rtnl_message_read(m, &type, &data) >= 0); assert_se(type == IFLA_LINKINFO); assert_se(data == NULL); /* assert_se(sd_rtnl_message_read(m, &type, &data) >= 0); assert_se(type == IFLA_INFO_KIND); assert_se(streq("kind", (char *)data)); assert_se(sd_rtnl_message_read(m, &type, &data) >= 0); assert_se(type == IFLA_INFO_DATA); assert_se(data == NULL); assert_se(sd_rtnl_message_read(m, &type, &data) >= 0); assert_se(type == IFLA_VLAN_ID); assert_se(*(uint16_t *)data == 100); assert_se(sd_rtnl_message_read(m, &type, &data) == 0); assert_se(sd_rtnl_message_exit_container(m) >= 0); assert_se(sd_rtnl_message_read(m, &type, &data) >= 0); assert_se(type == IFLA_INFO_KIND); assert_se(streq("kind", (char *)data)); assert_se(sd_rtnl_message_read(m, &type, &data) == 0); assert_se(sd_rtnl_message_exit_container(m) >= 0); */ ifi = NLMSG_DATA(m->hdr); r = rtnl_message_parse(m, &m->rta_offset_tb, &m->rta_tb_size, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(m->hdr)); if(r < 0) return; assert_se(sd_rtnl_message_read_u32(m, IFLA_LINKINFO, &u32_data) == 0); assert_se(sd_rtnl_message_exit_container(m) == -EINVAL); }
static void test_route(void) { _cleanup_rtnl_message_unref_ sd_rtnl_message *req; struct in_addr addr; uint32_t index = 2; uint16_t type; void *data; uint32_t u32_data; int r; struct rtmsg *rtm; r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET); if (r < 0) { log_error("Could not create RTM_NEWROUTE message: %s", strerror(-r)); return; } addr.s_addr = htonl(INADDR_LOOPBACK); r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr); if (r < 0) { log_error("Could not append RTA_GATEWAY attribute: %s", strerror(-r)); return; } r = sd_rtnl_message_append_u32(req, RTA_OIF, index); if (r < 0) { log_error("Could not append RTA_OIF attribute: %s", strerror(-r)); return; } assert_se(rtnl_message_seal(NULL, req) >= 0); assert_se(sd_rtnl_message_read(req, &type, &data) > 0); assert_se(type == RTA_GATEWAY); assert_se(((struct in_addr *)data)->s_addr == addr.s_addr); assert_se(sd_rtnl_message_read(req, &type, &data) > 0); assert_se(type == RTA_OIF); assert_se(*(uint32_t *) data == index); rtm = NLMSG_DATA(req->hdr); r = rtnl_message_parse(req, &req->rta_offset_tb, &req->rta_tb_size, RTA_MAX, RTM_RTA(rtm), RTM_PAYLOAD(req->hdr)); assert_se(sd_rtnl_message_read_u32(req, RTA_GATEWAY, &u32_data) == 0); assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) == 0); assert_se((req = sd_rtnl_message_unref(req)) == NULL); }
int sd_rtnl_message_rewind(sd_rtnl_message *m) { const NLType *type; 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++) { free(m->rta_offset_tb[i]); m->rta_offset_tb[i] = NULL; m->rta_tb_size[i] = 0; m->container_type_system[i] = NULL; } m->n_containers = 0; if (m->rta_offset_tb[0]) { /* top-level attributes have already been parsed */ return 0; } assert(m->hdr); r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type); if (r < 0) return r; if (type->type == NLA_NESTED) { const NLTypeSystem *type_system = type->type_system; assert(type_system); m->container_type_system[0] = type_system; r = rtnl_message_parse(m, &m->rta_offset_tb[m->n_containers], &m->rta_tb_size[m->n_containers], type_system->max, (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) + NLMSG_ALIGN(type->size)), NLMSG_PAYLOAD(m->hdr, type->size)); if (r < 0) return r; } 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; }