xref: /aosp_15_r20/external/iproute2/ip/iplink_vrf.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /* iplink_vrf.c	VRF device support
2*de1e4e89SAndroid Build Coastguard Worker  *
3*de1e4e89SAndroid Build Coastguard Worker  *              This program is free software; you can redistribute it and/or
4*de1e4e89SAndroid Build Coastguard Worker  *              modify it under the terms of the GNU General Public License
5*de1e4e89SAndroid Build Coastguard Worker  *              as published by the Free Software Foundation; either version
6*de1e4e89SAndroid Build Coastguard Worker  *              2 of the License, or (at your option) any later version.
7*de1e4e89SAndroid Build Coastguard Worker  *
8*de1e4e89SAndroid Build Coastguard Worker  * Authors:     Shrijeet Mukherjee <[email protected]>
9*de1e4e89SAndroid Build Coastguard Worker  */
10*de1e4e89SAndroid Build Coastguard Worker 
11*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
12*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_link.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
17*de1e4e89SAndroid Build Coastguard Worker 
18*de1e4e89SAndroid Build Coastguard Worker #include "rt_names.h"
19*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
20*de1e4e89SAndroid Build Coastguard Worker #include "ip_common.h"
21*de1e4e89SAndroid Build Coastguard Worker 
vrf_explain(FILE * f)22*de1e4e89SAndroid Build Coastguard Worker static void vrf_explain(FILE *f)
23*de1e4e89SAndroid Build Coastguard Worker {
24*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "Usage: ... vrf table TABLEID\n");
25*de1e4e89SAndroid Build Coastguard Worker }
26*de1e4e89SAndroid Build Coastguard Worker 
explain(void)27*de1e4e89SAndroid Build Coastguard Worker static void explain(void)
28*de1e4e89SAndroid Build Coastguard Worker {
29*de1e4e89SAndroid Build Coastguard Worker 	vrf_explain(stderr);
30*de1e4e89SAndroid Build Coastguard Worker }
31*de1e4e89SAndroid Build Coastguard Worker 
vrf_parse_opt(struct link_util * lu,int argc,char ** argv,struct nlmsghdr * n)32*de1e4e89SAndroid Build Coastguard Worker static int vrf_parse_opt(struct link_util *lu, int argc, char **argv,
33*de1e4e89SAndroid Build Coastguard Worker 			    struct nlmsghdr *n)
34*de1e4e89SAndroid Build Coastguard Worker {
35*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
36*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "table") == 0) {
37*de1e4e89SAndroid Build Coastguard Worker 			__u32 table;
38*de1e4e89SAndroid Build Coastguard Worker 
39*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
40*de1e4e89SAndroid Build Coastguard Worker 
41*de1e4e89SAndroid Build Coastguard Worker 			if (rtnl_rttable_a2n(&table, *argv))
42*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid table ID\n", *argv);
43*de1e4e89SAndroid Build Coastguard Worker 			addattr32(n, 1024, IFLA_VRF_TABLE, table);
44*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "help") == 0) {
45*de1e4e89SAndroid Build Coastguard Worker 			explain();
46*de1e4e89SAndroid Build Coastguard Worker 			return -1;
47*de1e4e89SAndroid Build Coastguard Worker 		} else {
48*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "vrf: unknown option \"%s\"?\n",
49*de1e4e89SAndroid Build Coastguard Worker 				*argv);
50*de1e4e89SAndroid Build Coastguard Worker 			explain();
51*de1e4e89SAndroid Build Coastguard Worker 			return -1;
52*de1e4e89SAndroid Build Coastguard Worker 		}
53*de1e4e89SAndroid Build Coastguard Worker 		argc--, argv++;
54*de1e4e89SAndroid Build Coastguard Worker 	}
55*de1e4e89SAndroid Build Coastguard Worker 
56*de1e4e89SAndroid Build Coastguard Worker 	return 0;
57*de1e4e89SAndroid Build Coastguard Worker }
58*de1e4e89SAndroid Build Coastguard Worker 
vrf_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])59*de1e4e89SAndroid Build Coastguard Worker static void vrf_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
60*de1e4e89SAndroid Build Coastguard Worker {
61*de1e4e89SAndroid Build Coastguard Worker 	if (!tb)
62*de1e4e89SAndroid Build Coastguard Worker 		return;
63*de1e4e89SAndroid Build Coastguard Worker 
64*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_VRF_TABLE])
65*de1e4e89SAndroid Build Coastguard Worker 		print_uint(PRINT_ANY,
66*de1e4e89SAndroid Build Coastguard Worker 			   "table",
67*de1e4e89SAndroid Build Coastguard Worker 			   "table %u ",
68*de1e4e89SAndroid Build Coastguard Worker 			   rta_getattr_u32(tb[IFLA_VRF_TABLE]));
69*de1e4e89SAndroid Build Coastguard Worker }
70*de1e4e89SAndroid Build Coastguard Worker 
vrf_slave_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])71*de1e4e89SAndroid Build Coastguard Worker static void vrf_slave_print_opt(struct link_util *lu, FILE *f,
72*de1e4e89SAndroid Build Coastguard Worker 				struct rtattr *tb[])
73*de1e4e89SAndroid Build Coastguard Worker {
74*de1e4e89SAndroid Build Coastguard Worker 	if (!tb)
75*de1e4e89SAndroid Build Coastguard Worker 		return;
76*de1e4e89SAndroid Build Coastguard Worker 
77*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_VRF_PORT_TABLE]) {
78*de1e4e89SAndroid Build Coastguard Worker 		print_uint(PRINT_ANY,
79*de1e4e89SAndroid Build Coastguard Worker 			   "table",
80*de1e4e89SAndroid Build Coastguard Worker 			   "table %u ",
81*de1e4e89SAndroid Build Coastguard Worker 			   rta_getattr_u32(tb[IFLA_VRF_PORT_TABLE]));
82*de1e4e89SAndroid Build Coastguard Worker 	}
83*de1e4e89SAndroid Build Coastguard Worker }
84*de1e4e89SAndroid Build Coastguard Worker 
vrf_print_help(struct link_util * lu,int argc,char ** argv,FILE * f)85*de1e4e89SAndroid Build Coastguard Worker static void vrf_print_help(struct link_util *lu, int argc, char **argv,
86*de1e4e89SAndroid Build Coastguard Worker 			   FILE *f)
87*de1e4e89SAndroid Build Coastguard Worker {
88*de1e4e89SAndroid Build Coastguard Worker 	vrf_explain(f);
89*de1e4e89SAndroid Build Coastguard Worker }
90*de1e4e89SAndroid Build Coastguard Worker 
91*de1e4e89SAndroid Build Coastguard Worker struct link_util vrf_link_util = {
92*de1e4e89SAndroid Build Coastguard Worker 	.id		= "vrf",
93*de1e4e89SAndroid Build Coastguard Worker 	.maxattr	= IFLA_VRF_MAX,
94*de1e4e89SAndroid Build Coastguard Worker 	.parse_opt	= vrf_parse_opt,
95*de1e4e89SAndroid Build Coastguard Worker 	.print_opt	= vrf_print_opt,
96*de1e4e89SAndroid Build Coastguard Worker 	.print_help	= vrf_print_help,
97*de1e4e89SAndroid Build Coastguard Worker };
98*de1e4e89SAndroid Build Coastguard Worker 
99*de1e4e89SAndroid Build Coastguard Worker struct link_util vrf_slave_link_util = {
100*de1e4e89SAndroid Build Coastguard Worker 	.id             = "vrf_slave",
101*de1e4e89SAndroid Build Coastguard Worker 	.maxattr        = IFLA_VRF_PORT_MAX,
102*de1e4e89SAndroid Build Coastguard Worker 	.print_opt	= vrf_slave_print_opt,
103*de1e4e89SAndroid Build Coastguard Worker };
104*de1e4e89SAndroid Build Coastguard Worker 
105*de1e4e89SAndroid Build Coastguard Worker /* returns table id if name is a VRF device */
ipvrf_get_table(const char * name)106*de1e4e89SAndroid Build Coastguard Worker __u32 ipvrf_get_table(const char *name)
107*de1e4e89SAndroid Build Coastguard Worker {
108*de1e4e89SAndroid Build Coastguard Worker 	struct {
109*de1e4e89SAndroid Build Coastguard Worker 		struct nlmsghdr		n;
110*de1e4e89SAndroid Build Coastguard Worker 		struct ifinfomsg	i;
111*de1e4e89SAndroid Build Coastguard Worker 		char			buf[1024];
112*de1e4e89SAndroid Build Coastguard Worker 	} req = {
113*de1e4e89SAndroid Build Coastguard Worker 		.n = {
114*de1e4e89SAndroid Build Coastguard Worker 			.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
115*de1e4e89SAndroid Build Coastguard Worker 			.nlmsg_flags = NLM_F_REQUEST,
116*de1e4e89SAndroid Build Coastguard Worker 			.nlmsg_type  = RTM_GETLINK,
117*de1e4e89SAndroid Build Coastguard Worker 		},
118*de1e4e89SAndroid Build Coastguard Worker 		.i = {
119*de1e4e89SAndroid Build Coastguard Worker 			.ifi_family  = preferred_family,
120*de1e4e89SAndroid Build Coastguard Worker 		},
121*de1e4e89SAndroid Build Coastguard Worker 	};
122*de1e4e89SAndroid Build Coastguard Worker 	struct {
123*de1e4e89SAndroid Build Coastguard Worker 		struct nlmsghdr n;
124*de1e4e89SAndroid Build Coastguard Worker 		char buf[8192];
125*de1e4e89SAndroid Build Coastguard Worker 	} answer;
126*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[IFLA_MAX+1];
127*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *li[IFLA_INFO_MAX+1];
128*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *vrf_attr[IFLA_VRF_MAX + 1];
129*de1e4e89SAndroid Build Coastguard Worker 	struct ifinfomsg *ifi;
130*de1e4e89SAndroid Build Coastguard Worker 	__u32 tb_id = 0;
131*de1e4e89SAndroid Build Coastguard Worker 	int len;
132*de1e4e89SAndroid Build Coastguard Worker 
133*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1);
134*de1e4e89SAndroid Build Coastguard Worker 
135*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_talk_suppress_rtnl_errmsg(&rth, &req.n,
136*de1e4e89SAndroid Build Coastguard Worker 					   &answer.n, sizeof(answer)) < 0) {
137*de1e4e89SAndroid Build Coastguard Worker 		/* special case "default" vrf to be the main table */
138*de1e4e89SAndroid Build Coastguard Worker 		if (errno == ENODEV && !strcmp(name, "default"))
139*de1e4e89SAndroid Build Coastguard Worker 			if (rtnl_rttable_a2n(&tb_id, "main"))
140*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr,
141*de1e4e89SAndroid Build Coastguard Worker 					"BUG: RTTable \"main\" not found.\n");
142*de1e4e89SAndroid Build Coastguard Worker 
143*de1e4e89SAndroid Build Coastguard Worker 		return tb_id;
144*de1e4e89SAndroid Build Coastguard Worker 	}
145*de1e4e89SAndroid Build Coastguard Worker 
146*de1e4e89SAndroid Build Coastguard Worker 	ifi = NLMSG_DATA(&answer.n);
147*de1e4e89SAndroid Build Coastguard Worker 	len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
148*de1e4e89SAndroid Build Coastguard Worker 	if (len < 0) {
149*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "BUG: Invalid response to link query.\n");
150*de1e4e89SAndroid Build Coastguard Worker 		return 0;
151*de1e4e89SAndroid Build Coastguard Worker 	}
152*de1e4e89SAndroid Build Coastguard Worker 
153*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
154*de1e4e89SAndroid Build Coastguard Worker 
155*de1e4e89SAndroid Build Coastguard Worker 	if (!tb[IFLA_LINKINFO])
156*de1e4e89SAndroid Build Coastguard Worker 		return 0;
157*de1e4e89SAndroid Build Coastguard Worker 
158*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
159*de1e4e89SAndroid Build Coastguard Worker 
160*de1e4e89SAndroid Build Coastguard Worker 	if (!li[IFLA_INFO_KIND] || !li[IFLA_INFO_DATA])
161*de1e4e89SAndroid Build Coastguard Worker 		return 0;
162*de1e4e89SAndroid Build Coastguard Worker 
163*de1e4e89SAndroid Build Coastguard Worker 	if (strcmp(RTA_DATA(li[IFLA_INFO_KIND]), "vrf"))
164*de1e4e89SAndroid Build Coastguard Worker 		return 0;
165*de1e4e89SAndroid Build Coastguard Worker 
166*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr_nested(vrf_attr, IFLA_VRF_MAX, li[IFLA_INFO_DATA]);
167*de1e4e89SAndroid Build Coastguard Worker 	if (vrf_attr[IFLA_VRF_TABLE])
168*de1e4e89SAndroid Build Coastguard Worker 		tb_id = rta_getattr_u32(vrf_attr[IFLA_VRF_TABLE]);
169*de1e4e89SAndroid Build Coastguard Worker 
170*de1e4e89SAndroid Build Coastguard Worker 	if (!tb_id)
171*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "BUG: VRF %s is missing table id\n", name);
172*de1e4e89SAndroid Build Coastguard Worker 
173*de1e4e89SAndroid Build Coastguard Worker 	return tb_id;
174*de1e4e89SAndroid Build Coastguard Worker }
175*de1e4e89SAndroid Build Coastguard Worker 
name_is_vrf(const char * name)176*de1e4e89SAndroid Build Coastguard Worker int name_is_vrf(const char *name)
177*de1e4e89SAndroid Build Coastguard Worker {
178*de1e4e89SAndroid Build Coastguard Worker 	struct {
179*de1e4e89SAndroid Build Coastguard Worker 		struct nlmsghdr		n;
180*de1e4e89SAndroid Build Coastguard Worker 		struct ifinfomsg	i;
181*de1e4e89SAndroid Build Coastguard Worker 		char			buf[1024];
182*de1e4e89SAndroid Build Coastguard Worker 	} req = {
183*de1e4e89SAndroid Build Coastguard Worker 		.n = {
184*de1e4e89SAndroid Build Coastguard Worker 			.nlmsg_len   = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
185*de1e4e89SAndroid Build Coastguard Worker 			.nlmsg_flags = NLM_F_REQUEST,
186*de1e4e89SAndroid Build Coastguard Worker 			.nlmsg_type  = RTM_GETLINK,
187*de1e4e89SAndroid Build Coastguard Worker 		},
188*de1e4e89SAndroid Build Coastguard Worker 		.i = {
189*de1e4e89SAndroid Build Coastguard Worker 			.ifi_family  = preferred_family,
190*de1e4e89SAndroid Build Coastguard Worker 		},
191*de1e4e89SAndroid Build Coastguard Worker 	};
192*de1e4e89SAndroid Build Coastguard Worker 	struct {
193*de1e4e89SAndroid Build Coastguard Worker 		struct nlmsghdr n;
194*de1e4e89SAndroid Build Coastguard Worker 		char buf[8192];
195*de1e4e89SAndroid Build Coastguard Worker 	} answer;
196*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[IFLA_MAX+1];
197*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *li[IFLA_INFO_MAX+1];
198*de1e4e89SAndroid Build Coastguard Worker 	struct ifinfomsg *ifi;
199*de1e4e89SAndroid Build Coastguard Worker 	int len;
200*de1e4e89SAndroid Build Coastguard Worker 
201*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(&req.n, sizeof(req), IFLA_IFNAME, name, strlen(name) + 1);
202*de1e4e89SAndroid Build Coastguard Worker 
203*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_talk_suppress_rtnl_errmsg(&rth, &req.n,
204*de1e4e89SAndroid Build Coastguard Worker 					   &answer.n, sizeof(answer)) < 0)
205*de1e4e89SAndroid Build Coastguard Worker 		return 0;
206*de1e4e89SAndroid Build Coastguard Worker 
207*de1e4e89SAndroid Build Coastguard Worker 	ifi = NLMSG_DATA(&answer.n);
208*de1e4e89SAndroid Build Coastguard Worker 	len = answer.n.nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
209*de1e4e89SAndroid Build Coastguard Worker 	if (len < 0) {
210*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "BUG: Invalid response to link query.\n");
211*de1e4e89SAndroid Build Coastguard Worker 		return 0;
212*de1e4e89SAndroid Build Coastguard Worker 	}
213*de1e4e89SAndroid Build Coastguard Worker 
214*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len);
215*de1e4e89SAndroid Build Coastguard Worker 
216*de1e4e89SAndroid Build Coastguard Worker 	if (!tb[IFLA_LINKINFO])
217*de1e4e89SAndroid Build Coastguard Worker 		return 0;
218*de1e4e89SAndroid Build Coastguard Worker 
219*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr_nested(li, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
220*de1e4e89SAndroid Build Coastguard Worker 
221*de1e4e89SAndroid Build Coastguard Worker 	if (!li[IFLA_INFO_KIND])
222*de1e4e89SAndroid Build Coastguard Worker 		return 0;
223*de1e4e89SAndroid Build Coastguard Worker 
224*de1e4e89SAndroid Build Coastguard Worker 	if (strcmp(RTA_DATA(li[IFLA_INFO_KIND]), "vrf"))
225*de1e4e89SAndroid Build Coastguard Worker 		return 0;
226*de1e4e89SAndroid Build Coastguard Worker 
227*de1e4e89SAndroid Build Coastguard Worker 	return ifi->ifi_index;
228*de1e4e89SAndroid Build Coastguard Worker }
229