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