static void test_multiple(void) { sd_netlink *rtnl1, *rtnl2; assert_se(sd_netlink_open(&rtnl1) >= 0); assert_se(sd_netlink_open(&rtnl2) >= 0); rtnl1 = sd_netlink_unref(rtnl1); rtnl2 = sd_netlink_unref(rtnl2); }
static int test_acd(const char *ifname, const char *address) { _cleanup_(sd_event_unrefp) sd_event *e = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *reply = NULL; union in_addr_union pa; struct ether_addr ha; int ifindex; assert_se(in_addr_from_string(AF_INET, address, &pa) >= 0); assert_se(sd_event_new(&e) >= 0); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_netlink_attach_event(rtnl, e, 0) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, 0) >= 0); assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, ifname) >= 0); assert_se(sd_netlink_call(rtnl, m, 0, &reply) >= 0); assert_se(sd_rtnl_message_link_get_ifindex(reply, &ifindex) >= 0); assert_se(sd_netlink_message_read_ether_addr(reply, IFLA_ADDRESS, &ha) >= 0); client_run(ifindex, &pa.in, &ha, e); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { sd_netlink *rtnl; int r; assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(rtnl); r = test_tunnel_configure(rtnl); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); return r; }
static void test_match(void) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_netlink_add_match(rtnl, RTM_NEWLINK, link_handler, NULL) >= 0); assert_se(sd_netlink_add_match(rtnl, RTM_NEWLINK, link_handler, NULL) >= 0); assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, link_handler, NULL) == 1); assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, link_handler, NULL) == 1); assert_se(sd_netlink_remove_match(rtnl, RTM_NEWLINK, link_handler, NULL) == 0); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); }
static void test_async(int ifindex) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL, *r = NULL; uint32_t serial; char *ifname; ifname = strdup("lo"); assert_se(ifname); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); assert_se(sd_netlink_call_async(rtnl, m, link_handler, ifname, 0, &serial) >= 0); assert_se(sd_netlink_wait(rtnl, 0) >= 0); assert_se(sd_netlink_process(rtnl, &r) >= 0); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); }
int loopback_setup(void) { _cleanup_netlink_unref_ sd_netlink *rtnl = NULL; int r; r = sd_netlink_open(&rtnl); if (r < 0) return r; r = start_loopback(rtnl); if (r < 0) { /* If we lack the permissions to configure the * loopback device, but we find it to be already * configured, let's exit cleanly, in order to * supported unprivileged containers. */ if (r == -EPERM && check_loopback(rtnl)) return 0; return log_warning_errno(r, "Failed to configure loopback device: %m"); } return 0; }
static void test_pipe(int ifindex) { _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m1 = NULL, *m2 = NULL; int counter = 0; assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m1, RTM_GETLINK, ifindex) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m2, RTM_GETLINK, ifindex) >= 0); counter++; assert_se(sd_netlink_call_async(rtnl, m1, pipe_handler, &counter, 0, NULL) >= 0); counter++; assert_se(sd_netlink_call_async(rtnl, m2, pipe_handler, &counter, 0, NULL) >= 0); while (counter > 0) { assert_se(sd_netlink_wait(rtnl, 0) >= 0); assert_se(sd_netlink_process(rtnl, NULL) >= 0); } assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); }
static void test_event_loop(int ifindex) { _cleanup_(sd_event_unrefp) sd_event *event = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; char *ifname; ifname = strdup("lo2"); assert_se(ifname); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, ifindex) >= 0); assert_se(sd_netlink_call_async(rtnl, m, link_handler, ifname, 0, NULL) >= 0); assert_se(sd_event_default(&event) >= 0); assert_se(sd_netlink_attach_event(rtnl, event, 0) >= 0); assert_se(sd_event_run(event, 0) >= 0); assert_se(sd_netlink_detach_event(rtnl) >= 0); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); }
static int list_links(int argc, char *argv[], void *userdata) { _cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL; _cleanup_netlink_unref_ sd_netlink *rtnl = NULL; _cleanup_free_ LinkInfo *links = NULL; int r, c, i; pager_open_if_enabled(); r = sd_netlink_open(&rtnl); if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0); if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_message_request_dump(req, true); if (r < 0) return rtnl_log_create_error(r); r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return log_error_errno(r, "Failed to enumerate links: %m"); if (arg_legend) printf("%3s %-16s %-18s %-11s %-10s\n", "IDX", "LINK", "TYPE", "OPERATIONAL", "SETUP"); c = decode_and_sort_links(reply, &links); if (c < 0) return rtnl_log_parse_error(c); for (i = 0; i < c; i++) { _cleanup_free_ char *setup_state = NULL, *operational_state = NULL; _cleanup_device_unref_ sd_device *d = NULL; const char *on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup; char devid[2 + DECIMAL_STR_MAX(int)]; _cleanup_free_ char *t = NULL; sd_network_link_get_operational_state(links[i].ifindex, &operational_state); operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); sd_network_link_get_setup_state(links[i].ifindex, &setup_state); setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); sprintf(devid, "n%i", links[i].ifindex); (void)sd_device_new_from_device_id(&d, devid); link_get_type_string(links[i].iftype, d, &t); printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n", links[i].ifindex, links[i].name, strna(t), on_color_operational, strna(operational_state), off_color_operational, on_color_setup, strna(setup_state), off_color_setup); } if (arg_legend) printf("\n%i links listed.\n", c); return 0; }
int local_addresses(sd_netlink *context, int ifindex, int af, struct local_address **ret) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_free_ struct local_address *list = NULL; size_t n_list = 0, n_allocated = 0; sd_netlink_message *m; int r; assert(ret); if (context) rtnl = sd_netlink_ref(context); else { r = sd_netlink_open(&rtnl); if (r < 0) return r; } r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, af); if (r < 0) return r; r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return r; for (m = reply; m; m = sd_netlink_message_next(m)) { struct local_address *a; unsigned char flags; uint16_t type; int ifi, family; r = sd_netlink_message_get_errno(m); if (r < 0) return r; r = sd_netlink_message_get_type(m, &type); if (r < 0) return r; if (type != RTM_NEWADDR) continue; r = sd_rtnl_message_addr_get_ifindex(m, &ifi); if (r < 0) return r; if (ifindex > 0 && ifi != ifindex) continue; r = sd_rtnl_message_addr_get_family(m, &family); if (r < 0) return r; if (af != AF_UNSPEC && af != family) continue; r = sd_rtnl_message_addr_get_flags(m, &flags); if (r < 0) return r; if (flags & IFA_F_DEPRECATED) continue; if (!GREEDY_REALLOC0(list, n_allocated, n_list+1)) return -ENOMEM; a = list + n_list; r = sd_rtnl_message_addr_get_scope(m, &a->scope); if (r < 0) return r; if (ifindex == 0 && IN_SET(a->scope, RT_SCOPE_HOST, RT_SCOPE_NOWHERE)) continue; switch (family) { case AF_INET: r = sd_netlink_message_read_in_addr(m, IFA_LOCAL, &a->address.in); if (r < 0) { r = sd_netlink_message_read_in_addr(m, IFA_ADDRESS, &a->address.in); if (r < 0) continue; } break; case AF_INET6: r = sd_netlink_message_read_in6_addr(m, IFA_LOCAL, &a->address.in6); if (r < 0) { r = sd_netlink_message_read_in6_addr(m, IFA_ADDRESS, &a->address.in6); if (r < 0) continue; } break; default: continue; } a->ifindex = ifi; a->family = family; n_list++; }; qsort_safe(list, n_list, sizeof(struct local_address), address_compare); *ret = TAKE_PTR(list); return (int) n_list; }
int local_gateways(sd_netlink *context, int ifindex, int af, struct local_address **ret) { _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; _cleanup_free_ struct local_address *list = NULL; sd_netlink_message *m = NULL; size_t n_list = 0, n_allocated = 0; int r; assert(ret); if (context) rtnl = sd_netlink_ref(context); else { r = sd_netlink_open(&rtnl); 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_netlink_message_request_dump(req, true); if (r < 0) return r; r = sd_netlink_call(rtnl, req, 0, &reply); if (r < 0) return r; for (m = reply; m; m = sd_netlink_message_next(m)) { struct local_address *a; uint16_t type; unsigned char dst_len, src_len; uint32_t ifi; int family; r = sd_netlink_message_get_errno(m); if (r < 0) return r; r = sd_netlink_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_netlink_message_read_u32(m, RTA_OIF, &ifi); if (r == -ENODATA) /* Not all routes have an RTA_OIF attribute (for example nexthop ones) */ continue; 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_netlink_message_read_in_addr(m, RTA_GATEWAY, &a->address.in); if (r < 0) continue; break; case AF_INET6: r = sd_netlink_message_read_in6_addr(m, RTA_GATEWAY, &a->address.in6); if (r < 0) continue; break; default: continue; } sd_netlink_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 = TAKE_PTR(list); return (int) n_list; }
static int test_pppoe_server(sd_event *e) { sd_netlink *rtnl; sd_netlink_message *m; pid_t pid; int r, client_ifindex, server_ifindex; r = unshare(CLONE_NEWNET); if (r < 0 && errno == EPERM) return EXIT_TEST_SKIP; assert_se(r >= 0); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(sd_netlink_attach_event(rtnl, e, 0) >= 0); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_NEWLINK, 0) >= 0); assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, "pppoe-server") >= 0); assert_se(sd_netlink_message_open_container(m, IFLA_LINKINFO) >= 0); assert_se(sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, "veth") >= 0); assert_se(sd_netlink_message_open_container(m, VETH_INFO_PEER) >= 0); assert_se(sd_netlink_message_append_string(m, IFLA_IFNAME, "pppoe-client") >= 0); assert_se(sd_netlink_message_close_container(m) >= 0); assert_se(sd_netlink_message_close_container(m) >= 0); assert_se(sd_netlink_message_close_container(m) >= 0); assert_se(sd_netlink_call(rtnl, m, 0, NULL) >= 0); client_ifindex = (int) if_nametoindex("pppoe-client"); assert_se(client_ifindex > 0); server_ifindex = (int) if_nametoindex("pppoe-server"); assert_se(server_ifindex > 0); m = sd_netlink_message_unref(m); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, client_ifindex) >= 0); assert_se(sd_rtnl_message_link_set_flags(m, IFF_UP, IFF_UP) >= 0); assert_se(sd_netlink_call(rtnl, m, 0, NULL) >= 0); m = sd_netlink_message_unref(m); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_SETLINK, server_ifindex) >= 0); assert_se(sd_rtnl_message_link_set_flags(m, IFF_UP, IFF_UP) >= 0); assert_se(sd_netlink_call(rtnl, m, 0, NULL) >= 0); pid = fork(); assert_se(pid >= 0); if (pid == 0) { /* let the client send some discover messages before the server is started */ sleep(2); /* TODO: manage pppoe-server-options */ execlp("pppoe-server", "pppoe-server", "-F", "-I", "pppoe-server", "-C", "Test-AC", "-S", "Service-Default", "-S", "Service-First-Auxiliary", "-S", "Service-Second-Auxiliary", NULL); assert_not_reached("failed to execute pppoe-server. not installed?"); } client_run("pppoe-client", e); assert_se(kill(pid, SIGTERM) >= 0); assert_se(wait_for_terminate(pid, NULL) >= 0); assert_se(!sd_netlink_message_unref(m)); assert_se(!sd_netlink_unref(rtnl)); return EXIT_SUCCESS; }
int main(void) { sd_netlink *rtnl; sd_netlink_message *m; sd_netlink_message *r; const char *string_data; int if_loopback; uint16_t type; test_match(); test_multiple(); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(rtnl); test_route(rtnl); test_message(rtnl); test_container(rtnl); if_loopback = (int) if_nametoindex("lo"); assert_se(if_loopback > 0); test_async(if_loopback); test_pipe(if_loopback); test_event_loop(if_loopback); test_link_configure(rtnl, if_loopback); test_get_addresses(rtnl); test_message_link_bridge(rtnl); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0); assert_se(m); assert_se(sd_netlink_message_get_type(m, &type) >= 0); assert_se(type == RTM_GETLINK); assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM); assert_se(sd_netlink_call(rtnl, m, 0, &r) == 1); assert_se(sd_netlink_message_get_type(r, &type) >= 0); assert_se(type == RTM_NEWLINK); assert_se((r = sd_netlink_message_unref(r)) == NULL); assert_se(sd_netlink_call(rtnl, m, -1, &r) == -EPERM); assert_se((m = sd_netlink_message_unref(m)) == NULL); assert_se((r = sd_netlink_message_unref(r)) == NULL); test_link_get(rtnl, if_loopback); test_address_get(rtnl, if_loopback); assert_se((m = sd_netlink_message_unref(m)) == NULL); assert_se((r = sd_netlink_message_unref(r)) == NULL); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); return EXIT_SUCCESS; }