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