MOD aaa-12 调整ipconfig目录,重命名为netconfig
SOL configm运行目录调整到/tmp/configm 修改人:zhangliang 检视人:zhangliang
This commit is contained in:
parent
b434ecb453
commit
54bba96dfe
|
@ -26,7 +26,7 @@ VPATH = ../user/configm/config-server ../user/configm/config-server/user_manager
|
|||
|
||||
# set the source file, don't used .o because of ...
|
||||
|
||||
COMMON_SRCS = configserver.c ipconfig/ipconfig.c ipconfig/parsefile.c \
|
||||
COMMON_SRCS = configserver.c netconfig/ipconfig/ipconfig.c netconfig/parsefile.c \
|
||||
authfree_config/authfree.c localportal_config/localportal.c userlock_config/userlock.c jumppage_config/jumppage.c agingtime_config/agingtime.c \
|
||||
user_group_config.c user_account_config.c usermanager-server/array_index.c usermanager-server/user_group.c usermanager-server/user_mod.c usermanager-server/user.c
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
KERNEL_HEADERS=-I@KERNEL_HEADERS@
|
||||
|
||||
CC=@CC@
|
||||
CFLAGS= -Wall @CFLAGS@
|
||||
LDFLAGS=@LDFLAGS@
|
||||
INCLUDE=-I../libbridge $(KERNEL_HEADERS)
|
||||
LIBS= -L ../libbridge -lbridge @LIBS@
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
bindir=@bindir@
|
||||
sbindir=@sbindir@
|
||||
mandir=@mandir@
|
||||
|
||||
INSTALL=@INSTALL@
|
||||
|
||||
|
||||
common_SOURCES= brctl_cmd.c brctl_disp.c
|
||||
brctl_SOURCES= brctl.c $(common_SOURCES)
|
||||
|
||||
common_OBJECTS= $(common_SOURCES:.c=.o)
|
||||
brctl_OBJECTS= $(brctl_SOURCES:.c=.o)
|
||||
|
||||
OBJECTS= $(common_OBJECTS) $(brctl_OBJECTS)
|
||||
|
||||
PROGRAMS= brctl
|
||||
|
||||
|
||||
all: $(PROGRAMS)
|
||||
|
||||
install: $(PROGRAMS)
|
||||
mkdir -p $(DESTDIR)$(sbindir)
|
||||
$(INSTALL) -m 755 $(PROGRAMS) $(DESTDIR)$(sbindir)
|
||||
|
||||
brctl: $(brctl_OBJECTS) ../libbridge/libbridge.a
|
||||
$(CC) $(LDFLAGS) $(brctl_OBJECTS) $(LIBS) -o brctl
|
||||
|
||||
%.o: %.c brctl.h
|
||||
$(CC) $(CFLAGS) $(INCLUDE) -c $<
|
||||
|
||||
clean:
|
||||
rm -f *.o brctl core
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Lennert Buytenhek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include "libbridge.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "brctl.h"
|
||||
|
||||
static void help()
|
||||
{
|
||||
printf("Usage: brctl [commands]\n");
|
||||
printf("commands:\n");
|
||||
command_helpall();
|
||||
}
|
||||
|
||||
int main(int argc, char *const* argv)
|
||||
{
|
||||
const struct command *cmd;
|
||||
int f;
|
||||
static const struct option options[] = {
|
||||
{ .name = "help", .val = 'h' },
|
||||
{ .name = "version", .val = 'V' },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
while ((f = getopt_long(argc, argv, "Vh", options, NULL)) != EOF)
|
||||
switch(f) {
|
||||
case 'h':
|
||||
help();
|
||||
return 0;
|
||||
case 'V':
|
||||
printf("%s, %s\n", PACKAGE_NAME, PACKAGE_VERSION);
|
||||
return 0;
|
||||
default:
|
||||
fprintf(stderr, "Unknown option '%c'\n", f);
|
||||
goto help;
|
||||
}
|
||||
|
||||
if (argc == optind)
|
||||
goto help;
|
||||
|
||||
if (br_init()) {
|
||||
fprintf(stderr, "can't setup bridge control: %s\n",
|
||||
strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if ((cmd = command_lookup(*argv)) == NULL) {
|
||||
fprintf(stderr, "never heard of command [%s]\n", *argv);
|
||||
goto help;
|
||||
}
|
||||
|
||||
if (argc < cmd->nargs + 1) {
|
||||
printf("Incorrect number of arguments for command\n");
|
||||
printf("Usage: brctl %s %s\n", cmd->name, cmd->help);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return cmd->func(argc, argv);
|
||||
|
||||
help:
|
||||
help();
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Lennert Buytenhek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _BRCTL_H
|
||||
#define _BRCTL_H
|
||||
|
||||
struct command
|
||||
{
|
||||
int nargs;
|
||||
const char *name;
|
||||
int (*func)(int argc, char *const* argv);
|
||||
const char *help;
|
||||
};
|
||||
|
||||
const struct command *command_lookup(const char *cmd);
|
||||
void command_help(const struct command *);
|
||||
void command_helpall(void);
|
||||
|
||||
void br_dump_bridge_id(const unsigned char *x);
|
||||
void br_show_timer(const struct timeval *tv);
|
||||
void br_dump_interface_list(const char *br);
|
||||
void br_dump_info(const char *br, const struct bridge_info *bri);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,503 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Lennert Buytenhek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include <asm/param.h>
|
||||
#include "libbridge.h"
|
||||
#include "brctl.h"
|
||||
|
||||
static int strtotimeval(struct timeval *tv, const char *time)
|
||||
{
|
||||
double secs;
|
||||
if (sscanf(time, "%lf", &secs) != 1)
|
||||
return -1;
|
||||
tv->tv_sec = secs;
|
||||
tv->tv_usec = 1000000 * (secs - tv->tv_sec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int br_cmd_addbr(int argc, char*const* argv)
|
||||
{
|
||||
int err;
|
||||
|
||||
switch (err = br_add_bridge(argv[1])) {
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case EEXIST:
|
||||
fprintf(stderr, "device %s already exists; can't create "
|
||||
"bridge with the same name\n", argv[1]);
|
||||
return 1;
|
||||
default:
|
||||
fprintf(stderr, "add bridge failed: %s\n",
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int br_cmd_delbr(int argc, char*const* argv)
|
||||
{
|
||||
int err;
|
||||
|
||||
switch (err = br_del_bridge(argv[1])){
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case ENXIO:
|
||||
fprintf(stderr, "bridge %s doesn't exist; can't delete it\n",
|
||||
argv[1]);
|
||||
return 1;
|
||||
|
||||
case EBUSY:
|
||||
fprintf(stderr, "bridge %s is still up; can't delete it\n",
|
||||
argv[1]);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "can't delete bridge %s: %s\n",
|
||||
argv[1], strerror(err));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int br_cmd_addif(int argc, char *const* argv)
|
||||
{
|
||||
const char *brname;
|
||||
int err;
|
||||
|
||||
argc -= 2;
|
||||
brname = *++argv;
|
||||
|
||||
while (argc-- > 0) {
|
||||
const char *ifname = *++argv;
|
||||
err = br_add_interface(brname, ifname);
|
||||
|
||||
switch(err) {
|
||||
case 0:
|
||||
continue;
|
||||
|
||||
case ENODEV:
|
||||
if (if_nametoindex(ifname) == 0)
|
||||
fprintf(stderr, "interface %s does not exist!\n", ifname);
|
||||
else
|
||||
fprintf(stderr, "bridge %s does not exist!\n", brname);
|
||||
break;
|
||||
|
||||
case EBUSY:
|
||||
fprintf(stderr, "device %s is already a member of a bridge; "
|
||||
"can't enslave it to bridge %s.\n", ifname,
|
||||
brname);
|
||||
break;
|
||||
|
||||
case ELOOP:
|
||||
fprintf(stderr, "device %s is a bridge device itself; "
|
||||
"can't enslave a bridge device to a bridge device.\n",
|
||||
ifname);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "can't add %s to bridge %s: %s\n",
|
||||
ifname, brname, strerror(err));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int br_cmd_delif(int argc, char *const* argv)
|
||||
{
|
||||
const char *brname;
|
||||
int err;
|
||||
|
||||
argc -= 2;
|
||||
brname = *++argv;
|
||||
|
||||
while (argc-- > 0) {
|
||||
const char *ifname = *++argv;
|
||||
err = br_del_interface(brname, ifname);
|
||||
switch (err) {
|
||||
case 0:
|
||||
continue;
|
||||
|
||||
case ENODEV:
|
||||
if (if_nametoindex(ifname) == 0)
|
||||
fprintf(stderr, "interface %s does not exist!\n", ifname);
|
||||
else
|
||||
fprintf(stderr, "bridge %s does not exist!\n", brname);
|
||||
break;
|
||||
|
||||
case EINVAL:
|
||||
fprintf(stderr, "device %s is not a slave of %s\n",
|
||||
ifname, brname);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "can't delete %s from %s: %s\n",
|
||||
ifname, brname, strerror(err));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int br_cmd_setageing(int argc, char *const* argv)
|
||||
{
|
||||
int err;
|
||||
struct timeval tv;
|
||||
|
||||
if (strtotimeval(&tv, argv[2])) {
|
||||
fprintf(stderr, "bad ageing time value\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = br_set_ageing_time(argv[1], &tv);
|
||||
if (err)
|
||||
fprintf(stderr, "set ageing time failed: %s\n",
|
||||
strerror(err));
|
||||
|
||||
return err != 0;
|
||||
}
|
||||
|
||||
static int br_cmd_setbridgeprio(int argc, char *const* argv)
|
||||
{
|
||||
int prio;
|
||||
int err;
|
||||
|
||||
if (sscanf(argv[2], "%i", &prio) != 1) {
|
||||
fprintf(stderr,"bad priority\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = br_set_bridge_priority(argv[1], prio);
|
||||
if (err)
|
||||
fprintf(stderr, "set bridge priority failed: %s\n",
|
||||
strerror(err));
|
||||
return err != 0;
|
||||
}
|
||||
|
||||
static int br_cmd_setfd(int argc, char *const* argv)
|
||||
{
|
||||
struct timeval tv;
|
||||
int err;
|
||||
|
||||
if (strtotimeval(&tv, argv[2])) {
|
||||
fprintf(stderr, "bad forward delay value\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = br_set_bridge_forward_delay(argv[1], &tv);
|
||||
if (err)
|
||||
fprintf(stderr, "set forward delay failed: %s\n",
|
||||
strerror(err));
|
||||
|
||||
return err != 0;
|
||||
}
|
||||
|
||||
static int br_cmd_sethello(int argc, char *const* argv)
|
||||
{
|
||||
struct timeval tv;
|
||||
int err;
|
||||
|
||||
if (strtotimeval(&tv, argv[2])) {
|
||||
fprintf(stderr, "bad hello timer value\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = br_set_bridge_hello_time(argv[1], &tv);
|
||||
if (err)
|
||||
fprintf(stderr, "set hello timer failed: %s\n",
|
||||
strerror(err));
|
||||
|
||||
return err != 0;
|
||||
}
|
||||
|
||||
static int br_cmd_setmaxage(int argc, char *const* argv)
|
||||
{
|
||||
struct timeval tv;
|
||||
int err;
|
||||
|
||||
if (strtotimeval(&tv, argv[2])) {
|
||||
fprintf(stderr, "bad max age value\n");
|
||||
return 1;
|
||||
}
|
||||
err = br_set_bridge_max_age(argv[1], &tv);
|
||||
if (err)
|
||||
fprintf(stderr, "set max age failed: %s\n",
|
||||
strerror(err));
|
||||
|
||||
return err != 0;
|
||||
}
|
||||
|
||||
static int br_cmd_setpathcost(int argc, char *const* argv)
|
||||
{
|
||||
int cost, err;
|
||||
|
||||
if (sscanf(argv[3], "%i", &cost) != 1) {
|
||||
fprintf(stderr, "bad path cost value\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = br_set_path_cost(argv[1], argv[2], cost);
|
||||
if (err)
|
||||
fprintf(stderr, "set path cost failed: %s\n",
|
||||
strerror(err));
|
||||
return err != 0;
|
||||
}
|
||||
|
||||
static int br_cmd_setportprio(int argc, char *const* argv)
|
||||
{
|
||||
int cost, err;
|
||||
|
||||
if (sscanf(argv[3], "%i", &cost) != 1) {
|
||||
fprintf(stderr, "bad path priority value\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = br_set_port_priority(argv[1], argv[2], cost);
|
||||
if (err)
|
||||
fprintf(stderr, "set port priority failed: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
return err != 0;
|
||||
}
|
||||
|
||||
static int br_cmd_stp(int argc, char *const* argv)
|
||||
{
|
||||
int stp, err;
|
||||
|
||||
if (!strcmp(argv[2], "on") || !strcmp(argv[2], "yes")
|
||||
|| !strcmp(argv[2], "1"))
|
||||
stp = 1;
|
||||
else if (!strcmp(argv[2], "off") || !strcmp(argv[2], "no")
|
||||
|| !strcmp(argv[2], "0"))
|
||||
stp = 0;
|
||||
else {
|
||||
fprintf(stderr, "expect on/off for argument\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = br_set_stp_state(argv[1], stp);
|
||||
if (err)
|
||||
fprintf(stderr, "set stp status failed: %s\n",
|
||||
strerror(errno));
|
||||
return err != 0;
|
||||
}
|
||||
|
||||
static int br_cmd_showstp(int argc, char *const* argv)
|
||||
{
|
||||
struct bridge_info info;
|
||||
const char *name = argv[1];
|
||||
|
||||
if (br_get_bridge_info(name, &info)) {
|
||||
if (errno == ENODEV)
|
||||
fprintf(stderr, "bridge %s does not exist!\n", name);
|
||||
else
|
||||
fprintf(stderr, "device %s is not a bridge!\n", name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
br_dump_info(name, &info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_bridge(const char *name, void *arg)
|
||||
{
|
||||
struct bridge_info info;
|
||||
static int show_header = 1;
|
||||
|
||||
if (br_get_bridge_info(name, &info)) {
|
||||
if (errno == ENODEV)
|
||||
fprintf(stderr, "bridge %s does not exist!\n", name);
|
||||
else
|
||||
fprintf(stderr, "device %s is not a bridge!\n", name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (show_header) {
|
||||
printf("bridge name\tbridge id\t\tSTP enabled\tinterfaces\n");
|
||||
show_header = 0;
|
||||
}
|
||||
|
||||
printf("%s\t\t", name);
|
||||
br_dump_bridge_id((unsigned char *)&info.bridge_id);
|
||||
printf("\t%s\t\t", info.stp_enabled?"yes":"no");
|
||||
|
||||
br_dump_interface_list(name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int br_cmd_show(int argc, char *const* argv)
|
||||
{
|
||||
int i, errs = 0;
|
||||
|
||||
if (argc == 1)
|
||||
br_foreach_bridge(show_bridge, NULL);
|
||||
else
|
||||
for(i = 2; i <= argc; i++)
|
||||
errs += show_bridge(argv[i - 1], NULL);
|
||||
|
||||
return errs > 0;
|
||||
}
|
||||
|
||||
static int compare_fdbs(const void *_f0, const void *_f1)
|
||||
{
|
||||
const struct fdb_entry *f0 = _f0;
|
||||
const struct fdb_entry *f1 = _f1;
|
||||
|
||||
return memcmp(f0->mac_addr, f1->mac_addr, 6);
|
||||
}
|
||||
|
||||
static int br_cmd_showmacs(int argc, char *const* argv)
|
||||
{
|
||||
const char *brname = argv[1];
|
||||
#define CHUNK 128
|
||||
int i, n;
|
||||
struct fdb_entry *fdb = NULL;
|
||||
int offset = 0;
|
||||
|
||||
for(;;) {
|
||||
fdb = realloc(fdb, (offset + CHUNK) * sizeof(struct fdb_entry));
|
||||
if (!fdb) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
n = br_read_fdb(brname, fdb+offset, offset, CHUNK);
|
||||
if (n == 0)
|
||||
break;
|
||||
|
||||
if (n < 0) {
|
||||
fprintf(stderr, "read of forward table failed: %s\n",
|
||||
strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
offset += n;
|
||||
}
|
||||
|
||||
qsort(fdb, offset, sizeof(struct fdb_entry), compare_fdbs);
|
||||
|
||||
printf("port no\tmac addr\t\tis local?\tageing timer\n");
|
||||
for (i = 0; i < offset; i++) {
|
||||
const struct fdb_entry *f = fdb + i;
|
||||
printf("%3i\t", f->port_no);
|
||||
printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t",
|
||||
f->mac_addr[0], f->mac_addr[1], f->mac_addr[2],
|
||||
f->mac_addr[3], f->mac_addr[4], f->mac_addr[5]);
|
||||
printf("%s\t\t", f->is_local?"yes":"no");
|
||||
br_show_timer(&f->ageing_timer_value);
|
||||
printf("\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int br_cmd_hairpin(int argc, char *const* argv)
|
||||
{
|
||||
int hairpin, err;
|
||||
const char *brname = *++argv;
|
||||
const char *ifname = *++argv;
|
||||
const char *hpmode = *++argv;
|
||||
|
||||
if (!strcmp(hpmode, "on") || !strcmp(hpmode, "yes")
|
||||
|| !strcmp(hpmode, "1"))
|
||||
hairpin = 1;
|
||||
else if (!strcmp(hpmode, "off") || !strcmp(hpmode, "no")
|
||||
|| !strcmp(hpmode, "0"))
|
||||
hairpin = 0;
|
||||
else {
|
||||
fprintf(stderr, "expect on/off for argument\n");
|
||||
return 1;
|
||||
}
|
||||
if (if_nametoindex(ifname) == 0) {
|
||||
fprintf(stderr, "interface %s does not exist!\n",
|
||||
ifname);
|
||||
return 1;
|
||||
} else if (if_nametoindex(brname) == 0) {
|
||||
fprintf(stderr, "bridge %s does not exist!\n",
|
||||
brname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = br_set_hairpin_mode(brname, ifname, hairpin);
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr, "can't set %s to hairpin on bridge %s: %s\n",
|
||||
ifname, brname, strerror(err));
|
||||
}
|
||||
return err != 0;
|
||||
}
|
||||
|
||||
static const struct command commands[] = {
|
||||
{ 1, "addbr", br_cmd_addbr, "<bridge>\t\tadd bridge" },
|
||||
{ 1, "delbr", br_cmd_delbr, "<bridge>\t\tdelete bridge" },
|
||||
{ 2, "addif", br_cmd_addif,
|
||||
"<bridge> <device>\tadd interface to bridge" },
|
||||
{ 2, "delif", br_cmd_delif,
|
||||
"<bridge> <device>\tdelete interface from bridge" },
|
||||
{ 3, "hairpin", br_cmd_hairpin,
|
||||
"<bridge> <port> {on|off}\tturn hairpin on/off" },
|
||||
{ 2, "setageing", br_cmd_setageing,
|
||||
"<bridge> <time>\t\tset ageing time" },
|
||||
{ 2, "setbridgeprio", br_cmd_setbridgeprio,
|
||||
"<bridge> <prio>\t\tset bridge priority" },
|
||||
{ 2, "setfd", br_cmd_setfd,
|
||||
"<bridge> <time>\t\tset bridge forward delay" },
|
||||
{ 2, "sethello", br_cmd_sethello,
|
||||
"<bridge> <time>\t\tset hello time" },
|
||||
{ 2, "setmaxage", br_cmd_setmaxage,
|
||||
"<bridge> <time>\t\tset max message age" },
|
||||
{ 3, "setpathcost", br_cmd_setpathcost,
|
||||
"<bridge> <port> <cost>\tset path cost" },
|
||||
{ 3, "setportprio", br_cmd_setportprio,
|
||||
"<bridge> <port> <prio>\tset port priority" },
|
||||
{ 0, "show", br_cmd_show,
|
||||
"[ <bridge> ]\t\tshow a list of bridges" },
|
||||
{ 1, "showmacs", br_cmd_showmacs,
|
||||
"<bridge>\t\tshow a list of mac addrs"},
|
||||
{ 1, "showstp", br_cmd_showstp,
|
||||
"<bridge>\t\tshow bridge stp info"},
|
||||
{ 2, "stp", br_cmd_stp,
|
||||
"<bridge> {on|off}\tturn stp on/off" },
|
||||
};
|
||||
|
||||
const struct command *command_lookup(const char *cmd)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) {
|
||||
if (!strcmp(cmd, commands[i].name))
|
||||
return &commands[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void command_helpall(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) {
|
||||
printf("\t%-10s\t%s\n", commands[i].name, commands[i].help);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Lennert Buytenhek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "libbridge.h"
|
||||
#include "brctl.h"
|
||||
|
||||
void br_dump_bridge_id(const unsigned char *x)
|
||||
{
|
||||
printf("%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x", x[0], x[1], x[2], x[3],
|
||||
x[4], x[5], x[6], x[7]);
|
||||
}
|
||||
|
||||
void br_show_timer(const struct timeval *tv)
|
||||
{
|
||||
printf("%4i.%.2i", (int)tv->tv_sec, (int)tv->tv_usec/10000);
|
||||
}
|
||||
|
||||
static int first;
|
||||
|
||||
static int dump_interface(const char *b, const char *p, void *arg)
|
||||
{
|
||||
|
||||
if (first)
|
||||
first = 0;
|
||||
else
|
||||
printf("\n\t\t\t\t\t\t\t");
|
||||
|
||||
printf("%s", p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void br_dump_interface_list(const char *br)
|
||||
{
|
||||
int err;
|
||||
|
||||
first = 1;
|
||||
err = br_foreach_port(br, dump_interface, NULL);
|
||||
if (err < 0)
|
||||
printf(" can't get port info: %s\n", strerror(-err));
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int dump_port_info(const char *br, const char *p, void *arg)
|
||||
{
|
||||
struct port_info pinfo;
|
||||
|
||||
if (br_get_port_info(br, p, &pinfo)) {
|
||||
printf("Can't get info for %p",p);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%s (%d)\n", p, pinfo.port_no);
|
||||
printf(" port id\t\t%.4x", pinfo.port_id);
|
||||
printf("\t\t\tstate\t\t%15s\n", br_get_state_name(pinfo.state));
|
||||
printf(" designated root\t");
|
||||
br_dump_bridge_id((unsigned char *)&pinfo.designated_root);
|
||||
printf("\tpath cost\t\t%4i\n", pinfo.path_cost);
|
||||
|
||||
printf(" designated bridge\t");
|
||||
br_dump_bridge_id((unsigned char *)&pinfo.designated_bridge);
|
||||
printf("\tmessage age timer\t");
|
||||
br_show_timer(&pinfo.message_age_timer_value);
|
||||
printf("\n designated port\t%.4x", pinfo.designated_port);
|
||||
printf("\t\t\tforward delay timer\t");
|
||||
br_show_timer(&pinfo.forward_delay_timer_value);
|
||||
printf("\n designated cost\t%4i", pinfo.designated_cost);
|
||||
printf("\t\t\thold timer\t\t");
|
||||
br_show_timer(&pinfo.hold_timer_value);
|
||||
printf("\n flags\t\t\t");
|
||||
if (pinfo.config_pending)
|
||||
printf("CONFIG_PENDING ");
|
||||
if (pinfo.top_change_ack)
|
||||
printf("TOPOLOGY_CHANGE_ACK ");
|
||||
if (pinfo.hairpin_mode)
|
||||
printf("\n hairpin mode\t\t\%4i", pinfo.hairpin_mode);
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void br_dump_info(const char *br, const struct bridge_info *bri)
|
||||
{
|
||||
int err;
|
||||
|
||||
printf("%s\n", br);
|
||||
printf(" bridge id\t\t");
|
||||
br_dump_bridge_id((unsigned char *)&bri->bridge_id);
|
||||
printf("\n designated root\t");
|
||||
br_dump_bridge_id((unsigned char *)&bri->designated_root);
|
||||
printf("\n root port\t\t%4i\t\t\t", bri->root_port);
|
||||
printf("path cost\t\t%4i\n", bri->root_path_cost);
|
||||
printf(" max age\t\t");
|
||||
br_show_timer(&bri->max_age);
|
||||
printf("\t\t\tbridge max age\t\t");
|
||||
br_show_timer(&bri->bridge_max_age);
|
||||
printf("\n hello time\t\t");
|
||||
br_show_timer(&bri->hello_time);
|
||||
printf("\t\t\tbridge hello time\t");
|
||||
br_show_timer(&bri->bridge_hello_time);
|
||||
printf("\n forward delay\t\t");
|
||||
br_show_timer(&bri->forward_delay);
|
||||
printf("\t\t\tbridge forward delay\t");
|
||||
br_show_timer(&bri->bridge_forward_delay);
|
||||
printf("\n ageing time\t\t");
|
||||
br_show_timer(&bri->ageing_time);
|
||||
printf("\n hello timer\t\t");
|
||||
br_show_timer(&bri->hello_timer_value);
|
||||
printf("\t\t\ttcn timer\t\t");
|
||||
br_show_timer(&bri->tcn_timer_value);
|
||||
printf("\n topology change timer\t");
|
||||
br_show_timer(&bri->topology_change_timer_value);
|
||||
printf("\t\t\tgc timer\t\t");
|
||||
br_show_timer(&bri->gc_timer_value);
|
||||
printf("\n flags\t\t\t");
|
||||
if (bri->topology_change)
|
||||
printf("TOPOLOGY_CHANGE ");
|
||||
if (bri->topology_change_detected)
|
||||
printf("TOPOLOGY_CHANGE_DETECTED ");
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
printf("\n");
|
||||
|
||||
err = br_foreach_port(br, dump_port_info, NULL);
|
||||
if (err < 0)
|
||||
printf("can't get ports: %s\n", strerror(-err));
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
config.h
|
||||
stamp-h1
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
KERNEL_HEADERS=-I@KERNEL_HEADERS@
|
||||
|
||||
AR=ar
|
||||
RANLIB=@RANLIB@
|
||||
|
||||
CC=@CC@
|
||||
CFLAGS = -Wall -g $(KERNEL_HEADERS)
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
includedir=@includedir@
|
||||
libdir=@libdir@
|
||||
|
||||
libbridge_SOURCES= \
|
||||
libbridge_devif.c \
|
||||
libbridge_if.c \
|
||||
libbridge_init.c \
|
||||
libbridge_misc.c
|
||||
|
||||
libbridge_OBJECTS=$(libbridge_SOURCES:.c=.o)
|
||||
|
||||
all: libbridge.a
|
||||
|
||||
# At present there is no need for a bridge-utils-devel package
|
||||
install:
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o libbridge.a
|
||||
|
||||
libbridge.a: $(libbridge_OBJECTS)
|
||||
$(AR) rcs $@ $(libbridge_OBJECTS)
|
||||
$(RANLIB) $@
|
||||
|
||||
%.o: %.c libbridge.h libbridge_private.h
|
||||
$(CC) $(CFLAGS) $(INCLUDE) -c $<
|
||||
|
||||
libbridge_compat.o: libbridge_compat.c if_index.c
|
||||
$(CC) $(CFLAGS) -c libbridge_compat.c
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/* libbridge/config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the `gethostname' function. */
|
||||
#undef HAVE_GETHOSTNAME
|
||||
|
||||
/* Define to 1 if you have the `if_indextoname' function. */
|
||||
#undef HAVE_IF_INDEXTONAME
|
||||
|
||||
/* Define to 1 if you have the `if_nametoindex' function. */
|
||||
#undef HAVE_IF_NAMETOINDEX
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `socket' function. */
|
||||
#undef HAVE_SOCKET
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strdup' function. */
|
||||
#undef HAVE_STRDUP
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||
#undef HAVE_SYS_IOCTL_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the `uname' function. */
|
||||
#undef HAVE_UNAME
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#undef TIME_WITH_SYS_TIME
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Lennert Buytenhek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _LIBBRIDGE_H
|
||||
#define _LIBBRIDGE_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_bridge.h>
|
||||
|
||||
/* defined in net/if.h but that conflicts with linux/if.h... */
|
||||
extern unsigned int if_nametoindex (const char *__ifname);
|
||||
extern char *if_indextoname (unsigned int __ifindex, char *__ifname);
|
||||
|
||||
|
||||
struct bridge_id
|
||||
{
|
||||
unsigned char prio[2];
|
||||
unsigned char addr[6];
|
||||
};
|
||||
|
||||
struct bridge_info
|
||||
{
|
||||
struct bridge_id designated_root;
|
||||
struct bridge_id bridge_id;
|
||||
unsigned root_path_cost;
|
||||
struct timeval max_age;
|
||||
struct timeval hello_time;
|
||||
struct timeval forward_delay;
|
||||
struct timeval bridge_max_age;
|
||||
struct timeval bridge_hello_time;
|
||||
struct timeval bridge_forward_delay;
|
||||
uint16_t root_port;
|
||||
unsigned char stp_enabled;
|
||||
unsigned char topology_change;
|
||||
unsigned char topology_change_detected;
|
||||
struct timeval ageing_time;
|
||||
struct timeval hello_timer_value;
|
||||
struct timeval tcn_timer_value;
|
||||
struct timeval topology_change_timer_value;
|
||||
struct timeval gc_timer_value;
|
||||
};
|
||||
|
||||
struct fdb_entry
|
||||
{
|
||||
uint8_t mac_addr[6];
|
||||
uint16_t port_no;
|
||||
unsigned char is_local;
|
||||
struct timeval ageing_timer_value;
|
||||
};
|
||||
|
||||
struct port_info
|
||||
{
|
||||
unsigned port_no;
|
||||
struct bridge_id designated_root;
|
||||
struct bridge_id designated_bridge;
|
||||
uint16_t port_id;
|
||||
uint16_t designated_port;
|
||||
uint8_t priority;
|
||||
unsigned char top_change_ack;
|
||||
unsigned char config_pending;
|
||||
unsigned char state;
|
||||
unsigned path_cost;
|
||||
unsigned designated_cost;
|
||||
struct timeval message_age_timer_value;
|
||||
struct timeval forward_delay_timer_value;
|
||||
struct timeval hold_timer_value;
|
||||
unsigned char hairpin_mode;
|
||||
};
|
||||
|
||||
extern int br_init(void);
|
||||
extern int br_refresh(void);
|
||||
extern void br_shutdown(void);
|
||||
|
||||
extern int br_foreach_bridge(int (*iterator)(const char *brname, void *),
|
||||
void *arg);
|
||||
extern int br_foreach_port(const char *brname,
|
||||
int (*iterator)(const char *brname, const char *port,
|
||||
void *arg ),
|
||||
void *arg);
|
||||
extern const char *br_get_state_name(int state);
|
||||
|
||||
extern int br_get_bridge_info(const char *br, struct bridge_info *info);
|
||||
extern int br_get_port_info(const char *brname, const char *port,
|
||||
struct port_info *info);
|
||||
extern int br_add_bridge(const char *brname);
|
||||
extern int br_del_bridge(const char *brname);
|
||||
extern int br_add_interface(const char *br, const char *dev);
|
||||
extern int br_del_interface(const char *br, const char *dev);
|
||||
extern int br_set_bridge_forward_delay(const char *br, struct timeval *tv);
|
||||
extern int br_set_bridge_hello_time(const char *br, struct timeval *tv);
|
||||
extern int br_set_bridge_max_age(const char *br, struct timeval *tv);
|
||||
extern int br_set_ageing_time(const char *br, struct timeval *tv);
|
||||
extern int br_set_stp_state(const char *br, int stp_state);
|
||||
extern int br_set_bridge_priority(const char *br, int bridge_priority);
|
||||
extern int br_set_port_priority(const char *br, const char *p,
|
||||
int port_priority);
|
||||
extern int br_set_path_cost(const char *br, const char *p,
|
||||
int path_cost);
|
||||
extern int br_read_fdb(const char *br, struct fdb_entry *fdbs,
|
||||
unsigned long skip, int num);
|
||||
extern int br_set_hairpin_mode(const char *bridge, const char *dev,
|
||||
int hairpin_mode);
|
||||
#endif
|
|
@ -0,0 +1,449 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Lennert Buytenhek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "libbridge.h"
|
||||
#include "libbridge_private.h"
|
||||
|
||||
static FILE *fpopen(const char *dir, const char *name)
|
||||
{
|
||||
char path[SYSFS_PATH_MAX];
|
||||
|
||||
snprintf(path, SYSFS_PATH_MAX, "%s/%s", dir, name);
|
||||
return fopen(path, "r");
|
||||
}
|
||||
|
||||
static void fetch_id(const char *dev, const char *name, struct bridge_id *id)
|
||||
{
|
||||
FILE *f = fpopen(dev, name);
|
||||
|
||||
if (!f)
|
||||
fprintf(stderr, "%s: %s\n", dev, strerror(errno));
|
||||
else {
|
||||
fscanf(f, "%2hhx%2hhx.%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
|
||||
&id->prio[0], &id->prio[1],
|
||||
&id->addr[0], &id->addr[1], &id->addr[2],
|
||||
&id->addr[3], &id->addr[4], &id->addr[5]);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch an integer attribute out of sysfs. */
|
||||
static int fetch_int(const char *dev, const char *name)
|
||||
{
|
||||
FILE *f = fpopen(dev, name);
|
||||
int value = -1;
|
||||
|
||||
if (!f)
|
||||
return 0;
|
||||
|
||||
fscanf(f, "%i", &value);
|
||||
fclose(f);
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Get a time value out of sysfs */
|
||||
static void fetch_tv(const char *dev, const char *name,
|
||||
struct timeval *tv)
|
||||
{
|
||||
__jiffies_to_tv(tv, fetch_int(dev, name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert device name to an index in the list of ports in bridge.
|
||||
*
|
||||
* Old API does bridge operations as if ports were an array
|
||||
* inside bridge structure.
|
||||
*/
|
||||
static int get_portno(const char *brname, const char *ifname)
|
||||
{
|
||||
int i;
|
||||
int ifindex = if_nametoindex(ifname);
|
||||
int ifindices[MAX_PORTS];
|
||||
unsigned long args[4] = { BRCTL_GET_PORT_LIST,
|
||||
(unsigned long)ifindices, MAX_PORTS, 0 };
|
||||
struct ifreq ifr;
|
||||
|
||||
if (ifindex <= 0)
|
||||
goto error;
|
||||
|
||||
memset(ifindices, 0, sizeof(ifindices));
|
||||
strncpy(ifr.ifr_name, brname, IFNAMSIZ);
|
||||
ifr.ifr_data = (char *) &args;
|
||||
|
||||
if (ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr) < 0) {
|
||||
dprintf("get_portno: get ports of %s failed: %s\n",
|
||||
brname, strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_PORTS; i++) {
|
||||
if (ifindices[i] == ifindex)
|
||||
return i;
|
||||
}
|
||||
|
||||
dprintf("%s is not a in bridge %s\n", ifname, brname);
|
||||
error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get information via ioctl */
|
||||
static int old_get_bridge_info(const char *bridge, struct bridge_info *info)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
struct __bridge_info i;
|
||||
unsigned long args[4] = { BRCTL_GET_BRIDGE_INFO,
|
||||
(unsigned long) &i, 0, 0 };
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
|
||||
ifr.ifr_data = (char *) &args;
|
||||
|
||||
if (ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr) < 0) {
|
||||
dprintf("%s: can't get info %s\n",
|
||||
bridge, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
|
||||
memcpy(&info->designated_root, &i.designated_root, 8);
|
||||
memcpy(&info->bridge_id, &i.bridge_id, 8);
|
||||
info->root_path_cost = i.root_path_cost;
|
||||
info->root_port = i.root_port;
|
||||
info->topology_change = i.topology_change;
|
||||
info->topology_change_detected = i.topology_change_detected;
|
||||
info->stp_enabled = i.stp_enabled;
|
||||
__jiffies_to_tv(&info->max_age, i.max_age);
|
||||
__jiffies_to_tv(&info->hello_time, i.hello_time);
|
||||
__jiffies_to_tv(&info->forward_delay, i.forward_delay);
|
||||
__jiffies_to_tv(&info->bridge_max_age, i.bridge_max_age);
|
||||
__jiffies_to_tv(&info->bridge_hello_time, i.bridge_hello_time);
|
||||
__jiffies_to_tv(&info->bridge_forward_delay, i.bridge_forward_delay);
|
||||
__jiffies_to_tv(&info->ageing_time, i.ageing_time);
|
||||
__jiffies_to_tv(&info->hello_timer_value, i.hello_timer_value);
|
||||
__jiffies_to_tv(&info->tcn_timer_value, i.tcn_timer_value);
|
||||
__jiffies_to_tv(&info->topology_change_timer_value,
|
||||
i.topology_change_timer_value);
|
||||
__jiffies_to_tv(&info->gc_timer_value, i.gc_timer_value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get bridge parameters using either sysfs or old
|
||||
* ioctl.
|
||||
*/
|
||||
int br_get_bridge_info(const char *bridge, struct bridge_info *info)
|
||||
{
|
||||
DIR *dir;
|
||||
char path[SYSFS_PATH_MAX];
|
||||
|
||||
snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/bridge", bridge);
|
||||
dir = opendir(path);
|
||||
if (dir == NULL) {
|
||||
dprintf("path '%s' is not a directory\n", path);
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
fetch_id(path, "root_id", &info->designated_root);
|
||||
fetch_id(path, "bridge_id", &info->bridge_id);
|
||||
info->root_path_cost = fetch_int(path, "root_path_cost");
|
||||
fetch_tv(path, "max_age", &info->max_age);
|
||||
fetch_tv(path, "hello_time", &info->hello_time);
|
||||
fetch_tv(path, "forward_delay", &info->forward_delay);
|
||||
fetch_tv(path, "max_age", &info->bridge_max_age);
|
||||
fetch_tv(path, "hello_time", &info->bridge_hello_time);
|
||||
fetch_tv(path, "forward_delay", &info->bridge_forward_delay);
|
||||
fetch_tv(path, "ageing_time", &info->ageing_time);
|
||||
fetch_tv(path, "hello_timer", &info->hello_timer_value);
|
||||
fetch_tv(path, "tcn_timer", &info->tcn_timer_value);
|
||||
fetch_tv(path, "topology_change_timer",
|
||||
&info->topology_change_timer_value);;
|
||||
fetch_tv(path, "gc_timer", &info->gc_timer_value);
|
||||
|
||||
info->root_port = fetch_int(path, "root_port");
|
||||
info->stp_enabled = fetch_int(path, "stp_state");
|
||||
info->topology_change = fetch_int(path, "topology_change");
|
||||
info->topology_change_detected = fetch_int(path, "topology_change_detected");
|
||||
|
||||
closedir(dir);
|
||||
return 0;
|
||||
|
||||
fallback:
|
||||
return old_get_bridge_info(bridge, info);
|
||||
}
|
||||
|
||||
static int old_get_port_info(const char *brname, const char *port,
|
||||
struct port_info *info)
|
||||
{
|
||||
struct __port_info i;
|
||||
int index;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
index = get_portno(brname, port);
|
||||
if (index < 0)
|
||||
return errno;
|
||||
|
||||
else {
|
||||
struct ifreq ifr;
|
||||
unsigned long args[4] = { BRCTL_GET_PORT_INFO,
|
||||
(unsigned long) &i, index, 0 };
|
||||
|
||||
strncpy(ifr.ifr_name, brname, IFNAMSIZ);
|
||||
ifr.ifr_data = (char *) &args;
|
||||
|
||||
if (ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr) < 0) {
|
||||
dprintf("old can't get port %s(%d) info %s\n",
|
||||
brname, index, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
|
||||
info->port_no = index;
|
||||
memcpy(&info->designated_root, &i.designated_root, 8);
|
||||
memcpy(&info->designated_bridge, &i.designated_bridge, 8);
|
||||
info->port_id = i.port_id;
|
||||
info->designated_port = i.designated_port;
|
||||
info->path_cost = i.path_cost;
|
||||
info->designated_cost = i.designated_cost;
|
||||
info->state = i.state;
|
||||
info->top_change_ack = i.top_change_ack;
|
||||
info->config_pending = i.config_pending;
|
||||
__jiffies_to_tv(&info->message_age_timer_value,
|
||||
i.message_age_timer_value);
|
||||
__jiffies_to_tv(&info->forward_delay_timer_value,
|
||||
i.forward_delay_timer_value);
|
||||
__jiffies_to_tv(&info->hold_timer_value, i.hold_timer_value);
|
||||
info->hairpin_mode = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get information about port on bridge.
|
||||
*/
|
||||
int br_get_port_info(const char *brname, const char *port,
|
||||
struct port_info *info)
|
||||
{
|
||||
DIR *d;
|
||||
char path[SYSFS_PATH_MAX];
|
||||
|
||||
snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/brport", port);
|
||||
d = opendir(path);
|
||||
if (!d)
|
||||
goto fallback;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
fetch_id(path, "designated_root", &info->designated_root);
|
||||
fetch_id(path, "designated_bridge", &info->designated_bridge);
|
||||
info->port_no = fetch_int(path, "port_no");
|
||||
info->port_id = fetch_int(path, "port_id");
|
||||
info->designated_port = fetch_int(path, "designated_port");
|
||||
info->path_cost = fetch_int(path, "path_cost");
|
||||
info->designated_cost = fetch_int(path, "designated_cost");
|
||||
info->state = fetch_int(path, "state");
|
||||
info->top_change_ack = fetch_int(path, "change_ack");
|
||||
info->config_pending = fetch_int(path, "config_pending");
|
||||
fetch_tv(path, "message_age_timer", &info->message_age_timer_value);
|
||||
fetch_tv(path, "forward_delay_timer", &info->forward_delay_timer_value);
|
||||
fetch_tv(path, "hold_timer", &info->hold_timer_value);
|
||||
info->hairpin_mode = fetch_int(path, "hairpin_mode");
|
||||
|
||||
closedir(d);
|
||||
|
||||
return 0;
|
||||
fallback:
|
||||
return old_get_port_info(brname, port, info);
|
||||
}
|
||||
|
||||
static int set_sysfs(const char *path, unsigned long value)
|
||||
{
|
||||
int fd, ret = 0, cc;
|
||||
char buf[32];
|
||||
|
||||
fd = open(path, O_WRONLY);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
cc = snprintf(buf, sizeof(buf), "%lu\n", value);
|
||||
if (write(fd, buf, cc) < 0)
|
||||
ret = -1;
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int br_set(const char *bridge, const char *name,
|
||||
unsigned long value, unsigned long oldcode)
|
||||
{
|
||||
int ret;
|
||||
char path[SYSFS_PATH_MAX];
|
||||
|
||||
snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/bridge/%s",
|
||||
bridge, name);
|
||||
|
||||
if ((ret = set_sysfs(path, value)) < 0) {
|
||||
/* fallback to old ioctl */
|
||||
struct ifreq ifr;
|
||||
unsigned long args[4] = { oldcode, value, 0, 0 };
|
||||
|
||||
strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
|
||||
ifr.ifr_data = (char *) &args;
|
||||
ret = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);
|
||||
}
|
||||
|
||||
return ret < 0 ? errno : 0;
|
||||
}
|
||||
|
||||
int br_set_bridge_forward_delay(const char *br, struct timeval *tv)
|
||||
{
|
||||
return br_set(br, "forward_delay", __tv_to_jiffies(tv),
|
||||
BRCTL_SET_BRIDGE_FORWARD_DELAY);
|
||||
}
|
||||
|
||||
int br_set_bridge_hello_time(const char *br, struct timeval *tv)
|
||||
{
|
||||
return br_set(br, "hello_time", __tv_to_jiffies(tv),
|
||||
BRCTL_SET_BRIDGE_HELLO_TIME);
|
||||
}
|
||||
|
||||
int br_set_bridge_max_age(const char *br, struct timeval *tv)
|
||||
{
|
||||
return br_set(br, "max_age", __tv_to_jiffies(tv),
|
||||
BRCTL_SET_BRIDGE_MAX_AGE);
|
||||
}
|
||||
|
||||
int br_set_ageing_time(const char *br, struct timeval *tv)
|
||||
{
|
||||
return br_set(br, "ageing_time", __tv_to_jiffies(tv),
|
||||
BRCTL_SET_AGEING_TIME);
|
||||
}
|
||||
|
||||
int br_set_stp_state(const char *br, int stp_state)
|
||||
{
|
||||
return br_set(br, "stp_state", stp_state, BRCTL_SET_BRIDGE_STP_STATE);
|
||||
}
|
||||
|
||||
int br_set_bridge_priority(const char *br, int bridge_priority)
|
||||
{
|
||||
return br_set(br, "priority", bridge_priority,
|
||||
BRCTL_SET_BRIDGE_PRIORITY);
|
||||
}
|
||||
|
||||
static int port_set(const char *bridge, const char *ifname,
|
||||
const char *name, unsigned long value,
|
||||
unsigned long oldcode)
|
||||
{
|
||||
int ret;
|
||||
char path[SYSFS_PATH_MAX];
|
||||
|
||||
snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/brport/%s", ifname, name);
|
||||
|
||||
if ((ret = set_sysfs(path, value)) < 0) {
|
||||
int index = get_portno(bridge, ifname);
|
||||
|
||||
if (index < 0)
|
||||
ret = index;
|
||||
else {
|
||||
struct ifreq ifr;
|
||||
unsigned long args[4] = { oldcode, index, value, 0 };
|
||||
|
||||
strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
|
||||
ifr.ifr_data = (char *) &args;
|
||||
ret = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);
|
||||
}
|
||||
}
|
||||
|
||||
return ret < 0 ? errno : 0;
|
||||
}
|
||||
|
||||
int br_set_port_priority(const char *bridge, const char *port, int priority)
|
||||
{
|
||||
return port_set(bridge, port, "priority", priority, BRCTL_SET_PORT_PRIORITY);
|
||||
}
|
||||
|
||||
int br_set_path_cost(const char *bridge, const char *port, int cost)
|
||||
{
|
||||
return port_set(bridge, port, "path_cost", cost, BRCTL_SET_PATH_COST);
|
||||
}
|
||||
|
||||
int br_set_hairpin_mode(const char *bridge, const char *port, int hairpin_mode)
|
||||
{
|
||||
return port_set(bridge, port, "hairpin_mode", hairpin_mode, 0);
|
||||
}
|
||||
|
||||
static inline void __copy_fdb(struct fdb_entry *ent,
|
||||
const struct __fdb_entry *f)
|
||||
{
|
||||
memcpy(ent->mac_addr, f->mac_addr, 6);
|
||||
ent->port_no = f->port_no;
|
||||
ent->is_local = f->is_local;
|
||||
__jiffies_to_tv(&ent->ageing_timer_value, f->ageing_timer_value);
|
||||
}
|
||||
|
||||
int br_read_fdb(const char *bridge, struct fdb_entry *fdbs,
|
||||
unsigned long offset, int num)
|
||||
{
|
||||
FILE *f;
|
||||
int i, n;
|
||||
struct __fdb_entry fe[num];
|
||||
char path[SYSFS_PATH_MAX];
|
||||
|
||||
/* open /sys/class/net/brXXX/brforward */
|
||||
snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/brforward", bridge);
|
||||
f = fopen(path, "r");
|
||||
if (f) {
|
||||
fseek(f, offset*sizeof(struct __fdb_entry), SEEK_SET);
|
||||
n = fread(fe, sizeof(struct __fdb_entry), num, f);
|
||||
fclose(f);
|
||||
} else {
|
||||
/* old kernel, use ioctl */
|
||||
unsigned long args[4] = { BRCTL_GET_FDB_ENTRIES,
|
||||
(unsigned long) fe,
|
||||
num, offset };
|
||||
struct ifreq ifr;
|
||||
int retries = 0;
|
||||
|
||||
strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
|
||||
ifr.ifr_data = (char *) args;
|
||||
|
||||
retry:
|
||||
n = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);
|
||||
|
||||
/* table can change during ioctl processing */
|
||||
if (n < 0 && errno == EAGAIN && ++retries < 10) {
|
||||
sleep(0);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
__copy_fdb(fdbs+i, fe+i);
|
||||
|
||||
return n;
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Lennert Buytenhek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "libbridge.h"
|
||||
#include "libbridge_private.h"
|
||||
|
||||
|
||||
int br_add_bridge(const char *brname)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#ifdef SIOCBRADDBR
|
||||
ret = ioctl(br_socket_fd, SIOCBRADDBR, brname);
|
||||
if (ret < 0)
|
||||
#endif
|
||||
{
|
||||
char _br[IFNAMSIZ];
|
||||
unsigned long arg[3]
|
||||
= { BRCTL_ADD_BRIDGE, (unsigned long) _br };
|
||||
|
||||
strncpy(_br, brname, IFNAMSIZ);
|
||||
ret = ioctl(br_socket_fd, SIOCSIFBR, arg);
|
||||
}
|
||||
|
||||
return ret < 0 ? errno : 0;
|
||||
}
|
||||
|
||||
int br_del_bridge(const char *brname)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#ifdef SIOCBRDELBR
|
||||
ret = ioctl(br_socket_fd, SIOCBRDELBR, brname);
|
||||
if (ret < 0)
|
||||
#endif
|
||||
{
|
||||
char _br[IFNAMSIZ];
|
||||
unsigned long arg[3]
|
||||
= { BRCTL_DEL_BRIDGE, (unsigned long) _br };
|
||||
|
||||
strncpy(_br, brname, IFNAMSIZ);
|
||||
ret = ioctl(br_socket_fd, SIOCSIFBR, arg);
|
||||
}
|
||||
return ret < 0 ? errno : 0;
|
||||
}
|
||||
|
||||
int br_add_interface(const char *bridge, const char *dev)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int err;
|
||||
int ifindex = if_nametoindex(dev);
|
||||
|
||||
if (ifindex == 0)
|
||||
return ENODEV;
|
||||
|
||||
strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
|
||||
#ifdef SIOCBRADDIF
|
||||
ifr.ifr_ifindex = ifindex;
|
||||
err = ioctl(br_socket_fd, SIOCBRADDIF, &ifr);
|
||||
if (err < 0)
|
||||
#endif
|
||||
{
|
||||
unsigned long args[4] = { BRCTL_ADD_IF, ifindex, 0, 0 };
|
||||
|
||||
ifr.ifr_data = (char *) args;
|
||||
err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);
|
||||
}
|
||||
|
||||
return err < 0 ? errno : 0;
|
||||
}
|
||||
|
||||
int br_del_interface(const char *bridge, const char *dev)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int err;
|
||||
int ifindex = if_nametoindex(dev);
|
||||
|
||||
if (ifindex == 0)
|
||||
return ENODEV;
|
||||
|
||||
strncpy(ifr.ifr_name, bridge, IFNAMSIZ);
|
||||
#ifdef SIOCBRDELIF
|
||||
ifr.ifr_ifindex = ifindex;
|
||||
err = ioctl(br_socket_fd, SIOCBRDELIF, &ifr);
|
||||
if (err < 0)
|
||||
#endif
|
||||
{
|
||||
unsigned long args[4] = { BRCTL_DEL_IF, ifindex, 0, 0 };
|
||||
|
||||
ifr.ifr_data = (char *) args;
|
||||
err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);
|
||||
}
|
||||
|
||||
return err < 0 ? errno : 0;
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Lennert Buytenhek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "libbridge.h"
|
||||
#include "libbridge_private.h"
|
||||
|
||||
int br_socket_fd = -1;
|
||||
|
||||
int br_init(void)
|
||||
{
|
||||
if ((br_socket_fd = socket(AF_LOCAL, SOCK_STREAM, 0)) < 0)
|
||||
return errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void br_shutdown(void)
|
||||
{
|
||||
close(br_socket_fd);
|
||||
br_socket_fd = -1;
|
||||
}
|
||||
|
||||
/* If /sys/class/net/XXX/bridge exists then it must be a bridge */
|
||||
static int isbridge(const struct dirent *entry)
|
||||
{
|
||||
char path[SYSFS_PATH_MAX];
|
||||
struct stat st;
|
||||
int ret, saved_errno;
|
||||
|
||||
if (entry->d_name[0] == '.'
|
||||
&& (entry->d_name[1] == '\0'
|
||||
|| (entry->d_name[1] == '.'
|
||||
&& entry->d_name[2] == '\0')))
|
||||
return 0;
|
||||
|
||||
snprintf(path, SYSFS_PATH_MAX,
|
||||
SYSFS_CLASS_NET "%s/bridge", entry->d_name);
|
||||
|
||||
/* Workaround old glibc breakage.
|
||||
If errno is set, then it fails scandir! */
|
||||
saved_errno = errno;
|
||||
ret = (stat(path, &st) == 0 && S_ISDIR(st.st_mode));
|
||||
errno = saved_errno;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* New interface uses sysfs to find bridges
|
||||
*/
|
||||
static int new_foreach_bridge(int (*iterator)(const char *name, void *),
|
||||
void *arg)
|
||||
{
|
||||
struct dirent **namelist;
|
||||
int i, count = 0;
|
||||
|
||||
count = scandir(SYSFS_CLASS_NET, &namelist, isbridge, alphasort);
|
||||
if (count < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (iterator(namelist[i]->d_name, arg))
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
free(namelist[i]);
|
||||
free(namelist);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Old interface uses ioctl
|
||||
*/
|
||||
static int old_foreach_bridge(int (*iterator)(const char *, void *),
|
||||
void *iarg)
|
||||
{
|
||||
int i, ret=0, num;
|
||||
char ifname[IFNAMSIZ];
|
||||
int ifindices[MAX_BRIDGES];
|
||||
unsigned long args[3] = { BRCTL_GET_BRIDGES,
|
||||
(unsigned long)ifindices, MAX_BRIDGES };
|
||||
|
||||
num = ioctl(br_socket_fd, SIOCGIFBR, args);
|
||||
if (num < 0) {
|
||||
dprintf("Get bridge indices failed: %s\n",
|
||||
strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (!if_indextoname(ifindices[i], ifname)) {
|
||||
dprintf("get find name for ifindex %d\n",
|
||||
ifindices[i]);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
++ret;
|
||||
if(iterator(ifname, iarg))
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Go over all bridges and call iterator function.
|
||||
* if iterator returns non-zero then stop.
|
||||
*/
|
||||
int br_foreach_bridge(int (*iterator)(const char *, void *),
|
||||
void *arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = new_foreach_bridge(iterator, arg);
|
||||
if (ret <= 0)
|
||||
ret = old_foreach_bridge(iterator, arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only used if sysfs is not available.
|
||||
*/
|
||||
static int old_foreach_port(const char *brname,
|
||||
int (*iterator)(const char *br, const char *port,
|
||||
void *arg),
|
||||
void *arg)
|
||||
{
|
||||
int i, err, count;
|
||||
struct ifreq ifr;
|
||||
char ifname[IFNAMSIZ];
|
||||
int ifindices[MAX_PORTS];
|
||||
unsigned long args[4] = { BRCTL_GET_PORT_LIST,
|
||||
(unsigned long)ifindices, MAX_PORTS, 0 };
|
||||
|
||||
memset(ifindices, 0, sizeof(ifindices));
|
||||
strncpy(ifr.ifr_name, brname, IFNAMSIZ);
|
||||
ifr.ifr_data = (char *) &args;
|
||||
|
||||
err = ioctl(br_socket_fd, SIOCDEVPRIVATE, &ifr);
|
||||
if (err < 0) {
|
||||
dprintf("list ports for bridge:'%s' failed: %s\n",
|
||||
brname, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
for (i = 0; i < MAX_PORTS; i++) {
|
||||
if (!ifindices[i])
|
||||
continue;
|
||||
|
||||
if (!if_indextoname(ifindices[i], ifname)) {
|
||||
dprintf("can't find name for ifindex:%d\n",
|
||||
ifindices[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
++count;
|
||||
if (iterator(brname, ifname, arg))
|
||||
break;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over all ports in bridge (using sysfs).
|
||||
*/
|
||||
int br_foreach_port(const char *brname,
|
||||
int (*iterator)(const char *br, const char *port, void *arg),
|
||||
void *arg)
|
||||
{
|
||||
int i, count;
|
||||
struct dirent **namelist;
|
||||
char path[SYSFS_PATH_MAX];
|
||||
|
||||
snprintf(path, SYSFS_PATH_MAX, SYSFS_CLASS_NET "%s/brif", brname);
|
||||
count = scandir(path, &namelist, 0, alphasort);
|
||||
if (count < 0)
|
||||
return old_foreach_port(brname, iterator, arg);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (namelist[i]->d_name[0] == '.'
|
||||
&& (namelist[i]->d_name[1] == '\0'
|
||||
|| (namelist[i]->d_name[1] == '.'
|
||||
&& namelist[i]->d_name[2] == '\0')))
|
||||
continue;
|
||||
|
||||
if (iterator(brname, namelist[i]->d_name, arg))
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < count; i++)
|
||||
free(namelist[i]);
|
||||
free(namelist);
|
||||
|
||||
return count;
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Lennert Buytenhek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <asm/param.h>
|
||||
#include "libbridge.h"
|
||||
#include "libbridge_private.h"
|
||||
|
||||
|
||||
static const char *state_names[5] = {
|
||||
[BR_STATE_DISABLED] = "disabled",
|
||||
[BR_STATE_LISTENING] = "listening",
|
||||
[BR_STATE_LEARNING] = "learning",
|
||||
[BR_STATE_FORWARDING] = "forwarding",
|
||||
[BR_STATE_BLOCKING] = "blocking",
|
||||
};
|
||||
|
||||
const char *br_get_state_name(int state)
|
||||
{
|
||||
if (state >= 0 && state <= 4)
|
||||
return state_names[state];
|
||||
|
||||
return "<INVALID STATE>";
|
||||
}
|
||||
|
||||
int __br_hz_internal;
|
||||
|
||||
int __get_hz(void)
|
||||
{
|
||||
const char * s = getenv("HZ");
|
||||
return s ? atoi(s) : HZ;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2000 Lennert Buytenhek
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef _LIBBRIDGE_PRIVATE_H
|
||||
#define _LIBBRIDGE_PRIVATE_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <linux/sockios.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/if_bridge.h>
|
||||
|
||||
#define MAX_BRIDGES 1024
|
||||
#define MAX_PORTS 1024
|
||||
|
||||
#define SYSFS_CLASS_NET "/sys/class/net/"
|
||||
#define SYSFS_PATH_MAX 256
|
||||
|
||||
#define dprintf(fmt,arg...)
|
||||
|
||||
extern int br_socket_fd;
|
||||
|
||||
static inline unsigned long __tv_to_jiffies(const struct timeval *tv)
|
||||
{
|
||||
unsigned long long jif;
|
||||
|
||||
jif = 1000000ULL * tv->tv_sec + tv->tv_usec;
|
||||
|
||||
return jif/10000;
|
||||
}
|
||||
|
||||
static inline void __jiffies_to_tv(struct timeval *tv, unsigned long jiffies)
|
||||
{
|
||||
unsigned long long tvusec;
|
||||
|
||||
tvusec = 10000ULL*jiffies;
|
||||
tv->tv_sec = tvusec/1000000;
|
||||
tv->tv_usec = tvusec - 1000000 * tv->tv_sec;
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue