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