mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
185 lines
4 KiB
C
185 lines
4 KiB
C
![]() |
// SPDX-License-Identifier: GPL-2.0
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include <ynl.h>
|
||
|
|
||
|
#include <arpa/inet.h>
|
||
|
#include <net/if.h>
|
||
|
|
||
|
#include "rt-link-user.h"
|
||
|
|
||
|
static void rt_link_print(struct rt_link_getlink_rsp *r)
|
||
|
{
|
||
|
unsigned int i;
|
||
|
|
||
|
printf("%3d: ", r->_hdr.ifi_index);
|
||
|
|
||
|
if (r->_len.ifname)
|
||
|
printf("%16s: ", r->ifname);
|
||
|
|
||
|
if (r->_present.mtu)
|
||
|
printf("mtu %5d ", r->mtu);
|
||
|
|
||
|
if (r->linkinfo._len.kind)
|
||
|
printf("kind %-8s ", r->linkinfo.kind);
|
||
|
else
|
||
|
printf(" %8s ", "");
|
||
|
|
||
|
if (r->prop_list._count.alt_ifname) {
|
||
|
printf("altname ");
|
||
|
for (i = 0; i < r->prop_list._count.alt_ifname; i++)
|
||
|
printf("%s ", r->prop_list.alt_ifname[i]->str);
|
||
|
printf(" ");
|
||
|
}
|
||
|
|
||
|
if (r->linkinfo._present.data && r->linkinfo.data._present.netkit) {
|
||
|
struct rt_link_linkinfo_netkit_attrs *netkit;
|
||
|
const char *name;
|
||
|
|
||
|
netkit = &r->linkinfo.data.netkit;
|
||
|
printf("primary %d ", netkit->primary);
|
||
|
|
||
|
name = NULL;
|
||
|
if (netkit->_present.policy)
|
||
|
name = rt_link_netkit_policy_str(netkit->policy);
|
||
|
if (name)
|
||
|
printf("policy %s ", name);
|
||
|
}
|
||
|
|
||
|
printf("\n");
|
||
|
}
|
||
|
|
||
|
static int rt_link_create_netkit(struct ynl_sock *ys)
|
||
|
{
|
||
|
struct rt_link_getlink_ntf *ntf_gl;
|
||
|
struct rt_link_newlink_req *req;
|
||
|
struct ynl_ntf_base_type *ntf;
|
||
|
int ret;
|
||
|
|
||
|
req = rt_link_newlink_req_alloc();
|
||
|
if (!req) {
|
||
|
fprintf(stderr, "Can't alloc req\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* rtnetlink doesn't provide info about the created object.
|
||
|
* It expects us to set the ECHO flag and the dig the info out
|
||
|
* of the notifications...
|
||
|
*/
|
||
|
rt_link_newlink_req_set_nlflags(req, NLM_F_CREATE | NLM_F_ECHO);
|
||
|
|
||
|
rt_link_newlink_req_set_linkinfo_kind(req, "netkit");
|
||
|
|
||
|
/* Test error messages */
|
||
|
rt_link_newlink_req_set_linkinfo_data_netkit_policy(req, 10);
|
||
|
ret = rt_link_newlink(ys, req);
|
||
|
if (ret) {
|
||
|
printf("Testing error message for policy being bad:\n\t%s\n", ys->err.msg);
|
||
|
} else {
|
||
|
fprintf(stderr, "Warning: unexpected success creating netkit with bad attrs\n");
|
||
|
goto created;
|
||
|
}
|
||
|
|
||
|
rt_link_newlink_req_set_linkinfo_data_netkit_policy(req, NETKIT_DROP);
|
||
|
|
||
|
ret = rt_link_newlink(ys, req);
|
||
|
created:
|
||
|
rt_link_newlink_req_free(req);
|
||
|
if (ret) {
|
||
|
fprintf(stderr, "YNL: %s\n", ys->err.msg);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (!ynl_has_ntf(ys)) {
|
||
|
fprintf(stderr,
|
||
|
"Warning: interface created but received no notification, won't delete the interface\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
ntf = ynl_ntf_dequeue(ys);
|
||
|
if (ntf->cmd != RTM_NEWLINK) {
|
||
|
fprintf(stderr,
|
||
|
"Warning: unexpected notification type, won't delete the interface\n");
|
||
|
return 0;
|
||
|
}
|
||
|
ntf_gl = (void *)ntf;
|
||
|
ret = ntf_gl->obj._hdr.ifi_index;
|
||
|
ynl_ntf_free(ntf);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static void rt_link_del(struct ynl_sock *ys, int ifindex)
|
||
|
{
|
||
|
struct rt_link_dellink_req *req;
|
||
|
|
||
|
req = rt_link_dellink_req_alloc();
|
||
|
if (!req) {
|
||
|
fprintf(stderr, "Can't alloc req\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
req->_hdr.ifi_index = ifindex;
|
||
|
if (rt_link_dellink(ys, req))
|
||
|
fprintf(stderr, "YNL: %s\n", ys->err.msg);
|
||
|
else
|
||
|
fprintf(stderr,
|
||
|
"Trying to delete a Netkit interface (ifindex %d)\n",
|
||
|
ifindex);
|
||
|
|
||
|
rt_link_dellink_req_free(req);
|
||
|
}
|
||
|
|
||
|
int main(int argc, char **argv)
|
||
|
{
|
||
|
struct rt_link_getlink_req_dump *req;
|
||
|
struct rt_link_getlink_list *rsp;
|
||
|
struct ynl_error yerr;
|
||
|
struct ynl_sock *ys;
|
||
|
int created = 0;
|
||
|
|
||
|
ys = ynl_sock_create(&ynl_rt_link_family, &yerr);
|
||
|
if (!ys) {
|
||
|
fprintf(stderr, "YNL: %s\n", yerr.msg);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (argc > 1) {
|
||
|
fprintf(stderr, "Trying to create a Netkit interface\n");
|
||
|
created = rt_link_create_netkit(ys);
|
||
|
if (created < 0)
|
||
|
goto err_destroy;
|
||
|
}
|
||
|
|
||
|
req = rt_link_getlink_req_dump_alloc();
|
||
|
if (!req)
|
||
|
goto err_del_ifc;
|
||
|
|
||
|
rsp = rt_link_getlink_dump(ys, req);
|
||
|
rt_link_getlink_req_dump_free(req);
|
||
|
if (!rsp)
|
||
|
goto err_close;
|
||
|
|
||
|
if (ynl_dump_empty(rsp))
|
||
|
fprintf(stderr, "Error: no links reported\n");
|
||
|
ynl_dump_foreach(rsp, link)
|
||
|
rt_link_print(link);
|
||
|
rt_link_getlink_list_free(rsp);
|
||
|
|
||
|
if (created)
|
||
|
rt_link_del(ys, created);
|
||
|
|
||
|
ynl_sock_destroy(ys);
|
||
|
return 0;
|
||
|
|
||
|
err_close:
|
||
|
fprintf(stderr, "YNL: %s\n", ys->err.msg);
|
||
|
err_del_ifc:
|
||
|
if (created)
|
||
|
rt_link_del(ys, created);
|
||
|
err_destroy:
|
||
|
ynl_sock_destroy(ys);
|
||
|
return 2;
|
||
|
}
|