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); }
static void test_link_configure(sd_rtnl *rtnl, int ifindex) { _cleanup_rtnl_message_unref_ sd_rtnl_message *message = NULL; const char *mac = "98:fe:94:3f:c6:18", *name = "test"; char buffer[ETHER_ADDR_TO_STRING_MAX]; unsigned int mtu = 1450, mtu_out; const char *name_out; struct ether_addr mac_out; /* we'd really like to test NEWLINK, but let's not mess with the running kernel */ assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_GETLINK, ifindex) >= 0); assert_se(sd_rtnl_message_append_string(message, IFLA_IFNAME, name) >= 0); assert_se(sd_rtnl_message_append_ether_addr(message, IFLA_ADDRESS, ether_aton(mac)) >= 0); assert_se(sd_rtnl_message_append_u32(message, IFLA_MTU, mtu) >= 0); assert_se(sd_rtnl_call(rtnl, message, 0, NULL) == 1); assert_se(sd_rtnl_message_rewind(message) >= 0); assert_se(sd_rtnl_message_read_string(message, IFLA_IFNAME, &name_out) >= 0); assert_se(streq(name, name_out)); assert_se(sd_rtnl_message_read_ether_addr(message, IFLA_ADDRESS, &mac_out) >= 0); assert_se(streq(mac, ether_addr_to_string(&mac_out, buffer))); assert_se(sd_rtnl_message_read_u32(message, IFLA_MTU, &mtu_out) >= 0); assert_se(mtu == mtu_out); }
static void test_container(void) { _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; uint16_t u16_data; uint32_t u32_data; const char *string_data; 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_union(m, IFLA_INFO_DATA, "vlan") >= 0); 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, "vlan") >= 0); assert_se(sd_rtnl_message_close_container(m) >= 0); assert_se(sd_rtnl_message_close_container(m) == -EINVAL); assert_se(sd_rtnl_message_rewind(m) >= 0); assert_se(sd_rtnl_message_enter_container(m, IFLA_LINKINFO) >= 0); assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0); assert_se(streq("vlan", string_data)); assert_se(sd_rtnl_message_enter_container(m, IFLA_INFO_DATA) >= 0); assert_se(sd_rtnl_message_read_u16(m, IFLA_VLAN_ID, &u16_data) >= 0); assert_se(sd_rtnl_message_exit_container(m) >= 0); assert_se(sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &string_data) >= 0); assert_se(streq("vlan", string_data)); assert_se(sd_rtnl_message_exit_container(m) >= 0); 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_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_link_get(sd_rtnl *rtnl, int ifindex) { sd_rtnl_message *m; sd_rtnl_message *r; unsigned int mtu = 1500; const char *str_data; uint8_t u8_data; uint32_t u32_data; struct ether_addr eth_data; assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); assert_se(m); /* u8 test cases */ assert_se(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0); assert_se(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0); assert_se(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0); /* u32 test cases */ assert_se(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0); assert_se(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0); assert_se(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0); assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0); assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0); assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1); assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0); assert_se(sd_rtnl_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0); assert_se(sd_rtnl_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0); assert_se(sd_rtnl_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0); assert_se(sd_rtnl_message_read_u32(r, IFLA_MTU, &u32_data) == 0); assert_se(sd_rtnl_message_read_u32(r, IFLA_GROUP, &u32_data) == 0); assert_se(sd_rtnl_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0); assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0); assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0); assert_se(sd_rtnl_message_read_ether_addr(r, IFLA_ADDRESS, ð_data) == 0); assert_se(sd_rtnl_flush(rtnl) >= 0); assert_se((m = sd_rtnl_message_unref(m)) == NULL); assert_se((r = sd_rtnl_message_unref(r)) == NULL); }
static void test_message_link_bridge(sd_rtnl *rtnl) { _cleanup_rtnl_message_unref_ sd_rtnl_message *message = NULL; uint32_t cost; assert_se(sd_rtnl_message_new_link(rtnl, &message, RTM_NEWLINK, 1) >= 0); assert_se(sd_rtnl_message_link_set_family(message, PF_BRIDGE) >= 0); assert_se(sd_rtnl_message_open_container(message, IFLA_PROTINFO) >= 0); assert_se(sd_rtnl_message_append_u32(message, IFLA_BRPORT_COST, 10) >= 0); assert_se(sd_rtnl_message_close_container(message) >= 0); assert_se(sd_rtnl_message_rewind(message) >= 0); assert_se(sd_rtnl_message_enter_container(message, IFLA_PROTINFO) >= 0); assert_se(sd_rtnl_message_read_u32(message, IFLA_BRPORT_COST, &cost) >= 0); assert_se(cost == 10); assert_se(sd_rtnl_message_exit_container(message) >= 0); }
static void test_route(void) { _cleanup_rtnl_message_unref_ sd_rtnl_message *req; struct in_addr addr, addr_data; uint32_t index = 2, u32_data; int r; r = sd_rtnl_message_new_route(NULL, &req, RTM_NEWROUTE, AF_INET, RTPROT_STATIC); if (r < 0) { log_error_errno(r, "Could not create RTM_NEWROUTE message: %m"); return; } addr.s_addr = htonl(INADDR_LOOPBACK); r = sd_rtnl_message_append_in_addr(req, RTA_GATEWAY, &addr); if (r < 0) { log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m"); return; } r = sd_rtnl_message_append_u32(req, RTA_OIF, index); if (r < 0) { log_error_errno(r, "Could not append RTA_OIF attribute: %m"); return; } assert_se(sd_rtnl_message_rewind(req) >= 0); assert_se(sd_rtnl_message_read_in_addr(req, RTA_GATEWAY, &addr_data) >= 0); assert_se(addr_data.s_addr == addr.s_addr); assert_se(sd_rtnl_message_read_u32(req, RTA_OIF, &u32_data) >= 0); assert_se(u32_data == index); assert_se((req = sd_rtnl_message_unref(req)) == NULL); }
static void test_link_get(sd_rtnl *rtnl, int ifindex) { sd_rtnl_message *m; sd_rtnl_message *r; unsigned int mtu = 1500; unsigned int *mtu_reply; void *data; char *str_data; uint16_t type; uint8_t u8_data; uint32_t u32_data; struct ether_addr eth_data; assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); assert_se(m); /* u8 test cases */ assert_se(sd_rtnl_message_append_u8(m, IFLA_CARRIER, 0) >= 0); assert_se(sd_rtnl_message_append_u8(m, IFLA_OPERSTATE, 0) >= 0); assert_se(sd_rtnl_message_append_u8(m, IFLA_LINKMODE, 0) >= 0); /* u32 test cases */ assert_se(sd_rtnl_message_append_u32(m, IFLA_MTU, mtu) >= 0); assert_se(sd_rtnl_message_append_u32(m, IFLA_GROUP, 0) >= 0); assert_se(sd_rtnl_message_append_u32(m, IFLA_TXQLEN, 0) >= 0); assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_TX_QUEUES, 0) >= 0); assert_se(sd_rtnl_message_append_u32(m, IFLA_NUM_RX_QUEUES, 0) >= 0); assert_se(sd_rtnl_call(rtnl, m, -1, &r) == 1); /* u8 read back */ assert_se(sd_rtnl_message_read(m, &type, &data) == 1); assert_se(type == IFLA_CARRIER); assert_se(sd_rtnl_message_read(m, &type, &data) == 1); assert_se(type == IFLA_OPERSTATE); assert_se(sd_rtnl_message_read(m, &type, &data) == 1); assert_se(type == IFLA_LINKMODE); /* u32 read back */ assert_se(sd_rtnl_message_read(m, &type, (void **) &mtu_reply) == 1); assert_se(type == IFLA_MTU); assert_se(*mtu_reply == mtu); assert_se(sd_rtnl_message_read(m, &type, &data) == 1); assert_se(type == IFLA_GROUP); assert_se(sd_rtnl_message_read(m, &type, &data) == 1); assert_se(type == IFLA_TXQLEN); assert_se(sd_rtnl_message_read(m, &type, &data) == 1); assert_se(type == IFLA_NUM_TX_QUEUES); assert_se(sd_rtnl_message_read(m, &type, &data) == 1); assert_se(type == IFLA_NUM_RX_QUEUES); while (sd_rtnl_message_read(r, &type, &data) > 0) { switch (type) { // case IFLA_MTU: // assert_se(*(unsigned int *) data == 65536); // break; // case IFLA_QDISC: // assert_se(streq((char *) data, "noqueue")); // break; case IFLA_IFNAME: assert_se(streq((char *) data, "lo")); break; } } assert_se(sd_rtnl_message_read_string(r, IFLA_IFNAME, &str_data) == 0); assert_se(sd_rtnl_message_read_u8(r, IFLA_CARRIER, &u8_data) == 0); assert_se(sd_rtnl_message_read_u8(r, IFLA_OPERSTATE, &u8_data) == 0); assert_se(sd_rtnl_message_read_u8(r, IFLA_LINKMODE, &u8_data) == 0); assert_se(sd_rtnl_message_read_u32(r, IFLA_MTU, &u32_data) == 0); assert_se(sd_rtnl_message_read_u32(r, IFLA_GROUP, &u32_data) == 0); assert_se(sd_rtnl_message_read_u32(r, IFLA_TXQLEN, &u32_data) == 0); assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_TX_QUEUES, &u32_data) == 0); assert_se(sd_rtnl_message_read_u32(r, IFLA_NUM_RX_QUEUES, &u32_data) == 0); assert_se(sd_rtnl_message_read_ether_addr(r, IFLA_ADDRESS, ð_data) == 0); assert_se(sd_rtnl_flush(rtnl) >= 0); assert_se((m = sd_rtnl_message_unref(m)) == NULL); assert_se((r = sd_rtnl_message_unref(r)) == NULL); }
int local_gateways(sd_rtnl *context, int ifindex, int af, struct local_address **ret) { _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL; _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; _cleanup_free_ struct local_address *list = NULL; sd_rtnl_message *m = NULL; size_t n_list = 0, n_allocated = 0; int r; assert(ret); if (context) rtnl = sd_rtnl_ref(context); else { r = sd_rtnl_open(&rtnl, 0); if (r < 0) return r; } r = sd_rtnl_message_new_route(rtnl, &req, RTM_GETROUTE, af, RTPROT_UNSPEC); if (r < 0) return r; r = sd_rtnl_message_request_dump(req, true); if (r < 0) return r; r = sd_rtnl_call(rtnl, req, 0, &reply); if (r < 0) return r; for (m = reply; m; m = sd_rtnl_message_next(m)) { struct local_address *a; uint16_t type; unsigned char dst_len, src_len; uint32_t ifi; int family; r = sd_rtnl_message_get_errno(m); if (r < 0) return r; r = sd_rtnl_message_get_type(m, &type); if (r < 0) return r; if (type != RTM_NEWROUTE) continue; /* We only care for default routes */ r = sd_rtnl_message_route_get_dst_prefixlen(m, &dst_len); if (r < 0) return r; if (dst_len != 0) continue; r = sd_rtnl_message_route_get_src_prefixlen(m, &src_len); if (r < 0) return r; if (src_len != 0) continue; r = sd_rtnl_message_read_u32(m, RTA_OIF, &ifi); if (r < 0) return r; if (ifindex > 0 && (int) ifi != ifindex) continue; r = sd_rtnl_message_route_get_family(m, &family); if (r < 0) return r; if (af != AF_UNSPEC && af != family) continue; if (!GREEDY_REALLOC0(list, n_allocated, n_list + 1)) return -ENOMEM; a = list + n_list; switch (family) { case AF_INET: r = sd_rtnl_message_read_in_addr(m, RTA_GATEWAY, &a->address.in); if (r < 0) continue; break; case AF_INET6: r = sd_rtnl_message_read_in6_addr(m, RTA_GATEWAY, &a->address.in6); if (r < 0) continue; break; default: continue; } sd_rtnl_message_read_u32(m, RTA_PRIORITY, &a->metric); a->ifindex = ifi; a->family = family; n_list++; } if (n_list > 0) qsort(list, n_list, sizeof(struct local_address), address_compare); *ret = list; list = NULL; return (int) n_list; }