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