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