xref: /linux/tools/net/ynl/samples/rt-link.c (revision 1b98f357dadd6ea613a435fbaef1a5dd7b35fd21)
1*d5d1813bSJakub Kicinski // SPDX-License-Identifier: GPL-2.0
2*d5d1813bSJakub Kicinski #include <stdio.h>
3*d5d1813bSJakub Kicinski #include <string.h>
4*d5d1813bSJakub Kicinski 
5*d5d1813bSJakub Kicinski #include <ynl.h>
6*d5d1813bSJakub Kicinski 
7*d5d1813bSJakub Kicinski #include <arpa/inet.h>
8*d5d1813bSJakub Kicinski #include <net/if.h>
9*d5d1813bSJakub Kicinski 
10*d5d1813bSJakub Kicinski #include "rt-link-user.h"
11*d5d1813bSJakub Kicinski 
12*d5d1813bSJakub Kicinski static void rt_link_print(struct rt_link_getlink_rsp *r)
13*d5d1813bSJakub Kicinski {
14*d5d1813bSJakub Kicinski 	unsigned int i;
15*d5d1813bSJakub Kicinski 
16*d5d1813bSJakub Kicinski 	printf("%3d: ", r->_hdr.ifi_index);
17*d5d1813bSJakub Kicinski 
18*d5d1813bSJakub Kicinski 	if (r->_len.ifname)
19*d5d1813bSJakub Kicinski 		printf("%16s: ", r->ifname);
20*d5d1813bSJakub Kicinski 
21*d5d1813bSJakub Kicinski 	if (r->_present.mtu)
22*d5d1813bSJakub Kicinski 		printf("mtu %5d  ", r->mtu);
23*d5d1813bSJakub Kicinski 
24*d5d1813bSJakub Kicinski 	if (r->linkinfo._len.kind)
25*d5d1813bSJakub Kicinski 		printf("kind %-8s  ", r->linkinfo.kind);
26*d5d1813bSJakub Kicinski 	else
27*d5d1813bSJakub Kicinski 		printf("     %8s  ", "");
28*d5d1813bSJakub Kicinski 
29*d5d1813bSJakub Kicinski 	if (r->prop_list._count.alt_ifname) {
30*d5d1813bSJakub Kicinski 		printf("altname ");
31*d5d1813bSJakub Kicinski 		for (i = 0; i < r->prop_list._count.alt_ifname; i++)
32*d5d1813bSJakub Kicinski 			printf("%s ", r->prop_list.alt_ifname[i]->str);
33*d5d1813bSJakub Kicinski 		printf(" ");
34*d5d1813bSJakub Kicinski 	}
35*d5d1813bSJakub Kicinski 
36*d5d1813bSJakub Kicinski 	if (r->linkinfo._present.data && r->linkinfo.data._present.netkit) {
37*d5d1813bSJakub Kicinski 		struct rt_link_linkinfo_netkit_attrs *netkit;
38*d5d1813bSJakub Kicinski 		const char *name;
39*d5d1813bSJakub Kicinski 
40*d5d1813bSJakub Kicinski 		netkit = &r->linkinfo.data.netkit;
41*d5d1813bSJakub Kicinski 		printf("primary %d  ", netkit->primary);
42*d5d1813bSJakub Kicinski 
43*d5d1813bSJakub Kicinski 		name = NULL;
44*d5d1813bSJakub Kicinski 		if (netkit->_present.policy)
45*d5d1813bSJakub Kicinski 			name = rt_link_netkit_policy_str(netkit->policy);
46*d5d1813bSJakub Kicinski 		if (name)
47*d5d1813bSJakub Kicinski 			printf("policy %s  ", name);
48*d5d1813bSJakub Kicinski 	}
49*d5d1813bSJakub Kicinski 
50*d5d1813bSJakub Kicinski 	printf("\n");
51*d5d1813bSJakub Kicinski }
52*d5d1813bSJakub Kicinski 
53*d5d1813bSJakub Kicinski static int rt_link_create_netkit(struct ynl_sock *ys)
54*d5d1813bSJakub Kicinski {
55*d5d1813bSJakub Kicinski 	struct rt_link_getlink_ntf *ntf_gl;
56*d5d1813bSJakub Kicinski 	struct rt_link_newlink_req *req;
57*d5d1813bSJakub Kicinski 	struct ynl_ntf_base_type *ntf;
58*d5d1813bSJakub Kicinski 	int ret;
59*d5d1813bSJakub Kicinski 
60*d5d1813bSJakub Kicinski 	req = rt_link_newlink_req_alloc();
61*d5d1813bSJakub Kicinski 	if (!req) {
62*d5d1813bSJakub Kicinski 		fprintf(stderr, "Can't alloc req\n");
63*d5d1813bSJakub Kicinski 		return -1;
64*d5d1813bSJakub Kicinski 	}
65*d5d1813bSJakub Kicinski 
66*d5d1813bSJakub Kicinski 	/* rtnetlink doesn't provide info about the created object.
67*d5d1813bSJakub Kicinski 	 * It expects us to set the ECHO flag and the dig the info out
68*d5d1813bSJakub Kicinski 	 * of the notifications...
69*d5d1813bSJakub Kicinski 	 */
70*d5d1813bSJakub Kicinski 	rt_link_newlink_req_set_nlflags(req, NLM_F_CREATE | NLM_F_ECHO);
71*d5d1813bSJakub Kicinski 
72*d5d1813bSJakub Kicinski 	rt_link_newlink_req_set_linkinfo_kind(req, "netkit");
73*d5d1813bSJakub Kicinski 
74*d5d1813bSJakub Kicinski 	/* Test error messages */
75*d5d1813bSJakub Kicinski 	rt_link_newlink_req_set_linkinfo_data_netkit_policy(req, 10);
76*d5d1813bSJakub Kicinski 	ret = rt_link_newlink(ys, req);
77*d5d1813bSJakub Kicinski 	if (ret) {
78*d5d1813bSJakub Kicinski 		printf("Testing error message for policy being bad:\n\t%s\n", ys->err.msg);
79*d5d1813bSJakub Kicinski 	} else {
80*d5d1813bSJakub Kicinski 		fprintf(stderr,	"Warning: unexpected success creating netkit with bad attrs\n");
81*d5d1813bSJakub Kicinski 		goto created;
82*d5d1813bSJakub Kicinski 	}
83*d5d1813bSJakub Kicinski 
84*d5d1813bSJakub Kicinski 	rt_link_newlink_req_set_linkinfo_data_netkit_policy(req, NETKIT_DROP);
85*d5d1813bSJakub Kicinski 
86*d5d1813bSJakub Kicinski 	ret = rt_link_newlink(ys, req);
87*d5d1813bSJakub Kicinski created:
88*d5d1813bSJakub Kicinski 	rt_link_newlink_req_free(req);
89*d5d1813bSJakub Kicinski 	if (ret) {
90*d5d1813bSJakub Kicinski 		fprintf(stderr, "YNL: %s\n", ys->err.msg);
91*d5d1813bSJakub Kicinski 		return -1;
92*d5d1813bSJakub Kicinski 	}
93*d5d1813bSJakub Kicinski 
94*d5d1813bSJakub Kicinski 	if (!ynl_has_ntf(ys)) {
95*d5d1813bSJakub Kicinski 		fprintf(stderr,
96*d5d1813bSJakub Kicinski 			"Warning: interface created but received no notification, won't delete the interface\n");
97*d5d1813bSJakub Kicinski 		return 0;
98*d5d1813bSJakub Kicinski 	}
99*d5d1813bSJakub Kicinski 
100*d5d1813bSJakub Kicinski 	ntf = ynl_ntf_dequeue(ys);
101*d5d1813bSJakub Kicinski 	if (ntf->cmd !=	RTM_NEWLINK) {
102*d5d1813bSJakub Kicinski 		fprintf(stderr,
103*d5d1813bSJakub Kicinski 			"Warning: unexpected notification type, won't delete the interface\n");
104*d5d1813bSJakub Kicinski 		return 0;
105*d5d1813bSJakub Kicinski 	}
106*d5d1813bSJakub Kicinski 	ntf_gl = (void *)ntf;
107*d5d1813bSJakub Kicinski 	ret = ntf_gl->obj._hdr.ifi_index;
108*d5d1813bSJakub Kicinski 	ynl_ntf_free(ntf);
109*d5d1813bSJakub Kicinski 
110*d5d1813bSJakub Kicinski 	return ret;
111*d5d1813bSJakub Kicinski }
112*d5d1813bSJakub Kicinski 
113*d5d1813bSJakub Kicinski static void rt_link_del(struct ynl_sock *ys, int ifindex)
114*d5d1813bSJakub Kicinski {
115*d5d1813bSJakub Kicinski 	struct rt_link_dellink_req *req;
116*d5d1813bSJakub Kicinski 
117*d5d1813bSJakub Kicinski 	req = rt_link_dellink_req_alloc();
118*d5d1813bSJakub Kicinski 	if (!req) {
119*d5d1813bSJakub Kicinski 		fprintf(stderr, "Can't alloc req\n");
120*d5d1813bSJakub Kicinski 		return;
121*d5d1813bSJakub Kicinski 	}
122*d5d1813bSJakub Kicinski 
123*d5d1813bSJakub Kicinski 	req->_hdr.ifi_index = ifindex;
124*d5d1813bSJakub Kicinski 	if (rt_link_dellink(ys, req))
125*d5d1813bSJakub Kicinski 		fprintf(stderr, "YNL: %s\n", ys->err.msg);
126*d5d1813bSJakub Kicinski 	else
127*d5d1813bSJakub Kicinski 		fprintf(stderr,
128*d5d1813bSJakub Kicinski 			"Trying to delete a Netkit interface (ifindex %d)\n",
129*d5d1813bSJakub Kicinski 			ifindex);
130*d5d1813bSJakub Kicinski 
131*d5d1813bSJakub Kicinski 	rt_link_dellink_req_free(req);
132*d5d1813bSJakub Kicinski }
133*d5d1813bSJakub Kicinski 
134*d5d1813bSJakub Kicinski int main(int argc, char **argv)
135*d5d1813bSJakub Kicinski {
136*d5d1813bSJakub Kicinski 	struct rt_link_getlink_req_dump *req;
137*d5d1813bSJakub Kicinski 	struct rt_link_getlink_list *rsp;
138*d5d1813bSJakub Kicinski 	struct ynl_error yerr;
139*d5d1813bSJakub Kicinski 	struct ynl_sock *ys;
140*d5d1813bSJakub Kicinski 	int created = 0;
141*d5d1813bSJakub Kicinski 
142*d5d1813bSJakub Kicinski 	ys = ynl_sock_create(&ynl_rt_link_family, &yerr);
143*d5d1813bSJakub Kicinski 	if (!ys) {
144*d5d1813bSJakub Kicinski 		fprintf(stderr, "YNL: %s\n", yerr.msg);
145*d5d1813bSJakub Kicinski 		return 1;
146*d5d1813bSJakub Kicinski 	}
147*d5d1813bSJakub Kicinski 
148*d5d1813bSJakub Kicinski 	if (argc > 1) {
149*d5d1813bSJakub Kicinski 		fprintf(stderr, "Trying to create a Netkit interface\n");
150*d5d1813bSJakub Kicinski 		created = rt_link_create_netkit(ys);
151*d5d1813bSJakub Kicinski 		if (created < 0)
152*d5d1813bSJakub Kicinski 			goto err_destroy;
153*d5d1813bSJakub Kicinski 	}
154*d5d1813bSJakub Kicinski 
155*d5d1813bSJakub Kicinski 	req = rt_link_getlink_req_dump_alloc();
156*d5d1813bSJakub Kicinski 	if (!req)
157*d5d1813bSJakub Kicinski 		goto err_del_ifc;
158*d5d1813bSJakub Kicinski 
159*d5d1813bSJakub Kicinski 	rsp = rt_link_getlink_dump(ys, req);
160*d5d1813bSJakub Kicinski 	rt_link_getlink_req_dump_free(req);
161*d5d1813bSJakub Kicinski 	if (!rsp)
162*d5d1813bSJakub Kicinski 		goto err_close;
163*d5d1813bSJakub Kicinski 
164*d5d1813bSJakub Kicinski 	if (ynl_dump_empty(rsp))
165*d5d1813bSJakub Kicinski 		fprintf(stderr, "Error: no links reported\n");
166*d5d1813bSJakub Kicinski 	ynl_dump_foreach(rsp, link)
167*d5d1813bSJakub Kicinski 		rt_link_print(link);
168*d5d1813bSJakub Kicinski 	rt_link_getlink_list_free(rsp);
169*d5d1813bSJakub Kicinski 
170*d5d1813bSJakub Kicinski 	if (created)
171*d5d1813bSJakub Kicinski 		rt_link_del(ys, created);
172*d5d1813bSJakub Kicinski 
173*d5d1813bSJakub Kicinski 	ynl_sock_destroy(ys);
174*d5d1813bSJakub Kicinski 	return 0;
175*d5d1813bSJakub Kicinski 
176*d5d1813bSJakub Kicinski err_close:
177*d5d1813bSJakub Kicinski 	fprintf(stderr, "YNL: %s\n", ys->err.msg);
178*d5d1813bSJakub Kicinski err_del_ifc:
179*d5d1813bSJakub Kicinski 	if (created)
180*d5d1813bSJakub Kicinski 		rt_link_del(ys, created);
181*d5d1813bSJakub Kicinski err_destroy:
182*d5d1813bSJakub Kicinski 	ynl_sock_destroy(ys);
183*d5d1813bSJakub Kicinski 	return 2;
184*d5d1813bSJakub Kicinski }
185