Mercurial > flash_v2
comparison packages/net/tcpip/current/tests/bridge.c @ 112:02ea4320376c ecos-sw-2000-07-21
Merge from eCos master repository on 2000-07-21-21:01:39-BST
| author | jlarmour |
|---|---|
| date | Fri, 21 Jul 2000 21:34:11 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 111:211b8a635ce9 | 112:02ea4320376c |
|---|---|
| 1 //========================================================================== | |
| 2 // | |
| 3 // tests/bridge.c | |
| 4 // | |
| 5 // | |
| 6 // | |
| 7 //========================================================================== | |
| 8 //####COPYRIGHTBEGIN#### | |
| 9 // | |
| 10 // ------------------------------------------- | |
| 11 // The contents of this file are subject to the Red Hat eCos Public License | |
| 12 // Version 1.1 (the "License"); you may not use this file except in | |
| 13 // compliance with the License. You may obtain a copy of the License at | |
| 14 // http://www.redhat.com/ | |
| 15 // | |
| 16 // Software distributed under the License is distributed on an "AS IS" | |
| 17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the | |
| 18 // License for the specific language governing rights and limitations under | |
| 19 // the License. | |
| 20 // | |
| 21 // The Original Code is eCos - Embedded Configurable Operating System, | |
| 22 // released September 30, 1998. | |
| 23 // | |
| 24 // The Initial Developer of the Original Code is Red Hat. | |
| 25 // Portions created by Red Hat are | |
| 26 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc. | |
| 27 // All Rights Reserved. | |
| 28 // ------------------------------------------- | |
| 29 // | |
| 30 //####COPYRIGHTEND#### | |
| 31 //####BSDCOPYRIGHTBEGIN#### | |
| 32 // | |
| 33 // ------------------------------------------- | |
| 34 // | |
| 35 // Portions of this software may have been derived from OpenBSD or other sources, | |
| 36 // and are covered by the appropriate copyright disclaimers included herein. | |
| 37 // | |
| 38 // ------------------------------------------- | |
| 39 // | |
| 40 //####BSDCOPYRIGHTEND#### | |
| 41 //========================================================================== | |
| 42 //#####DESCRIPTIONBEGIN#### | |
| 43 // | |
| 44 // Author(s): Jason L. Wright (jason@thought.net) | |
| 45 // Contributors: andrew.lunn@ascom.ch (Andrew Lunn), hmt | |
| 46 // Date: 2000-01-10 | |
| 47 // Purpose: | |
| 48 // Description: | |
| 49 // | |
| 50 // | |
| 51 //####DESCRIPTIONEND#### | |
| 52 // | |
| 53 //========================================================================== | |
| 54 | |
| 55 | |
| 56 /* $OpenBSD: brconfig.c,v 1.6 2000/02/04 06:32:04 deraadt Exp $ */ | |
| 57 | |
| 58 /* | |
| 59 * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net) | |
| 60 * All rights reserved. | |
| 61 * | |
| 62 * Redistribution and use in source and binary forms, with or without | |
| 63 * modification, are permitted provided that the following conditions | |
| 64 * are met: | |
| 65 * 1. Redistributions of source code must retain the above copyright | |
| 66 * notice, this list of conditions and the following disclaimer. | |
| 67 * 2. Redistributions in binary form must reproduce the above copyright | |
| 68 * notice, this list of conditions and the following disclaimer in the | |
| 69 * documentation and/or other materials provided with the distribution. | |
| 70 * 3. All advertising materials mentioning features or use of this software | |
| 71 * must display the following acknowledgement: | |
| 72 * This product includes software developed by Jason L. Wright | |
| 73 * 4. The name of the author may not be used to endorse or promote products | |
| 74 * derived from this software without specific prior written permission. | |
| 75 * | |
| 76 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
| 77 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 78 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| 79 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, | |
| 80 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 81 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| 82 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 83 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
| 84 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
| 85 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| 86 * POSSIBILITY OF SUCH DAMAGE. | |
| 87 */ | |
| 88 | |
| 89 #include <stdio.h> | |
| 90 #include <network.h> | |
| 91 #include <sys/types.h> | |
| 92 #include <stdlib.h> | |
| 93 #include <net/if.h> | |
| 94 #include <net/if_dl.h> | |
| 95 #include <netinet/in.h> | |
| 96 #include <netinet/if_ether.h> | |
| 97 #include <net/if_bridge.h> | |
| 98 #include <sys/errno.h> | |
| 99 #include <string.h> | |
| 100 #include <stdlib.h> | |
| 101 #include <limits.h> | |
| 102 #include <assert.h> | |
| 103 #include <ctype.h> | |
| 104 | |
| 105 void bridge_usage __P((void)); | |
| 106 int main __P((int, char **)); | |
| 107 int bridge_setflag __P((int, char *, short)); | |
| 108 int bridge_clrflag __P((int, char *, short)); | |
| 109 int bridge_ifsetflag __P((int, char *, char *, u_int32_t)); | |
| 110 int bridge_ifclrflag __P((int, char *, char *, u_int32_t)); | |
| 111 int bridge_list __P((int, char *, char *)); | |
| 112 int bridge_addrs __P((int, char *, char *)); | |
| 113 int bridge_addaddr __P((int, char *, char *, char *)); | |
| 114 int bridge_deladdr __P((int, char *, char *)); | |
| 115 int bridge_maxaddr __P((int, char *, char *)); | |
| 116 int bridge_timeout __P((int, char *, char *)); | |
| 117 int bridge_flush __P((int, char *)); | |
| 118 int bridge_flushall __P((int, char *)); | |
| 119 int bridge_add __P((int, char *, char *)); | |
| 120 int bridge_delete __P((int, char *, char *)); | |
| 121 int bridge_status __P((int, char *)); | |
| 122 int is_bridge __P((int, char *)); | |
| 123 int bridge_show_all __P((int)); | |
| 124 void printb __P((char *, unsigned short, char *)); | |
| 125 int bridge_rule __P((int, char *, int, char **, int)); | |
| 126 int bridge_rules __P((int, char *, char *, char *)); | |
| 127 int bridge_flush_rule __P((int, char *, char *)); | |
| 128 void bridge_badrule __P((int, char **, int)); | |
| 129 void bridge_showrule __P((struct ifbrlreq *, char *)); | |
| 130 int bridge_rulefile __P((int, char *, char *)); | |
| 131 | |
| 132 /* if_flags bits: borrowed from ifconfig.c */ | |
| 133 #define IFFBITS \ | |
| 134 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS\7RUNNING\10NOARP\ | |
| 135 \11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2\20MULTICAST" | |
| 136 | |
| 137 #define IFBAFBITS "\020\1STATIC" | |
| 138 #define IFBIFBITS "\020\1LEARNING\2DISCOVER\3BLOCKNONIP\4BLOCKARP" | |
| 139 | |
| 140 #define warnx(x) diag_printf(x); | |
| 141 #define warnx2(x,y) diag_printf(x,y) | |
| 142 #define warnx3(x,y,z) diag_printf(x,y,z) | |
| 143 #define err(x,y) assert(0); | |
| 144 extern int cyg_kmem_print_stats(void); | |
| 145 | |
| 146 static char * _ether_aton __P((char *, struct ether_addr *)); | |
| 147 | |
| 148 char * | |
| 149 ether_ntoa(e) | |
| 150 struct ether_addr *e; | |
| 151 { | |
| 152 static char a[] = "xx:xx:xx:xx:xx:xx"; | |
| 153 | |
| 154 if (e->ether_addr_octet[0] > 0xFF || e->ether_addr_octet[1] > 0xFF || | |
| 155 e->ether_addr_octet[2] > 0xFF || e->ether_addr_octet[3] > 0xFF || | |
| 156 e->ether_addr_octet[4] > 0xFF || e->ether_addr_octet[5] > 0xFF) { | |
| 157 errno = EINVAL; | |
| 158 return (NULL); | |
| 159 } | |
| 160 | |
| 161 (void)sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", | |
| 162 e->ether_addr_octet[0], e->ether_addr_octet[1], | |
| 163 e->ether_addr_octet[2], e->ether_addr_octet[3], | |
| 164 e->ether_addr_octet[4], e->ether_addr_octet[5]); | |
| 165 | |
| 166 return (a); | |
| 167 } | |
| 168 | |
| 169 static char * | |
| 170 _ether_aton(s, e) | |
| 171 char *s; | |
| 172 struct ether_addr *e; | |
| 173 { | |
| 174 int i; | |
| 175 long l; | |
| 176 char *pp; | |
| 177 | |
| 178 while (isspace(*s)) | |
| 179 s++; | |
| 180 | |
| 181 /* expect 6 hex octets separated by ':' or space/NUL if last octet */ | |
| 182 for (i = 0; i < 6; i++) { | |
| 183 l = strtol(s, &pp, 16); | |
| 184 if (pp == s || l > 0xFF || l < 0) | |
| 185 return (NULL); | |
| 186 if (!(*pp == ':' || (i == 5 && (isspace(*pp) || *pp == '\0')))) | |
| 187 return (NULL); | |
| 188 e->ether_addr_octet[i] = (u_char)l; | |
| 189 s = pp + 1; | |
| 190 } | |
| 191 | |
| 192 /* return character after the octets ala strtol(3) */ | |
| 193 return (pp); | |
| 194 } | |
| 195 | |
| 196 struct ether_addr * | |
| 197 ether_aton(s) | |
| 198 char *s; | |
| 199 { | |
| 200 static struct ether_addr n; | |
| 201 | |
| 202 return (_ether_aton(s, &n) ? &n : NULL); | |
| 203 } | |
| 204 | |
| 205 void | |
| 206 bridge_usage() | |
| 207 { | |
| 208 diag_printf("usage: brconfig -a\n"); | |
| 209 diag_printf( | |
| 210 "usage: brconfig interface [up] [down] [add if] [del if] ...\n"); | |
| 211 } | |
| 212 | |
| 213 | |
| 214 int | |
| 215 bridge_ifsetflag(s, brdg, ifsname, flag) | |
| 216 int s; | |
| 217 char *brdg, *ifsname; | |
| 218 u_int32_t flag; | |
| 219 { | |
| 220 struct ifbreq req; | |
| 221 | |
| 222 strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); | |
| 223 strncpy(req.ifbr_ifsname, ifsname, sizeof(req.ifbr_ifsname)); | |
| 224 if (ioctl(s, SIOCBRDGGIFFLGS, (caddr_t)&req) < 0) { | |
| 225 return (1); | |
| 226 } | |
| 227 | |
| 228 req.ifbr_ifsflags |= flag; | |
| 229 | |
| 230 if (ioctl(s, SIOCBRDGSIFFLGS, (caddr_t)&req) < 0) { | |
| 231 warnx3("%s: %s", brdg, ifsname); | |
| 232 return (1); | |
| 233 } | |
| 234 return (0); | |
| 235 } | |
| 236 | |
| 237 int | |
| 238 bridge_ifclrflag(s, brdg, ifsname, flag) | |
| 239 int s; | |
| 240 char *brdg, *ifsname; | |
| 241 u_int32_t flag; | |
| 242 { | |
| 243 struct ifbreq req; | |
| 244 | |
| 245 strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); | |
| 246 strncpy(req.ifbr_ifsname, ifsname, sizeof(req.ifbr_ifsname)); | |
| 247 | |
| 248 if (ioctl(s, SIOCBRDGGIFFLGS, (caddr_t)&req) < 0) { | |
| 249 warnx3("%s: %s", brdg, ifsname); | |
| 250 return (1); | |
| 251 } | |
| 252 | |
| 253 req.ifbr_ifsflags &= ~flag; | |
| 254 | |
| 255 if (ioctl(s, SIOCBRDGSIFFLGS, (caddr_t)&req) < 0) { | |
| 256 warnx3("%s: %s", brdg, ifsname); | |
| 257 return (1); | |
| 258 } | |
| 259 return (0); | |
| 260 } | |
| 261 | |
| 262 int | |
| 263 bridge_show_all(s) | |
| 264 int s; | |
| 265 { | |
| 266 char *inbuf = NULL; | |
| 267 struct ifconf ifc; | |
| 268 struct ifreq *ifrp, ifreq; | |
| 269 int len = 8192, i; | |
| 270 | |
| 271 while (1) { | |
| 272 ifc.ifc_len = len; | |
| 273 ifc.ifc_buf = inbuf = realloc(inbuf, len); | |
| 274 if (inbuf == NULL) | |
| 275 err(1, "malloc"); | |
| 276 if (ioctl(s, SIOCGIFCONF, &ifc) < 0) | |
| 277 err(1, "ioctl(SIOCGIFCONF)"); | |
| 278 if (ifc.ifc_len + sizeof(struct ifreq) < len) | |
| 279 break; | |
| 280 len *= 2; | |
| 281 } | |
| 282 ifrp = ifc.ifc_req; | |
| 283 ifreq.ifr_name[0] = '\0'; | |
| 284 for (i = 0; i < ifc.ifc_len; ) { | |
| 285 ifrp = (struct ifreq *)((caddr_t)ifc.ifc_req + i); | |
| 286 i += sizeof(ifrp->ifr_name) + | |
| 287 (ifrp->ifr_addr.sa_len > sizeof(struct sockaddr) ? | |
| 288 ifrp->ifr_addr.sa_len : sizeof(struct sockaddr)); | |
| 289 if (ifrp->ifr_addr.sa_family != AF_LINK) | |
| 290 continue; | |
| 291 if (!is_bridge(s, ifrp->ifr_name)) | |
| 292 continue; | |
| 293 bridge_status(s, ifrp->ifr_name); | |
| 294 } | |
| 295 free(ifc.ifc_buf); | |
| 296 return (0); | |
| 297 } | |
| 298 | |
| 299 int | |
| 300 bridge_setflag(s, brdg, f) | |
| 301 int s; | |
| 302 char *brdg; | |
| 303 short f; | |
| 304 { | |
| 305 struct ifreq ifr; | |
| 306 | |
| 307 strncpy(ifr.ifr_name, brdg, sizeof(ifr.ifr_name)); | |
| 308 | |
| 309 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { | |
| 310 warnx2("%s", brdg); | |
| 311 if (errno == EPERM) | |
| 312 return (1); | |
| 313 return (1); | |
| 314 } | |
| 315 | |
| 316 ifr.ifr_flags |= f; | |
| 317 | |
| 318 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) { | |
| 319 warnx2("%s", brdg); | |
| 320 if (errno == EPERM) | |
| 321 return (1); | |
| 322 return (1); | |
| 323 } | |
| 324 | |
| 325 return (0); | |
| 326 } | |
| 327 | |
| 328 int | |
| 329 bridge_clrflag(s, brdg, f) | |
| 330 int s; | |
| 331 char *brdg; | |
| 332 short f; | |
| 333 { | |
| 334 struct ifreq ifr; | |
| 335 | |
| 336 strncpy(ifr.ifr_name, brdg, sizeof(ifr.ifr_name)); | |
| 337 | |
| 338 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { | |
| 339 warnx2("%s", brdg); | |
| 340 if (errno == EPERM) | |
| 341 return (1); | |
| 342 return (1); | |
| 343 } | |
| 344 | |
| 345 ifr.ifr_flags &= ~(f); | |
| 346 | |
| 347 if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) { | |
| 348 warnx2("%s", brdg); | |
| 349 if (errno == EPERM) | |
| 350 return (1); | |
| 351 return (1); | |
| 352 } | |
| 353 | |
| 354 return (0); | |
| 355 } | |
| 356 | |
| 357 int | |
| 358 bridge_flushall(s, brdg) | |
| 359 int s; | |
| 360 char *brdg; | |
| 361 { | |
| 362 struct ifbreq req; | |
| 363 | |
| 364 strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); | |
| 365 req.ifbr_ifsflags = IFBF_FLUSHALL; | |
| 366 if (ioctl(s, SIOCBRDGFLUSH, &req) < 0) { | |
| 367 warnx2("%s", brdg); | |
| 368 return (1); | |
| 369 } | |
| 370 return (0); | |
| 371 } | |
| 372 | |
| 373 int | |
| 374 bridge_flush(s, brdg) | |
| 375 int s; | |
| 376 char *brdg; | |
| 377 { | |
| 378 struct ifbreq req; | |
| 379 | |
| 380 strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); | |
| 381 req.ifbr_ifsflags = IFBF_FLUSHDYN; | |
| 382 if (ioctl(s, SIOCBRDGFLUSH, &req) < 0) { | |
| 383 warnx2("%s", brdg); | |
| 384 return (1); | |
| 385 } | |
| 386 return (0); | |
| 387 } | |
| 388 | |
| 389 int | |
| 390 bridge_list(s, brdg, delim) | |
| 391 int s; | |
| 392 char *brdg, *delim; | |
| 393 { | |
| 394 struct ifbreq *reqp; | |
| 395 struct ifbifconf bifc; | |
| 396 int i, len = 8192; | |
| 397 char buf[sizeof(reqp->ifbr_ifsname) + 1], *inbuf = NULL; | |
| 398 | |
| 399 while (1) { | |
| 400 strncpy(bifc.ifbic_name, brdg, sizeof(bifc.ifbic_name)); | |
| 401 bifc.ifbic_len = len; | |
| 402 bifc.ifbic_buf = inbuf = realloc(inbuf, len); | |
| 403 if (inbuf == NULL) | |
| 404 err(1, "malloc"); | |
| 405 if (ioctl(s, SIOCBRDGIFS, &bifc) < 0) | |
| 406 err(1, brdg); | |
| 407 if (bifc.ifbic_len + sizeof(*reqp) < len) | |
| 408 break; | |
| 409 len *= 2; | |
| 410 } | |
| 411 for (i = 0; i < bifc.ifbic_len / sizeof(*reqp); i++) { | |
| 412 reqp = bifc.ifbic_req + i; | |
| 413 strncpy(buf, reqp->ifbr_ifsname, sizeof(buf)); | |
| 414 diag_printf("%s%s ", delim, buf); | |
| 415 printb("flags", reqp->ifbr_ifsflags, IFBIFBITS); | |
| 416 diag_printf("\n"); | |
| 417 bridge_rules(s, brdg, buf, delim); | |
| 418 } | |
| 419 free(bifc.ifbic_buf); | |
| 420 return (0); /* NOTREACHED */ | |
| 421 } | |
| 422 | |
| 423 int | |
| 424 bridge_add(s, brdg, ifn) | |
| 425 int s; | |
| 426 char *brdg, *ifn; | |
| 427 { | |
| 428 struct ifbreq req; | |
| 429 | |
| 430 strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); | |
| 431 strncpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); | |
| 432 if (ioctl(s, SIOCBRDGADD, &req) < 0) { | |
| 433 warnx3("%s: %s", brdg, ifn); | |
| 434 if (errno == EPERM) | |
| 435 return (1); | |
| 436 return (1); | |
| 437 } | |
| 438 return (0); | |
| 439 } | |
| 440 | |
| 441 int | |
| 442 bridge_delete(s, brdg, ifn) | |
| 443 int s; | |
| 444 char *brdg, *ifn; | |
| 445 { | |
| 446 struct ifbreq req; | |
| 447 | |
| 448 strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); | |
| 449 strncpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname)); | |
| 450 if (ioctl(s, SIOCBRDGDEL, &req) < 0) { | |
| 451 warnx3("%s: %s", brdg, ifn); | |
| 452 if (errno == EPERM) | |
| 453 return (1); | |
| 454 return (1); | |
| 455 } | |
| 456 return (0); | |
| 457 } | |
| 458 | |
| 459 int | |
| 460 bridge_timeout(s, brdg, arg) | |
| 461 int s; | |
| 462 char *brdg, *arg; | |
| 463 { | |
| 464 struct ifbcachetoreq ifbct; | |
| 465 u_int32_t newtime; | |
| 466 char *endptr; | |
| 467 | |
| 468 newtime = strtoul(arg, &endptr, 0); | |
| 469 if (arg[0] == '\0' || endptr[0] != '\0') { | |
| 470 diag_printf("invalid arg for timeout: %s\n", arg); | |
| 471 return (1); | |
| 472 } | |
| 473 | |
| 474 strncpy(ifbct.ifbct_name, brdg, sizeof(ifbct.ifbct_name)); | |
| 475 ifbct.ifbct_time = newtime; | |
| 476 if (ioctl(s, SIOCBRDGSTO, (caddr_t)&ifbct) < 0) { | |
| 477 warnx2("%s", brdg); | |
| 478 return (1); | |
| 479 } | |
| 480 return (0); | |
| 481 } | |
| 482 | |
| 483 int | |
| 484 bridge_maxaddr(s, brdg, arg) | |
| 485 int s; | |
| 486 char *brdg, *arg; | |
| 487 { | |
| 488 struct ifbcachereq ifbc; | |
| 489 u_int32_t newsize; | |
| 490 char *endptr; | |
| 491 | |
| 492 newsize = strtoul(arg, &endptr, 0); | |
| 493 if (arg[0] == '\0' || endptr[0] != '\0') { | |
| 494 diag_printf("invalid arg for maxaddr: %s\n", arg); | |
| 495 return (1); | |
| 496 } | |
| 497 | |
| 498 strncpy(ifbc.ifbc_name, brdg, sizeof(ifbc.ifbc_name)); | |
| 499 ifbc.ifbc_size = newsize; | |
| 500 if (ioctl(s, SIOCBRDGSCACHE, (caddr_t)&ifbc) < 0) { | |
| 501 warnx2("%s", brdg); | |
| 502 return (1); | |
| 503 } | |
| 504 return (0); | |
| 505 } | |
| 506 | |
| 507 int | |
| 508 bridge_deladdr(s, brdg, addr) | |
| 509 int s; | |
| 510 char *brdg, *addr; | |
| 511 { | |
| 512 struct ifbareq ifba; | |
| 513 struct ether_addr *ea; | |
| 514 | |
| 515 strncpy(ifba.ifba_name, brdg, sizeof(ifba.ifba_name)); | |
| 516 ea = ether_aton(addr); | |
| 517 if (ea == NULL) { | |
| 518 warnx2("Invalid address: %s", addr); | |
| 519 return (1); | |
| 520 } | |
| 521 bcopy(ea, &ifba.ifba_dst, sizeof(struct ether_addr)); | |
| 522 | |
| 523 if (ioctl(s, SIOCBRDGDADDR, &ifba) < 0) { | |
| 524 warnx3("%s: %s", brdg, addr); | |
| 525 return (1); | |
| 526 } | |
| 527 | |
| 528 return (0); | |
| 529 } | |
| 530 | |
| 531 int | |
| 532 bridge_addaddr(s, brdg, ifname, addr) | |
| 533 int s; | |
| 534 char *brdg, *ifname, *addr; | |
| 535 { | |
| 536 struct ifbareq ifba; | |
| 537 struct ether_addr *ea; | |
| 538 | |
| 539 strncpy(ifba.ifba_name, brdg, sizeof(ifba.ifba_name)); | |
| 540 strncpy(ifba.ifba_ifsname, ifname, sizeof(ifba.ifba_ifsname)); | |
| 541 | |
| 542 ea = ether_aton(addr); | |
| 543 if (ea == NULL) { | |
| 544 warnx2("Invalid address: %s", addr); | |
| 545 return (1); | |
| 546 } | |
| 547 bcopy(ea, &ifba.ifba_dst, sizeof(struct ether_addr)); | |
| 548 ifba.ifba_flags = IFBAF_STATIC; | |
| 549 | |
| 550 if (ioctl(s, SIOCBRDGSADDR, &ifba) < 0) { | |
| 551 warnx3("%s: %s", brdg, addr); | |
| 552 return (1); | |
| 553 } | |
| 554 | |
| 555 return (0); | |
| 556 } | |
| 557 | |
| 558 int | |
| 559 bridge_addrs(s, brdg, delim) | |
| 560 int s; | |
| 561 char *brdg, *delim; | |
| 562 { | |
| 563 struct ifbaconf ifbac; | |
| 564 struct ifbareq *ifba; | |
| 565 char *inbuf = NULL, buf[sizeof(ifba->ifba_ifsname) + 1]; | |
| 566 int i, len = 8192; | |
| 567 | |
| 568 while (1) { | |
| 569 ifbac.ifbac_len = len; | |
| 570 ifbac.ifbac_buf = inbuf = realloc(inbuf, len); | |
| 571 strncpy(ifbac.ifbac_name, brdg, sizeof(ifbac.ifbac_name)); | |
| 572 if (inbuf == NULL) | |
| 573 err(1, "malloc"); | |
| 574 if (ioctl(s, SIOCBRDGRTS, &ifbac) < 0) { | |
| 575 if (errno == ENETDOWN) | |
| 576 return (0); | |
| 577 err(1, brdg); | |
| 578 } | |
| 579 if (ifbac.ifbac_len + sizeof(*ifba) < len) | |
| 580 break; | |
| 581 len *= 2; | |
| 582 } | |
| 583 | |
| 584 for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) { | |
| 585 ifba = ifbac.ifbac_req + i; | |
| 586 strncpy(buf, ifba->ifba_ifsname, sizeof(buf)); | |
| 587 diag_printf("%s%s %s %d ", delim, ether_ntoa(&ifba->ifba_dst), | |
| 588 buf, ifba->ifba_age); | |
| 589 printb("flags", ifba->ifba_flags, IFBAFBITS); | |
| 590 diag_printf("\n"); | |
| 591 } | |
| 592 free(ifbac.ifbac_buf); | |
| 593 return (0); | |
| 594 } | |
| 595 | |
| 596 /* | |
| 597 * Check to make sure 'brdg' is really a bridge interface. | |
| 598 */ | |
| 599 int | |
| 600 is_bridge(s, brdg) | |
| 601 int s; | |
| 602 char *brdg; | |
| 603 { | |
| 604 struct ifreq ifr; | |
| 605 struct ifbaconf ifbac; | |
| 606 | |
| 607 strncpy(ifr.ifr_name, brdg, sizeof(ifr.ifr_name)); | |
| 608 | |
| 609 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) | |
| 610 return (0); | |
| 611 | |
| 612 ifbac.ifbac_len = 0; | |
| 613 strncpy(ifbac.ifbac_name, brdg, sizeof(ifbac.ifbac_name)); | |
| 614 if (ioctl(s, SIOCBRDGRTS, (caddr_t)&ifbac) < 0) { | |
| 615 if (errno == ENETDOWN) | |
| 616 return (1); | |
| 617 return (0); | |
| 618 } | |
| 619 return (1); | |
| 620 } | |
| 621 | |
| 622 int | |
| 623 bridge_status(s, brdg) | |
| 624 int s; | |
| 625 char *brdg; | |
| 626 { | |
| 627 struct ifreq ifr; | |
| 628 struct ifbcachereq ifbc; | |
| 629 struct ifbcachetoreq ifbct; | |
| 630 int err; | |
| 631 | |
| 632 strncpy(ifr.ifr_name, brdg, sizeof(ifr.ifr_name)); | |
| 633 if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { | |
| 634 warnx2("%s", brdg); | |
| 635 if (errno == EPERM) | |
| 636 return (1); | |
| 637 return (1); | |
| 638 } | |
| 639 | |
| 640 diag_printf("%s: ", brdg); | |
| 641 printb("flags", ifr.ifr_flags, IFFBITS); | |
| 642 diag_printf("\n"); | |
| 643 | |
| 644 diag_printf("Interfaces:\n"); | |
| 645 err = bridge_list(s, brdg, " "); | |
| 646 if (err) | |
| 647 return (err); | |
| 648 | |
| 649 strncpy(ifbc.ifbc_name, brdg, sizeof(ifbc.ifbc_name)); | |
| 650 if (ioctl(s, SIOCBRDGGCACHE, (caddr_t)&ifbc) < 0) { | |
| 651 warnx2("%s", brdg); | |
| 652 return (1); | |
| 653 } | |
| 654 | |
| 655 strncpy(ifbct.ifbct_name, brdg, sizeof(ifbct.ifbct_name)); | |
| 656 if (ioctl(s, SIOCBRDGGTO, (caddr_t)&ifbct) < 0) { | |
| 657 warnx2("%s", brdg); | |
| 658 return (1); | |
| 659 } | |
| 660 | |
| 661 diag_printf("Addresses (max cache: %d, timeout: %d):\n", | |
| 662 ifbc.ifbc_size, ifbct.ifbct_time); | |
| 663 | |
| 664 err = bridge_addrs(s, brdg, " "); | |
| 665 return (err); | |
| 666 } | |
| 667 | |
| 668 int | |
| 669 bridge_flush_rule(s, brdg, ifname) | |
| 670 int s; | |
| 671 char *brdg, *ifname; | |
| 672 { | |
| 673 struct ifbrlreq req; | |
| 674 | |
| 675 strncpy(req.ifbr_name, brdg, sizeof(req.ifbr_name)); | |
| 676 strncpy(req.ifbr_ifsname, ifname, sizeof(req.ifbr_ifsname)); | |
| 677 if (ioctl(s, SIOCBRDGFRL, &req) < 0) { | |
| 678 warnx3("%s: %s", brdg, ifname); | |
| 679 return (1); | |
| 680 } | |
| 681 return (0); | |
| 682 } | |
| 683 | |
| 684 int | |
| 685 bridge_rules(s, brdg, ifname, delim) | |
| 686 int s; | |
| 687 char *brdg, *ifname; | |
| 688 char *delim; | |
| 689 { | |
| 690 char *inbuf = NULL; | |
| 691 struct ifbrlconf ifc; | |
| 692 struct ifbrlreq *ifrp, ifreq; | |
| 693 int len = 8192, i; | |
| 694 | |
| 695 while (1) { | |
| 696 ifc.ifbrl_len = len; | |
| 697 ifc.ifbrl_buf = inbuf = realloc(inbuf, len); | |
| 698 strncpy(ifc.ifbrl_name, brdg, sizeof(ifc.ifbrl_name)); | |
| 699 strncpy(ifc.ifbrl_ifsname, ifname, sizeof(ifc.ifbrl_ifsname)); | |
| 700 if (inbuf == NULL) | |
| 701 err(1, "malloc"); | |
| 702 if (ioctl(s, SIOCBRDGGRL, &ifc) < 0) | |
| 703 err(1, "ioctl(SIOCBRDGGRL)"); | |
| 704 if (ifc.ifbrl_len + sizeof(ifreq) < len) | |
| 705 break; | |
| 706 len *= 2; | |
| 707 } | |
| 708 ifrp = ifc.ifbrl_req; | |
| 709 for (i = 0; i < ifc.ifbrl_len; i += sizeof(ifreq)) { | |
| 710 ifrp = (struct ifbrlreq *)((caddr_t)ifc.ifbrl_req + i); | |
| 711 bridge_showrule(ifrp, delim); | |
| 712 } | |
| 713 free(ifc.ifbrl_buf); | |
| 714 return (0); | |
| 715 } | |
| 716 | |
| 717 void | |
| 718 bridge_showrule(r, delim) | |
| 719 struct ifbrlreq *r; | |
| 720 char *delim; | |
| 721 { | |
| 722 if (delim) | |
| 723 diag_printf("%s ", delim); | |
| 724 else | |
| 725 diag_printf("%s: ", r->ifbr_name); | |
| 726 | |
| 727 if (r->ifbr_action == BRL_ACTION_BLOCK) | |
| 728 diag_printf("block "); | |
| 729 else if (r->ifbr_action == BRL_ACTION_PASS) | |
| 730 diag_printf("pass "); | |
| 731 else | |
| 732 diag_printf("[neither block nor pass?]\n"); | |
| 733 | |
| 734 if ((r->ifbr_flags & (BRL_FLAG_IN | BRL_FLAG_OUT)) == | |
| 735 (BRL_FLAG_IN | BRL_FLAG_OUT)) | |
| 736 diag_printf("in/out "); | |
| 737 else if (r->ifbr_flags & BRL_FLAG_IN) | |
| 738 diag_printf("in "); | |
| 739 else if (r->ifbr_flags & BRL_FLAG_OUT) | |
| 740 diag_printf("out "); | |
| 741 else | |
| 742 diag_printf("[neither in nor out?]\n"); | |
| 743 | |
| 744 diag_printf("on %s", r->ifbr_ifsname); | |
| 745 | |
| 746 if (r->ifbr_flags & BRL_FLAG_SRCVALID) | |
| 747 diag_printf(" src %s", ether_ntoa(&r->ifbr_src)); | |
| 748 if (r->ifbr_flags & BRL_FLAG_DSTVALID) | |
| 749 diag_printf(" dst %s", ether_ntoa(&r->ifbr_dst)); | |
| 750 | |
| 751 diag_printf("\n"); | |
| 752 } | |
| 753 | |
| 754 /* | |
| 755 * Parse a rule definition and send it upwards. | |
| 756 * | |
| 757 * Syntax: | |
| 758 * {block|pass} {in|out|in/out} on {ifs} [src {mac}] [dst {mac}] | |
| 759 */ | |
| 760 int | |
| 761 bridge_rule(int s, char *brdg, int targc, char **targv, int ln) | |
| 762 { | |
| 763 char **argv = targv; | |
| 764 int argc = targc; | |
| 765 struct ifbrlreq rule; | |
| 766 struct ether_addr *ea, *dea; | |
| 767 | |
| 768 if (argc == 0) { | |
| 769 diag_printf( "invalid rule\n"); | |
| 770 return (1); | |
| 771 } | |
| 772 rule.ifbr_flags = 0; | |
| 773 rule.ifbr_action = 0; | |
| 774 strncpy(rule.ifbr_name, brdg, sizeof(rule.ifbr_name)); | |
| 775 | |
| 776 if (strcmp(argv[0], "block") == 0) | |
| 777 rule.ifbr_action = BRL_ACTION_BLOCK; | |
| 778 else if (strcmp(argv[0], "pass") == 0) | |
| 779 rule.ifbr_action = BRL_ACTION_PASS; | |
| 780 else | |
| 781 goto bad_rule; | |
| 782 argc--; argv++; | |
| 783 | |
| 784 if (argc == 0) { | |
| 785 bridge_badrule(targc, targv, ln); | |
| 786 return (1); | |
| 787 } | |
| 788 if (strcmp(argv[0], "in") == 0) | |
| 789 rule.ifbr_flags |= BRL_FLAG_IN; | |
| 790 else if (strcmp(argv[0], "out") == 0) | |
| 791 rule.ifbr_flags |= BRL_FLAG_OUT; | |
| 792 else if (strcmp(argv[0], "in/out") == 0) | |
| 793 rule.ifbr_flags |= BRL_FLAG_IN | BRL_FLAG_OUT; | |
| 794 else | |
| 795 goto bad_rule; | |
| 796 argc--; argv++; | |
| 797 | |
| 798 if (argc == 0 || strcmp(argv[0], "on")) | |
| 799 goto bad_rule; | |
| 800 argc--; argv++; | |
| 801 | |
| 802 if (argc == 0) | |
| 803 goto bad_rule; | |
| 804 strncpy(rule.ifbr_ifsname, argv[0], sizeof(rule.ifbr_ifsname)); | |
| 805 argc--; argv++; | |
| 806 | |
| 807 while (argc) { | |
| 808 if (strcmp(argv[0], "dst") == 0) { | |
| 809 if (rule.ifbr_flags & BRL_FLAG_DSTVALID) | |
| 810 goto bad_rule; | |
| 811 rule.ifbr_flags |= BRL_FLAG_DSTVALID; | |
| 812 dea = &rule.ifbr_dst; | |
| 813 } | |
| 814 else if (strcmp(argv[0], "src") == 0) { | |
| 815 if (rule.ifbr_flags & BRL_FLAG_SRCVALID) | |
| 816 goto bad_rule; | |
| 817 rule.ifbr_flags |= BRL_FLAG_SRCVALID; | |
| 818 dea = &rule.ifbr_src; | |
| 819 } | |
| 820 else | |
| 821 goto bad_rule; | |
| 822 | |
| 823 argc--; argv++; | |
| 824 | |
| 825 if (argc == 0) | |
| 826 goto bad_rule; | |
| 827 ea = ether_aton(argv[0]); | |
| 828 if (ea == NULL) { | |
| 829 warnx2("Invalid address: %s", argv[0]); | |
| 830 return (1); | |
| 831 } | |
| 832 bcopy(ea, dea, sizeof(*dea)); | |
| 833 argc--; argv++; | |
| 834 } | |
| 835 | |
| 836 if (ioctl(s, SIOCBRDGARL, &rule) < 0) { | |
| 837 warnx2("%s", brdg); | |
| 838 return (1); | |
| 839 } | |
| 840 return (0); | |
| 841 | |
| 842 bad_rule: | |
| 843 bridge_badrule(targc, targv, ln); | |
| 844 return (1); | |
| 845 } | |
| 846 | |
| 847 #define MAXRULEWORDS 8 | |
| 848 #ifdef ZAP | |
| 849 int | |
| 850 bridge_rulefile(s, brdg, fname) | |
| 851 int s; | |
| 852 char *brdg, *fname; | |
| 853 { | |
| 854 FILE *f; | |
| 855 char *str, *argv[MAXRULEWORDS], buf[1024], xbuf[1024]; | |
| 856 int ln = 1, argc = 0, err = 0, xerr; | |
| 857 | |
| 858 f = fopen(fname, "r"); | |
| 859 if (f == NULL) { | |
| 860 warnx2("%s", fname); | |
| 861 return (1); | |
| 862 } | |
| 863 | |
| 864 while (1) { | |
| 865 fgets(buf, sizeof(buf), f); | |
| 866 if (feof(f)) | |
| 867 break; | |
| 868 ln++; | |
| 869 if (buf[0] == '#') | |
| 870 continue; | |
| 871 | |
| 872 argc = 0; | |
| 873 str = strtok(buf, "\n\r "); | |
| 874 strncpy(xbuf, buf, sizeof(xbuf)); | |
| 875 while (str != NULL) { | |
| 876 argv[argc++] = str; | |
| 877 if (argc > MAXRULEWORDS) { | |
| 878 diag_printf( "invalid rule: %d: %s\n", | |
| 879 ln, xbuf); | |
| 880 break; | |
| 881 } | |
| 882 str = strtok(NULL, "\n\r "); | |
| 883 } | |
| 884 | |
| 885 if (argc > MAXRULEWORDS) | |
| 886 continue; | |
| 887 | |
| 888 xerr = bridge_rule(s, brdg, argc, argv, ln); | |
| 889 if (xerr) | |
| 890 err = xerr; | |
| 891 } | |
| 892 fclose(f); | |
| 893 return (err); | |
| 894 } | |
| 895 #endif | |
| 896 void | |
| 897 bridge_badrule(argc, argv, ln) | |
| 898 int argc, ln; | |
| 899 char **argv; | |
| 900 { | |
| 901 int i; | |
| 902 | |
| 903 diag_printf( "invalid rule: "); | |
| 904 if (ln != -1) | |
| 905 diag_printf( "%d: ", ln); | |
| 906 for (i = 0; i < argc; i++) { | |
| 907 diag_printf( "%s ", argv[i]); | |
| 908 } | |
| 909 diag_printf( "\n"); | |
| 910 } | |
| 911 | |
| 912 /* | |
| 913 * Print a value ala the %b format of the kernel's printf | |
| 914 * (borrowed from ifconfig.c) | |
| 915 */ | |
| 916 void | |
| 917 printb(s, v, bits) | |
| 918 char *s; | |
| 919 char *bits; | |
| 920 unsigned short v; | |
| 921 { | |
| 922 register int i, any = 0; | |
| 923 register char c; | |
| 924 | |
| 925 if (bits && *bits == 8) | |
| 926 diag_printf("%s=%o", s, v); | |
| 927 else | |
| 928 diag_printf("%s=%x", s, v); | |
| 929 bits++; | |
| 930 if (bits) { | |
| 931 diag_printf("<"); | |
| 932 while ((i = *bits++)) { | |
| 933 if (v & (1 << (i-1))) { | |
| 934 if (any) | |
| 935 diag_printf(","); | |
| 936 any = 1; | |
| 937 for (; (c = *bits) > 32; bits++) | |
| 938 diag_printf("%c",c); | |
| 939 } else | |
| 940 for (; *bits > 32; bits++) | |
| 941 ; | |
| 942 } | |
| 943 diag_printf(">"); | |
| 944 } | |
| 945 } | |
| 946 | |
| 947 static void | |
| 948 interface_up(const char *intf) | |
| 949 { | |
| 950 struct ifreq ifr; | |
| 951 int s; | |
| 952 | |
| 953 s = socket(AF_INET, SOCK_DGRAM, 0); | |
| 954 if (s < 0) { | |
| 955 perror("socket"); | |
| 956 return; | |
| 957 } | |
| 958 | |
| 959 strcpy(ifr.ifr_name, intf); | |
| 960 ifr.ifr_flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING; | |
| 961 if (ioctl(s, SIOCSIFFLAGS, &ifr)) { | |
| 962 perror("SIOCSIFFLAGS"); | |
| 963 } | |
| 964 close(s); | |
| 965 } | |
| 966 | |
| 967 static void | |
| 968 main_fn(cyg_addrword_t data) { | |
| 969 | |
| 970 int sock; | |
| 971 char brdg[] = "bridge0"; | |
| 972 | |
| 973 sock = socket(AF_INET, SOCK_DGRAM, 0); | |
| 974 assert(sock >= 0); | |
| 975 | |
| 976 #ifdef CYGHWR_NET_DRIVER_ETH0 | |
| 977 interface_up("eth0"); | |
| 978 eth0_up = 1; | |
| 979 bridge_add(sock,brdg,"eth0"); | |
| 980 #endif | |
| 981 #ifdef CYGHWR_NET_DRIVER_ETH1 | |
| 982 interface_up("eth1"); | |
| 983 eth1_up = 1; | |
| 984 bridge_add(sock,brdg,"eth1"); | |
| 985 #endif | |
| 986 | |
| 987 bridge_status(sock,brdg); | |
| 988 bridge_setflag(sock,brdg, IFF_UP); | |
| 989 | |
| 990 while(1) { | |
| 991 cyg_kmem_print_stats(); | |
| 992 cyg_thread_delay(500); | |
| 993 } | |
| 994 } | |
| 995 | |
| 996 static char main_stack[8192]; | |
| 997 static cyg_handle_t main_handle; | |
| 998 static cyg_thread main_thread; | |
| 999 | |
| 1000 void | |
| 1001 cyg_user_start(void) { | |
| 1002 printf("cyg_user_start starting\n"); | |
| 1003 cyg_thread_create(4, &main_fn, 0, "main", &main_stack, sizeof(main_stack), | |
| 1004 &main_handle, &main_thread); | |
| 1005 cyg_thread_resume(main_handle); | |
| 1006 printf("cyg_user_start done\n"); | |
| 1007 } | |
| 1008 | |
| 1009 |
