mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-10-06 02:18:09 +00:00

Replace the iproute2 snapshot with a version string which is autogenerated as part of the build process using git describe. This will also allow seeing if the version of the command is built from the same sources is as upstream. Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
218 lines
4.4 KiB
C
218 lines
4.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Get/set/delete bridge with netlink
|
|
*
|
|
* Authors: Stephen Hemminger <shemminger@vyatta.com>
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
|
|
#include "version.h"
|
|
#include "utils.h"
|
|
#include "br_common.h"
|
|
#include "namespace.h"
|
|
#include "color.h"
|
|
|
|
struct rtnl_handle rth = { .fd = -1 };
|
|
int preferred_family = AF_UNSPEC;
|
|
int oneline;
|
|
int show_stats;
|
|
int show_details;
|
|
static int color;
|
|
int compress_vlans;
|
|
int json;
|
|
int timestamp;
|
|
static const char *batch_file;
|
|
int force;
|
|
|
|
static void usage(void) __attribute__((noreturn));
|
|
|
|
static void usage(void)
|
|
{
|
|
fprintf(stderr,
|
|
"Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n"
|
|
" bridge [ -force ] -batch filename\n"
|
|
"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
|
|
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
|
|
" -o[neline] | -t[imestamp] | -n[etns] name |\n"
|
|
" -c[ompressvlans] -color -p[retty] -j[son] }\n");
|
|
exit(-1);
|
|
}
|
|
|
|
static int do_help(int argc, char **argv)
|
|
{
|
|
usage();
|
|
}
|
|
|
|
|
|
static const struct cmd {
|
|
const char *cmd;
|
|
int (*func)(int argc, char **argv);
|
|
} cmds[] = {
|
|
{ "link", do_link },
|
|
{ "fdb", do_fdb },
|
|
{ "mdb", do_mdb },
|
|
{ "vlan", do_vlan },
|
|
{ "monitor", do_monitor },
|
|
{ "help", do_help },
|
|
{ 0 }
|
|
};
|
|
|
|
static int do_cmd(const char *argv0, int argc, char **argv)
|
|
{
|
|
const struct cmd *c;
|
|
|
|
for (c = cmds; c->cmd; ++c) {
|
|
if (matches(argv0, c->cmd) == 0)
|
|
return c->func(argc-1, argv+1);
|
|
}
|
|
|
|
fprintf(stderr,
|
|
"Object \"%s\" is unknown, try \"bridge help\".\n", argv0);
|
|
return -1;
|
|
}
|
|
|
|
static int batch(const char *name)
|
|
{
|
|
char *line = NULL;
|
|
size_t len = 0;
|
|
int ret = EXIT_SUCCESS;
|
|
|
|
if (name && strcmp(name, "-") != 0) {
|
|
if (freopen(name, "r", stdin) == NULL) {
|
|
fprintf(stderr,
|
|
"Cannot open file \"%s\" for reading: %s\n",
|
|
name, strerror(errno));
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (rtnl_open(&rth, 0) < 0) {
|
|
fprintf(stderr, "Cannot open rtnetlink\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
rtnl_set_strict_dump(&rth);
|
|
|
|
cmdlineno = 0;
|
|
while (getcmdline(&line, &len, stdin) != -1) {
|
|
char *largv[100];
|
|
int largc;
|
|
|
|
largc = makeargs(line, largv, 100);
|
|
if (largc == 0)
|
|
continue; /* blank line */
|
|
|
|
if (do_cmd(largv[0], largc, largv)) {
|
|
fprintf(stderr, "Command failed %s:%d\n",
|
|
name, cmdlineno);
|
|
ret = EXIT_FAILURE;
|
|
if (!force)
|
|
break;
|
|
}
|
|
}
|
|
if (line)
|
|
free(line);
|
|
|
|
rtnl_close(&rth);
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
while (argc > 1) {
|
|
const char *opt = argv[1];
|
|
|
|
if (strcmp(opt, "--") == 0) {
|
|
argc--; argv++;
|
|
break;
|
|
}
|
|
if (opt[0] != '-')
|
|
break;
|
|
if (opt[1] == '-')
|
|
opt++;
|
|
|
|
if (matches(opt, "-help") == 0) {
|
|
usage();
|
|
} else if (matches(opt, "-Version") == 0) {
|
|
printf("bridge utility, 0.0\n");
|
|
exit(0);
|
|
} else if (matches(opt, "-stats") == 0 ||
|
|
matches(opt, "-statistics") == 0) {
|
|
++show_stats;
|
|
} else if (matches(opt, "-details") == 0) {
|
|
++show_details;
|
|
} else if (matches(opt, "-oneline") == 0) {
|
|
++oneline;
|
|
} else if (matches(opt, "-timestamp") == 0) {
|
|
++timestamp;
|
|
} else if (matches(opt, "-family") == 0) {
|
|
argc--;
|
|
argv++;
|
|
if (argc <= 1)
|
|
usage();
|
|
if (strcmp(argv[1], "inet") == 0)
|
|
preferred_family = AF_INET;
|
|
else if (strcmp(argv[1], "inet6") == 0)
|
|
preferred_family = AF_INET6;
|
|
else if (strcmp(argv[1], "help") == 0)
|
|
usage();
|
|
else
|
|
invarg("invalid protocol family", argv[1]);
|
|
} else if (strcmp(opt, "-4") == 0) {
|
|
preferred_family = AF_INET;
|
|
} else if (strcmp(opt, "-6") == 0) {
|
|
preferred_family = AF_INET6;
|
|
} else if (matches(opt, "-netns") == 0) {
|
|
NEXT_ARG();
|
|
if (netns_switch(argv[1]))
|
|
exit(-1);
|
|
} else if (matches(opt, "-compressvlans") == 0) {
|
|
++compress_vlans;
|
|
} else if (matches_color(opt, &color)) {
|
|
} else if (matches(opt, "-force") == 0) {
|
|
++force;
|
|
} else if (matches(opt, "-json") == 0) {
|
|
++json;
|
|
} else if (matches(opt, "-pretty") == 0) {
|
|
++pretty;
|
|
} else if (matches(opt, "-batch") == 0) {
|
|
argc--;
|
|
argv++;
|
|
if (argc <= 1)
|
|
usage();
|
|
batch_file = argv[1];
|
|
} else {
|
|
fprintf(stderr,
|
|
"Option \"%s\" is unknown, try \"bridge help\".\n",
|
|
opt);
|
|
exit(-1);
|
|
}
|
|
argc--; argv++;
|
|
}
|
|
|
|
_SL_ = oneline ? "\\" : "\n";
|
|
|
|
check_enable_color(color, json);
|
|
|
|
if (batch_file)
|
|
return batch(batch_file);
|
|
|
|
if (rtnl_open(&rth, 0) < 0)
|
|
exit(1);
|
|
|
|
rtnl_set_strict_dump(&rth);
|
|
|
|
if (argc > 1)
|
|
return do_cmd(argv[1], argc-1, argv+1);
|
|
|
|
rtnl_close(&rth);
|
|
usage();
|
|
}
|