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
rt_link_print(struct rt_link_getlink_rsp * r)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
rt_link_create_netkit(struct ynl_sock * ys)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
rt_link_del(struct ynl_sock * ys,int ifindex)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
main(int argc,char ** argv)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