Mercurial > flash_v2
diff packages/net/common/current/tests/bridge.c @ 208:e0c0827131d1 ecos
Merge from eCos master repository on 2002-05-20-20:11:54-BST
| author | jlarmour |
|---|---|
| date | Mon, 20 May 2002 22:19:26 +0000 |
| parents | |
| children | 94b558c9fb67 |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/net/common/current/tests/bridge.c @@ -0,0 +1,986 @@ +//========================================================================== +// +// tests/bridge.c +// +// +// +//========================================================================== +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Jason L. Wright (jason@thought.net) +// Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt +// Date: 2000-01-10 +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +/* $OpenBSD: brconfig.c,v 1.6 2000/02/04 06:32:04 deraadt Exp $ */ + +/* + * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Jason L. Wright + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <network.h> +#include <sys/types.h> +#include <stdlib.h> +#include <net/if.h> +#include <net/if_dl.h> +#include <netinet/in.h> +#include <netinet/if_ether.h> +#include <net/if_bridge.h> +#include <sys/errno.h> +#include <string.h> +#include <stdlib.h> +#include <limits.h> +#include <assert.h> +#include <ctype.h> + +void bridge_usage __P((void)); +int main __P((int, char **)); +int bridge_setflag __P((int, char *, short)); +int bridge_clrflag __P((int, char *, short)); +int bridge_ifsetflag __P((int, char *, char *, u_int32_t)); +int bridge_ifclrflag __P((int, char *, char *, u_int32_t)); +int bridge_list __P((int, char *, char *)); +int bridge_addrs __P((int, char *, char *)); +int bridge_addaddr __P((int, char *, char *, char *)); +int bridge_deladdr __P((int, char *, char *)); +int bridge_maxaddr __P((int, char *, char *)); +int bridge_timeout __P((int, char *, char *)); +int bridge_flush __P((int, char *)); +int bridge_flushall __P((int, char *)); +int bridge_add __P((int, char *, char *)); +int bridge_delete __P((int, char *, char *)); +int bridge_status __P((int, char *)); +int is_bridge __P((int, char *)); +int bridge_show_all __P((int)); +void printb __P((char *, unsigned short, char *)); +int bridge_rule __P((int, char *, int, char **, int)); +int bridge_rules __P((int, char *, char *, char *)); +int bridge_flush_rule __P((int, char *, char *)); +void bridge_badrule __P((int, char **, int)); +void bridge_showrule __P((struct ifbrlreq *, char *)); +int bridge_rulefile __P((int, char *, char *)); + +/* if_flags bits: borrowed from ifconfig.c */ +#define IFFBITS \ +"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ +\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" + +#define IFBAFBITS "\020\1STATIC" +#define IFBIFBITS "\020\1LEARNING\2DISCOVER\3BLOCKNONIP\4BLOCKARP" + +#define warnx(x) diag_printf(x); +#define warnx2(x,y) diag_printf(x,y) +#define warnx3(x,y,z) diag_printf(x,y,z) +#define err(x,y) assert(0); +extern int cyg_kmem_print_stats(void); + +static char * _ether_aton __P((char *, struct ether_addr *)); + +char * +ether_ntoa(e) + struct ether_addr *e; +{ + static char a[] = "xx:xx:xx:xx:xx:xx"; + + if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF || + e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF || + e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) { + errno = EINVAL; + return (NULL); + } + + (void)sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", + e->ether_addr_octet[0], e->ether_addr_octet[1], + e->ether_addr_octet[2], e->ether_addr_octet[3], + e->ether_addr_octet[4], e->ether_addr_octet[5]); + + return (a); +} + +static char * +_ether_aton(s, e) + char *s; + struct ether_addr *e; +{ + int i; + long l; + char *pp; + + while (isspace(*s)) + s++; + + /* expect 6 hex octets separated by ':' or space/NUL if last octet */ + for (i = 0; i < 6; i++) { + l = strtol(s, &pp, 16); + if (pp == s || l > 0xFF || l < 0) + return (NULL); + if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0')))) + return (NULL); + e->ether_addr_octet[i] = (u_char)l; + s = pp + 1; + } + + /* return character after the octets ala strtol(3) */ + return (pp); +} + +struct ether_addr * +ether_aton(s) + char *s; +{ + static struct ether_addr n; + + return (_ether_aton(s, &n) ? &n : NULL); +} + +void +bridge_usage() +{ + diag_printf("usage: brconfig -a\n"); + diag_printf( + "usage: brconfig interface [up] [down] [add if] [del if] ...\n"); +} + + +int +bridge_ifsetflag(s, brdg, ifsname, flag) + int s; + char *brdg, *ifsname; + u_int32_t flag; +{ + struct ifbreq req; + + strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); + strncpy(req.ifbr_ifsname, ifsname, sizeof(req.ifbr_ifsname)); + if (ioctl(s, SIOCBRDGGIFFLGS, (caddr_t)&req) < 0) { + return (1); + } + + req.ifbr_ifsflags |= flag; + + if (ioctl(s, SIOCBRDGSIFFLGS, (caddr_t)&req) < 0) { + warnx3("%s: %s", brdg, ifsname); + return (1); + } + return (0); +} + +int +bridge_ifclrflag(s, brdg, ifsname, flag) + int s; + char *brdg, *ifsname; + u_int32_t flag; +{ + struct ifbreq req; + + strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); + strncpy(req.ifbr_ifsname, ifsname, sizeof(req.ifbr_ifsname)); + + if (ioctl(s, SIOCBRDGGIFFLGS, (caddr_t)&req) < 0) { + warnx3("%s: %s", brdg, ifsname); + return (1); + } + + req.ifbr_ifsflags &= ~flag; + + if (ioctl(s, SIOCBRDGSIFFLGS, (caddr_t)&req) < 0) { + warnx3("%s: %s", brdg, ifsname); + return (1); + } + return (0); +} + +int +bridge_show_all(s) + int s; +{ + char *inbuf = NULL; + struct ifconf ifc; + struct ifreq *ifrp, ifreq; + int len = 8192, i; + + while (1) { + ifc.ifc_len = len; + ifc.ifc_buf = inbuf = realloc(inbuf, len); + if (inbuf == NULL) + err(1, "malloc"); + if (ioctl(s, SIOCGIFCONF, &ifc) < 0) + err(1, "ioctl(SIOCGIFCONF)"); + if (ifc.ifc_len + sizeof(struct ifreq) < len) + break; + len *= 2; + } + ifrp = ifc.ifc_req; + ifreq.ifr_name[0] = '\0'; + for (i = 0; i < ifc.ifc_len; ) { + ifrp = (struct ifreq *)((caddr_t)ifc.ifc_req + i); + i += sizeof(ifrp->ifr_name) + + (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr) ? + ifrp->ifr_addr.sa_len : sizeof(struct sockaddr)); + if (ifrp->ifr_addr.sa_family != AF_LINK) + continue; + if (!is_bridge(s, ifrp->ifr_name)) + continue; + bridge_status(s, ifrp->ifr_name); + } + free(ifc.ifc_buf); + return (0); +} + +int +bridge_setflag(s, brdg, f) + int s; + char *brdg; + short f; +{ + struct ifreq ifr; + + 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); + } + + ifr.ifr_flags |= f; + + if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) { + warnx2("%s", brdg); + if (errno == EPERM) + return (1); + return (1); + } + + return (0); +} + +int +bridge_clrflag(s, brdg, f) + int s; + char *brdg; + short f; +{ + struct ifreq ifr; + + 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); + } + + ifr.ifr_flags &= ~(f); + + if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) { + warnx2("%s", brdg); + if (errno == EPERM) + return (1); + return (1); + } + + return (0); +} + +int +bridge_flushall(s, brdg) + int s; + char *brdg; +{ + struct ifbreq req; + + strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); + req.ifbr_ifsflags = IFBF_FLUSHALL; + if (ioctl(s, SIOCBRDGFLUSH, &req) < 0) { + warnx2("%s", brdg); + return (1); + } + return (0); +} + +int +bridge_flush(s, brdg) + int s; + char *brdg; +{ + struct ifbreq req; + + strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); + req.ifbr_ifsflags = IFBF_FLUSHDYN; + if (ioctl(s, SIOCBRDGFLUSH, &req) < 0) { + warnx2("%s", brdg); + return (1); + } + return (0); +} + +int +bridge_list(s, brdg, delim) + int s; + char *brdg, *delim; +{ + struct ifbreq *reqp; + struct ifbifconf bifc; + int i, len = 8192; + char buf[sizeof(reqp->ifbr_ifsname) + 1], *inbuf = NULL; + + while (1) { + strncpy(bifc.ifbic_name, brdg, sizeof(bifc.ifbic_name)); + bifc.ifbic_len = len; + bifc.ifbic_buf = inbuf = realloc(inbuf, len); + if (inbuf == NULL) + err(1, "malloc"); + if (ioctl(s, SIOCBRDGIFS, &bifc) < 0) + err(1, brdg); + if (bifc.ifbic_len + sizeof(*reqp) < len) + break; + len *= 2; + } + for (i = 0; i < bifc.ifbic_len / sizeof(*reqp); i++) { + reqp = bifc.ifbic_req + i; + strncpy(buf, reqp->ifbr_ifsname, sizeof(buf)); + diag_printf("%s%s ", delim, buf); + printb("flags", reqp->ifbr_ifsflags, IFBIFBITS); + diag_printf("\n"); + bridge_rules(s, brdg, buf, delim); + } + free(bifc.ifbic_buf); + return (0); /* NOTREACHED */ +} + +int +bridge_add(s, brdg, ifn) + int s; + char *brdg, *ifn; +{ + struct ifbreq req; + + strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); + strncpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); + if (ioctl(s, SIOCBRDGADD, &req) < 0) { + warnx3("%s: %s", brdg, ifn); + if (errno == EPERM) + return (1); + return (1); + } + return (0); +} + +int +bridge_delete(s, brdg, ifn) + int s; + char *brdg, *ifn; +{ + struct ifbreq req; + + strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); + strncpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); + if (ioctl(s, SIOCBRDGDEL, &req) < 0) { + warnx3("%s: %s", brdg, ifn); + if (errno == EPERM) + return (1); + return (1); + } + return (0); +} + +int +bridge_timeout(s, brdg, arg) + int s; + char *brdg, *arg; +{ + struct ifbcachetoreq ifbct; + u_int32_t newtime; + char *endptr; + + newtime = strtoul(arg, &endptr, 0); + if (arg[0] == '\0' || endptr[0] != '\0') { + diag_printf("invalid arg for timeout: %s\n", arg); + return (1); + } + + strncpy(ifbct.ifbct_name, brdg, sizeof(ifbct.ifbct_name)); + ifbct.ifbct_time = newtime; + if (ioctl(s, SIOCBRDGSTO, (caddr_t)&ifbct) < 0) { + warnx2("%s", brdg); + return (1); + } + return (0); +} + +int +bridge_maxaddr(s, brdg, arg) + int s; + char *brdg, *arg; +{ + struct ifbcachereq ifbc; + u_int32_t newsize; + char *endptr; + + newsize = strtoul(arg, &endptr, 0); + if (arg[0] == '\0' || endptr[0] != '\0') { + diag_printf("invalid arg for maxaddr: %s\n", arg); + return (1); + } + + strncpy(ifbc.ifbc_name, brdg, sizeof(ifbc.ifbc_name)); + ifbc.ifbc_size = newsize; + if (ioctl(s, SIOCBRDGSCACHE, (caddr_t)&ifbc) < 0) { + warnx2("%s", brdg); + return (1); + } + return (0); +} + +int +bridge_deladdr(s, brdg, addr) + int s; + char *brdg, *addr; +{ + struct ifbareq ifba; + struct ether_addr *ea; + + strncpy(ifba.ifba_name, brdg, sizeof(ifba.ifba_name)); + ea = ether_aton(addr); + if (ea == NULL) { + warnx2("Invalid address: %s", addr); + return (1); + } + bcopy(ea, &ifba.ifba_dst, sizeof(struct ether_addr)); + + 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"); +#endif +#ifdef CYGHWR_NET_DRIVER_ETH1 + interface_up("eth1"); + eth1_up = 1; + bridge_add(sock,brdg,"eth1"); +#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"); +} + +
