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