xref: /aosp_15_r20/external/iproute2/bridge/bridge.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * Get/set/delete bridge with netlink
3*de1e4e89SAndroid Build Coastguard Worker  *
4*de1e4e89SAndroid Build Coastguard Worker  * Authors:	Stephen Hemminger <[email protected]>
5*de1e4e89SAndroid Build Coastguard Worker  */
6*de1e4e89SAndroid Build Coastguard Worker 
7*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
8*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
9*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
10*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
11*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
12*de1e4e89SAndroid Build Coastguard Worker #include <errno.h>
13*de1e4e89SAndroid Build Coastguard Worker 
14*de1e4e89SAndroid Build Coastguard Worker #include "SNAPSHOT.h"
15*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
16*de1e4e89SAndroid Build Coastguard Worker #include "br_common.h"
17*de1e4e89SAndroid Build Coastguard Worker #include "namespace.h"
18*de1e4e89SAndroid Build Coastguard Worker 
19*de1e4e89SAndroid Build Coastguard Worker struct rtnl_handle rth = { .fd = -1 };
20*de1e4e89SAndroid Build Coastguard Worker int preferred_family = AF_UNSPEC;
21*de1e4e89SAndroid Build Coastguard Worker int oneline;
22*de1e4e89SAndroid Build Coastguard Worker int show_stats;
23*de1e4e89SAndroid Build Coastguard Worker int show_details;
24*de1e4e89SAndroid Build Coastguard Worker int compress_vlans;
25*de1e4e89SAndroid Build Coastguard Worker int json_output;
26*de1e4e89SAndroid Build Coastguard Worker int timestamp;
27*de1e4e89SAndroid Build Coastguard Worker char *batch_file;
28*de1e4e89SAndroid Build Coastguard Worker int force;
29*de1e4e89SAndroid Build Coastguard Worker const char *_SL_;
30*de1e4e89SAndroid Build Coastguard Worker 
31*de1e4e89SAndroid Build Coastguard Worker static void usage(void) __attribute__((noreturn));
32*de1e4e89SAndroid Build Coastguard Worker 
usage(void)33*de1e4e89SAndroid Build Coastguard Worker static void usage(void)
34*de1e4e89SAndroid Build Coastguard Worker {
35*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr,
36*de1e4e89SAndroid Build Coastguard Worker "Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n"
37*de1e4e89SAndroid Build Coastguard Worker "       bridge [ -force ] -batch filename\n"
38*de1e4e89SAndroid Build Coastguard Worker "where	OBJECT := { link | fdb | mdb | vlan | monitor }\n"
39*de1e4e89SAndroid Build Coastguard Worker "	OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
40*de1e4e89SAndroid Build Coastguard Worker "		     -o[neline] | -t[imestamp] | -n[etns] name |\n"
41*de1e4e89SAndroid Build Coastguard Worker "		     -c[ompressvlans] -j{son} }\n");
42*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
43*de1e4e89SAndroid Build Coastguard Worker }
44*de1e4e89SAndroid Build Coastguard Worker 
do_help(int argc,char ** argv)45*de1e4e89SAndroid Build Coastguard Worker static int do_help(int argc, char **argv)
46*de1e4e89SAndroid Build Coastguard Worker {
47*de1e4e89SAndroid Build Coastguard Worker 	usage();
48*de1e4e89SAndroid Build Coastguard Worker }
49*de1e4e89SAndroid Build Coastguard Worker 
50*de1e4e89SAndroid Build Coastguard Worker 
51*de1e4e89SAndroid Build Coastguard Worker static const struct cmd {
52*de1e4e89SAndroid Build Coastguard Worker 	const char *cmd;
53*de1e4e89SAndroid Build Coastguard Worker 	int (*func)(int argc, char **argv);
54*de1e4e89SAndroid Build Coastguard Worker } cmds[] = {
55*de1e4e89SAndroid Build Coastguard Worker 	{ "link",	do_link },
56*de1e4e89SAndroid Build Coastguard Worker 	{ "fdb",	do_fdb },
57*de1e4e89SAndroid Build Coastguard Worker 	{ "mdb",	do_mdb },
58*de1e4e89SAndroid Build Coastguard Worker 	{ "vlan",	do_vlan },
59*de1e4e89SAndroid Build Coastguard Worker 	{ "monitor",	do_monitor },
60*de1e4e89SAndroid Build Coastguard Worker 	{ "help",	do_help },
61*de1e4e89SAndroid Build Coastguard Worker 	{ 0 }
62*de1e4e89SAndroid Build Coastguard Worker };
63*de1e4e89SAndroid Build Coastguard Worker 
do_cmd(const char * argv0,int argc,char ** argv)64*de1e4e89SAndroid Build Coastguard Worker static int do_cmd(const char *argv0, int argc, char **argv)
65*de1e4e89SAndroid Build Coastguard Worker {
66*de1e4e89SAndroid Build Coastguard Worker 	const struct cmd *c;
67*de1e4e89SAndroid Build Coastguard Worker 
68*de1e4e89SAndroid Build Coastguard Worker 	for (c = cmds; c->cmd; ++c) {
69*de1e4e89SAndroid Build Coastguard Worker 		if (matches(argv0, c->cmd) == 0)
70*de1e4e89SAndroid Build Coastguard Worker 			return c->func(argc-1, argv+1);
71*de1e4e89SAndroid Build Coastguard Worker 	}
72*de1e4e89SAndroid Build Coastguard Worker 
73*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr,
74*de1e4e89SAndroid Build Coastguard Worker 		"Object \"%s\" is unknown, try \"bridge help\".\n", argv0);
75*de1e4e89SAndroid Build Coastguard Worker 	return -1;
76*de1e4e89SAndroid Build Coastguard Worker }
77*de1e4e89SAndroid Build Coastguard Worker 
batch(const char * name)78*de1e4e89SAndroid Build Coastguard Worker static int batch(const char *name)
79*de1e4e89SAndroid Build Coastguard Worker {
80*de1e4e89SAndroid Build Coastguard Worker 	char *line = NULL;
81*de1e4e89SAndroid Build Coastguard Worker 	size_t len = 0;
82*de1e4e89SAndroid Build Coastguard Worker 	int ret = EXIT_SUCCESS;
83*de1e4e89SAndroid Build Coastguard Worker 
84*de1e4e89SAndroid Build Coastguard Worker 	if (name && strcmp(name, "-") != 0) {
85*de1e4e89SAndroid Build Coastguard Worker 		if (freopen(name, "r", stdin) == NULL) {
86*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr,
87*de1e4e89SAndroid Build Coastguard Worker 				"Cannot open file \"%s\" for reading: %s\n",
88*de1e4e89SAndroid Build Coastguard Worker 				name, strerror(errno));
89*de1e4e89SAndroid Build Coastguard Worker 			return EXIT_FAILURE;
90*de1e4e89SAndroid Build Coastguard Worker 		}
91*de1e4e89SAndroid Build Coastguard Worker 	}
92*de1e4e89SAndroid Build Coastguard Worker 
93*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_open(&rth, 0) < 0) {
94*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "Cannot open rtnetlink\n");
95*de1e4e89SAndroid Build Coastguard Worker 		return EXIT_FAILURE;
96*de1e4e89SAndroid Build Coastguard Worker 	}
97*de1e4e89SAndroid Build Coastguard Worker 
98*de1e4e89SAndroid Build Coastguard Worker 	cmdlineno = 0;
99*de1e4e89SAndroid Build Coastguard Worker 	while (getcmdline(&line, &len, stdin) != -1) {
100*de1e4e89SAndroid Build Coastguard Worker 		char *largv[100];
101*de1e4e89SAndroid Build Coastguard Worker 		int largc;
102*de1e4e89SAndroid Build Coastguard Worker 
103*de1e4e89SAndroid Build Coastguard Worker 		largc = makeargs(line, largv, 100);
104*de1e4e89SAndroid Build Coastguard Worker 		if (largc == 0)
105*de1e4e89SAndroid Build Coastguard Worker 			continue;       /* blank line */
106*de1e4e89SAndroid Build Coastguard Worker 
107*de1e4e89SAndroid Build Coastguard Worker 		if (do_cmd(largv[0], largc, largv)) {
108*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "Command failed %s:%d\n",
109*de1e4e89SAndroid Build Coastguard Worker 				name, cmdlineno);
110*de1e4e89SAndroid Build Coastguard Worker 			ret = EXIT_FAILURE;
111*de1e4e89SAndroid Build Coastguard Worker 			if (!force)
112*de1e4e89SAndroid Build Coastguard Worker 				break;
113*de1e4e89SAndroid Build Coastguard Worker 		}
114*de1e4e89SAndroid Build Coastguard Worker 	}
115*de1e4e89SAndroid Build Coastguard Worker 	if (line)
116*de1e4e89SAndroid Build Coastguard Worker 		free(line);
117*de1e4e89SAndroid Build Coastguard Worker 
118*de1e4e89SAndroid Build Coastguard Worker 	rtnl_close(&rth);
119*de1e4e89SAndroid Build Coastguard Worker 	return ret;
120*de1e4e89SAndroid Build Coastguard Worker }
121*de1e4e89SAndroid Build Coastguard Worker 
122*de1e4e89SAndroid Build Coastguard Worker int
main(int argc,char ** argv)123*de1e4e89SAndroid Build Coastguard Worker main(int argc, char **argv)
124*de1e4e89SAndroid Build Coastguard Worker {
125*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 1) {
126*de1e4e89SAndroid Build Coastguard Worker 		const char *opt = argv[1];
127*de1e4e89SAndroid Build Coastguard Worker 
128*de1e4e89SAndroid Build Coastguard Worker 		if (strcmp(opt, "--") == 0) {
129*de1e4e89SAndroid Build Coastguard Worker 			argc--; argv++;
130*de1e4e89SAndroid Build Coastguard Worker 			break;
131*de1e4e89SAndroid Build Coastguard Worker 		}
132*de1e4e89SAndroid Build Coastguard Worker 		if (opt[0] != '-')
133*de1e4e89SAndroid Build Coastguard Worker 			break;
134*de1e4e89SAndroid Build Coastguard Worker 		if (opt[1] == '-')
135*de1e4e89SAndroid Build Coastguard Worker 			opt++;
136*de1e4e89SAndroid Build Coastguard Worker 
137*de1e4e89SAndroid Build Coastguard Worker 		if (matches(opt, "-help") == 0) {
138*de1e4e89SAndroid Build Coastguard Worker 			usage();
139*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-Version") == 0) {
140*de1e4e89SAndroid Build Coastguard Worker 			printf("bridge utility, 0.0\n");
141*de1e4e89SAndroid Build Coastguard Worker 			exit(0);
142*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-stats") == 0 ||
143*de1e4e89SAndroid Build Coastguard Worker 			   matches(opt, "-statistics") == 0) {
144*de1e4e89SAndroid Build Coastguard Worker 			++show_stats;
145*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-details") == 0) {
146*de1e4e89SAndroid Build Coastguard Worker 			++show_details;
147*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-oneline") == 0) {
148*de1e4e89SAndroid Build Coastguard Worker 			++oneline;
149*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-timestamp") == 0) {
150*de1e4e89SAndroid Build Coastguard Worker 			++timestamp;
151*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-family") == 0) {
152*de1e4e89SAndroid Build Coastguard Worker 			argc--;
153*de1e4e89SAndroid Build Coastguard Worker 			argv++;
154*de1e4e89SAndroid Build Coastguard Worker 			if (argc <= 1)
155*de1e4e89SAndroid Build Coastguard Worker 				usage();
156*de1e4e89SAndroid Build Coastguard Worker 			if (strcmp(argv[1], "inet") == 0)
157*de1e4e89SAndroid Build Coastguard Worker 				preferred_family = AF_INET;
158*de1e4e89SAndroid Build Coastguard Worker 			else if (strcmp(argv[1], "inet6") == 0)
159*de1e4e89SAndroid Build Coastguard Worker 				preferred_family = AF_INET6;
160*de1e4e89SAndroid Build Coastguard Worker 			else if (strcmp(argv[1], "help") == 0)
161*de1e4e89SAndroid Build Coastguard Worker 				usage();
162*de1e4e89SAndroid Build Coastguard Worker 			else
163*de1e4e89SAndroid Build Coastguard Worker 				invarg("invalid protocol family", argv[1]);
164*de1e4e89SAndroid Build Coastguard Worker 		} else if (strcmp(opt, "-4") == 0) {
165*de1e4e89SAndroid Build Coastguard Worker 			preferred_family = AF_INET;
166*de1e4e89SAndroid Build Coastguard Worker 		} else if (strcmp(opt, "-6") == 0) {
167*de1e4e89SAndroid Build Coastguard Worker 			preferred_family = AF_INET6;
168*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-netns") == 0) {
169*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
170*de1e4e89SAndroid Build Coastguard Worker 			if (netns_switch(argv[1]))
171*de1e4e89SAndroid Build Coastguard Worker 				exit(-1);
172*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-compressvlans") == 0) {
173*de1e4e89SAndroid Build Coastguard Worker 			++compress_vlans;
174*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-force") == 0) {
175*de1e4e89SAndroid Build Coastguard Worker 			++force;
176*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-json") == 0) {
177*de1e4e89SAndroid Build Coastguard Worker 			++json_output;
178*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(opt, "-batch") == 0) {
179*de1e4e89SAndroid Build Coastguard Worker 			argc--;
180*de1e4e89SAndroid Build Coastguard Worker 			argv++;
181*de1e4e89SAndroid Build Coastguard Worker 			if (argc <= 1)
182*de1e4e89SAndroid Build Coastguard Worker 				usage();
183*de1e4e89SAndroid Build Coastguard Worker 			batch_file = argv[1];
184*de1e4e89SAndroid Build Coastguard Worker 		} else {
185*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr,
186*de1e4e89SAndroid Build Coastguard Worker 				"Option \"%s\" is unknown, try \"bridge help\".\n",
187*de1e4e89SAndroid Build Coastguard Worker 				opt);
188*de1e4e89SAndroid Build Coastguard Worker 			exit(-1);
189*de1e4e89SAndroid Build Coastguard Worker 		}
190*de1e4e89SAndroid Build Coastguard Worker 		argc--;	argv++;
191*de1e4e89SAndroid Build Coastguard Worker 	}
192*de1e4e89SAndroid Build Coastguard Worker 
193*de1e4e89SAndroid Build Coastguard Worker 	_SL_ = oneline ? "\\" : "\n";
194*de1e4e89SAndroid Build Coastguard Worker 
195*de1e4e89SAndroid Build Coastguard Worker 	if (batch_file)
196*de1e4e89SAndroid Build Coastguard Worker 		return batch(batch_file);
197*de1e4e89SAndroid Build Coastguard Worker 
198*de1e4e89SAndroid Build Coastguard Worker 	if (rtnl_open(&rth, 0) < 0)
199*de1e4e89SAndroid Build Coastguard Worker 		exit(1);
200*de1e4e89SAndroid Build Coastguard Worker 
201*de1e4e89SAndroid Build Coastguard Worker 	if (argc > 1)
202*de1e4e89SAndroid Build Coastguard Worker 		return do_cmd(argv[1], argc-1, argv+1);
203*de1e4e89SAndroid Build Coastguard Worker 
204*de1e4e89SAndroid Build Coastguard Worker 	rtnl_close(&rth);
205*de1e4e89SAndroid Build Coastguard Worker 	usage();
206*de1e4e89SAndroid Build Coastguard Worker }
207