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