📄 bridge.c
字号:
if (ioctl(s, SIOCBRDGDADDR, &ifba) < 0) {
warnx3("%s: %s", brdg, addr);
return (1);
}
return (0);
}
int
bridge_addaddr(s, brdg, ifname, addr)
int s;
char *brdg, *ifname, *addr;
{
struct ifbareq ifba;
struct ether_addr *ea;
strncpy(ifba.ifba_name, brdg, sizeof(ifba.ifba_name));
strncpy(ifba.ifba_ifsname, ifname, sizeof(ifba.ifba_ifsname));
ea = ether_aton(addr);
if (ea == NULL) {
warnx2("Invalid address: %s", addr);
return (1);
}
bcopy(ea, &ifba.ifba_dst, sizeof(struct ether_addr));
ifba.ifba_flags = IFBAF_STATIC;
if (ioctl(s, SIOCBRDGSADDR, &ifba) < 0) {
warnx3("%s: %s", brdg, addr);
return (1);
}
return (0);
}
int
bridge_addrs(s, brdg, delim)
int s;
char *brdg, *delim;
{
struct ifbaconf ifbac;
struct ifbareq *ifba;
char *inbuf = NULL, buf[sizeof(ifba->ifba_ifsname) + 1];
int i, len = 8192;
while (1) {
ifbac.ifbac_len = len;
ifbac.ifbac_buf = inbuf = realloc(inbuf, len);
strncpy(ifbac.ifbac_name, brdg, sizeof(ifbac.ifbac_name));
if (inbuf == NULL)
err(1, "malloc");
if (ioctl(s, SIOCBRDGRTS, &ifbac) < 0) {
if (errno == ENETDOWN)
return (0);
err(1, brdg);
}
if (ifbac.ifbac_len + sizeof(*ifba) < len)
break;
len *= 2;
}
for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) {
ifba = ifbac.ifbac_req + i;
strncpy(buf, ifba->ifba_ifsname, sizeof(buf));
diag_printf("%s%s %s %d ", delim, ether_ntoa(&ifba->ifba_dst),
buf, ifba->ifba_age);
printb("flags", ifba->ifba_flags, IFBAFBITS);
diag_printf("\n");
}
free(ifbac.ifbac_buf);
return (0);
}
/*
* Check to make sure 'brdg' is really a bridge interface.
*/
int
is_bridge(s, brdg)
int s;
char *brdg;
{
struct ifreq ifr;
struct ifbaconf ifbac;
strncpy(ifr.ifr_name, brdg, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
return (0);
ifbac.ifbac_len = 0;
strncpy(ifbac.ifbac_name, brdg, sizeof(ifbac.ifbac_name));
if (ioctl(s, SIOCBRDGRTS, (caddr_t)&ifbac) < 0) {
if (errno == ENETDOWN)
return (1);
return (0);
}
return (1);
}
int
bridge_status(s, brdg)
int s;
char *brdg;
{
struct ifreq ifr;
struct ifbcachereq ifbc;
struct ifbcachetoreq ifbct;
int err;
strncpy(ifr.ifr_name, brdg, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
warnx2("%s", brdg);
if (errno == EPERM)
return (1);
return (1);
}
diag_printf("%s: ", brdg);
printb("flags", ifr.ifr_flags, IFFBITS);
diag_printf("\n");
diag_printf("Interfaces:\n");
err = bridge_list(s, brdg, " ");
if (err)
return (err);
strncpy(ifbc.ifbc_name, brdg, sizeof(ifbc.ifbc_name));
if (ioctl(s, SIOCBRDGGCACHE, (caddr_t)&ifbc) < 0) {
warnx2("%s", brdg);
return (1);
}
strncpy(ifbct.ifbct_name, brdg, sizeof(ifbct.ifbct_name));
if (ioctl(s, SIOCBRDGGTO, (caddr_t)&ifbct) < 0) {
warnx2("%s", brdg);
return (1);
}
diag_printf("Addresses (max cache: %d, timeout: %d):\n",
ifbc.ifbc_size, ifbct.ifbct_time);
err = bridge_addrs(s, brdg, " ");
return (err);
}
int
bridge_flush_rule(s, brdg, ifname)
int s;
char *brdg, *ifname;
{
struct ifbrlreq req;
strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name));
strncpy(req.ifbr_ifsname, ifname, sizeof(req.ifbr_ifsname));
if (ioctl(s, SIOCBRDGFRL, &req) < 0) {
warnx3("%s: %s", brdg, ifname);
return (1);
}
return (0);
}
int
bridge_rules(s, brdg, ifname, delim)
int s;
char *brdg, *ifname;
char *delim;
{
char *inbuf = NULL;
struct ifbrlconf ifc;
struct ifbrlreq *ifrp, ifreq;
int len = 8192, i;
while (1) {
ifc.ifbrl_len = len;
ifc.ifbrl_buf = inbuf = realloc(inbuf, len);
strncpy(ifc.ifbrl_name, brdg, sizeof(ifc.ifbrl_name));
strncpy(ifc.ifbrl_ifsname, ifname, sizeof(ifc.ifbrl_ifsname));
if (inbuf == NULL)
err(1, "malloc");
if (ioctl(s, SIOCBRDGGRL, &ifc) < 0)
err(1, "ioctl(SIOCBRDGGRL)");
if (ifc.ifbrl_len + sizeof(ifreq) < len)
break;
len *= 2;
}
ifrp = ifc.ifbrl_req;
for (i = 0; i < ifc.ifbrl_len; i += sizeof(ifreq)) {
ifrp = (struct ifbrlreq *)((caddr_t)ifc.ifbrl_req + i);
bridge_showrule(ifrp, delim);
}
free(ifc.ifbrl_buf);
return (0);
}
void
bridge_showrule(r, delim)
struct ifbrlreq *r;
char *delim;
{
if (delim)
diag_printf("%s ", delim);
else
diag_printf("%s: ", r->ifbr_name);
if (r->ifbr_action == BRL_ACTION_BLOCK)
diag_printf("block ");
else if (r->ifbr_action == BRL_ACTION_PASS)
diag_printf("pass ");
else
diag_printf("[neither block nor pass?]\n");
if ((r->ifbr_flags & (BRL_FLAG_IN | BRL_FLAG_OUT)) ==
(BRL_FLAG_IN | BRL_FLAG_OUT))
diag_printf("in/out ");
else if (r->ifbr_flags & BRL_FLAG_IN)
diag_printf("in ");
else if (r->ifbr_flags & BRL_FLAG_OUT)
diag_printf("out ");
else
diag_printf("[neither in nor out?]\n");
diag_printf("on %s", r->ifbr_ifsname);
if (r->ifbr_flags & BRL_FLAG_SRCVALID)
diag_printf(" src %s", ether_ntoa(&r->ifbr_src));
if (r->ifbr_flags & BRL_FLAG_DSTVALID)
diag_printf(" dst %s", ether_ntoa(&r->ifbr_dst));
diag_printf("\n");
}
/*
* Parse a rule definition and send it upwards.
*
* Syntax:
* {block|pass} {in|out|in/out} on {ifs} [src {mac}] [dst {mac}]
*/
int
bridge_rule(int s, char *brdg, int targc, char **targv, int ln)
{
char **argv = targv;
int argc = targc;
struct ifbrlreq rule;
struct ether_addr *ea, *dea;
if (argc == 0) {
diag_printf( "invalid rule\n");
return (1);
}
rule.ifbr_flags = 0;
rule.ifbr_action = 0;
strncpy(rule.ifbr_name, brdg, sizeof(rule.ifbr_name));
if (strcmp(argv[0], "block") == 0)
rule.ifbr_action = BRL_ACTION_BLOCK;
else if (strcmp(argv[0], "pass") == 0)
rule.ifbr_action = BRL_ACTION_PASS;
else
goto bad_rule;
argc--; argv++;
if (argc == 0) {
bridge_badrule(targc, targv, ln);
return (1);
}
if (strcmp(argv[0], "in") == 0)
rule.ifbr_flags |= BRL_FLAG_IN;
else if (strcmp(argv[0], "out") == 0)
rule.ifbr_flags |= BRL_FLAG_OUT;
else if (strcmp(argv[0], "in/out") == 0)
rule.ifbr_flags |= BRL_FLAG_IN | BRL_FLAG_OUT;
else
goto bad_rule;
argc--; argv++;
if (argc == 0 || strcmp(argv[0], "on"))
goto bad_rule;
argc--; argv++;
if (argc == 0)
goto bad_rule;
strncpy(rule.ifbr_ifsname, argv[0], sizeof(rule.ifbr_ifsname));
argc--; argv++;
while (argc) {
if (strcmp(argv[0], "dst") == 0) {
if (rule.ifbr_flags & BRL_FLAG_DSTVALID)
goto bad_rule;
rule.ifbr_flags |= BRL_FLAG_DSTVALID;
dea = &rule.ifbr_dst;
}
else if (strcmp(argv[0], "src") == 0) {
if (rule.ifbr_flags & BRL_FLAG_SRCVALID)
goto bad_rule;
rule.ifbr_flags |= BRL_FLAG_SRCVALID;
dea = &rule.ifbr_src;
}
else
goto bad_rule;
argc--; argv++;
if (argc == 0)
goto bad_rule;
ea = ether_aton(argv[0]);
if (ea == NULL) {
warnx2("Invalid address: %s", argv[0]);
return (1);
}
bcopy(ea, dea, sizeof(*dea));
argc--; argv++;
}
if (ioctl(s, SIOCBRDGARL, &rule) < 0) {
warnx2("%s", brdg);
return (1);
}
return (0);
bad_rule:
bridge_badrule(targc, targv, ln);
return (1);
}
#define MAXRULEWORDS 8
#ifdef ZAP
int
bridge_rulefile(s, brdg, fname)
int s;
char *brdg, *fname;
{
FILE *f;
char *str, *argv[MAXRULEWORDS], buf[1024], xbuf[1024];
int ln = 1, argc = 0, err = 0, xerr;
f = fopen(fname, "r");
if (f == NULL) {
warnx2("%s", fname);
return (1);
}
while (1) {
fgets(buf, sizeof(buf), f);
if (feof(f))
break;
ln++;
if (buf[0] == '#')
continue;
argc = 0;
str = strtok(buf, "\n\r ");
strncpy(xbuf, buf, sizeof(xbuf));
while (str != NULL) {
argv[argc++] = str;
if (argc > MAXRULEWORDS) {
diag_printf( "invalid rule: %d: %s\n",
ln, xbuf);
break;
}
str = strtok(NULL, "\n\r ");
}
if (argc > MAXRULEWORDS)
continue;
xerr = bridge_rule(s, brdg, argc, argv, ln);
if (xerr)
err = xerr;
}
fclose(f);
return (err);
}
#endif
void
bridge_badrule(argc, argv, ln)
int argc, ln;
char **argv;
{
int i;
diag_printf( "invalid rule: ");
if (ln != -1)
diag_printf( "%d: ", ln);
for (i = 0; i < argc; i++) {
diag_printf( "%s ", argv[i]);
}
diag_printf( "\n");
}
/*
* Print a value ala the %b format of the kernel's printf
* (borrowed from ifconfig.c)
*/
void
printb(s, v, bits)
char *s;
char *bits;
unsigned short v;
{
register int i, any = 0;
register char c;
if (bits && *bits == 8)
diag_printf("%s=%o", s, v);
else
diag_printf("%s=%x", s, v);
bits++;
if (bits) {
diag_printf("<");
while ((i = *bits++)) {
if (v & (1 << (i-1))) {
if (any)
diag_printf(",");
any = 1;
for (; (c = *bits) > 32; bits++)
diag_printf("%c",c);
} else
for (; *bits > 32; bits++)
;
}
diag_printf(">");
}
}
static void
interface_up(const char *intf)
{
struct ifreq ifr;
int s;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0) {
perror("socket");
return;
}
strcpy(ifr.ifr_name, intf);
ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
if (ioctl(s, SIOCSIFFLAGS, &ifr)) {
perror("SIOCSIFFLAGS");
}
close(s);
}
static void
main_fn(cyg_addrword_t data) {
int sock;
char brdg[] = "bridge0";
sock = socket(AF_INET, SOCK_DGRAM, 0);
assert(sock >= 0);
#ifdef CYGHWR_NET_DRIVER_ETH0
interface_up("eth0");
eth0_up = 1;
bridge_add(sock,brdg,"eth0");
#ifdef CYGPKG_NET_BRIDGE_STP_CODE
bridge_ifsetflag (sock, brdg, "eth0", IFBIF_STP);
#endif
#endif
#ifdef CYGHWR_NET_DRIVER_ETH1
interface_up("eth1");
eth1_up = 1;
bridge_add(sock,brdg,"eth1");
#ifdef CYGPKG_NET_BRIDGE_STP_CODE
bridge_ifsetflag (sock, brdg, "eth1", IFBIF_STP);
#endif
#endif
bridge_status(sock,brdg);
bridge_setflag(sock,brdg, IFF_UP);
while(1) {
cyg_kmem_print_stats();
cyg_thread_delay(500);
}
}
static char main_stack[8192];
static cyg_handle_t main_handle;
static cyg_thread main_thread;
void
cyg_user_start(void) {
printf("cyg_user_start starting\n");
cyg_thread_create(4, &main_fn, 0, "main", &main_stack, sizeof(main_stack),
&main_handle, &main_thread);
cyg_thread_resume(main_handle);
printf("cyg_user_start done\n");
}
#else // CYGPKG_NET_BRIDGE_HANDLER
void
cyg_user_start(void) {
printf("No bridge support available\n");
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -