1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
diff -urN linux/include/net/br.h linux.bridge/include/net/br.h
--- linux/include/net/br.h Thu Apr 11 23:49:47 1996
+++ linux.bridge/include/net/br.h Mon Sep 16 20:11:21 1996
@@ -161,15 +161,29 @@
#define IS_BRIDGED 0x2e
+
+#define BR_MAX_PROTOCOLS 32
+#define BR_MAX_PROT_STATS BR_MAX_PROTOCOLS
+
+/* policy values for policy field */
+#define BR_ACCEPT 1
+#define BR_REJECT 0
+
struct br_stat {
unsigned int flags;
Bridge_data bridge_data;
Port_data port_data[No_of_ports];
+ unsigned int policy;
+ unsigned int exempt_protocols;
+ unsigned short protocols[BR_MAX_PROTOCOLS];
+ unsigned short prot_id[BR_MAX_PROT_STATS]; /* Protocol encountered */
+ unsigned int prot_counter[BR_MAX_PROT_STATS]; /* How many packets ? */
};
/* defined flags for br_stat.flags */
#define BR_UP 0x0001 /* bridging enabled */
#define BR_DEBUG 0x0002 /* debugging enabled */
+#define BR_PROT_STATS 0x0004 /* protocol statistics enabled */
struct br_cf {
unsigned int cmd;
@@ -188,6 +202,11 @@
#define BRCMD_DISPLAY_FDB 8 /* arg1 = port */
#define BRCMD_ENABLE_DEBUG 9
#define BRCMD_DISABLE_DEBUG 10
+#define BRCMD_SET_POLICY 11 /* arg1 = default policy (1==bridge all) */
+#define BRCMD_EXEMPT_PROTOCOL 12 /* arg1 = protocol (see net/if_ether.h) */
+#define BRCMD_ENABLE_PROT_STATS 13
+#define BRCMD_DISABLE_PROT_STATS 14
+#define BRCMD_ZERO_PROT_STATS 15
/* prototypes of all bridging functions... */
@@ -260,6 +279,8 @@
int br_receive_frame(struct sk_buff *skb); /* 3.5 */
int br_tx_frame(struct sk_buff *skb);
int br_ioctl(unsigned int cmd, void *arg);
+
+int br_protocol_ok(unsigned short protocol);
void free_fdb(struct fdb *);
struct fdb *get_fdb(void);
diff -urN linux/net/bridge/br.c linux.bridge/net/bridge/br.c
--- linux/net/bridge/br.c Thu Jul 18 22:24:05 1996
+++ linux.bridge/net/bridge/br.c Mon Sep 16 21:30:06 1996
@@ -3,6 +3,10 @@
*
* Originally by John Hayes (Network Plumbing).
* Minor hacks to get it to run with 1.3.x by Alan Cox <Alan.Cox@linux.org>
+ * More hacks to be able to switch protocols on and off by Christoph Lameter
+ * <clameter@debian.org>
+ * Software and more Documentation for the bridge is available from ftp.debian.org
+ * in the bridge package or at ftp.fuller.edu/Linux/bridge
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -79,6 +83,67 @@
0
};
+/*
+ * Implementation of Protocol specific bridging
+ *
+ * The protocols to be bridged or not to be bridged are stored in a hashed array. This is the old type
+ * of unlinked hash array where one simply takes the next cell if the one the hash function points to
+ * is occupied.
+ */
+
+#define BR_PROTOCOL_HASH(x) (x % BR_MAX_PROTOCOLS)
+
+/* Checks if that protocol type is to be bridged */
+int br_protocol_ok(unsigned short protocol)
+{
+ unsigned x;
+
+ /* See if protocol statistics are to be kept */
+ if (br_stats.flags & BR_PROT_STATS)
+ { for(x=0;x<BR_MAX_PROT_STATS &&
+ br_stats.prot_id[x]!=protocol && br_stats.prot_id[x];x++) ;
+ if (x<BR_MAX_PROT_STATS)
+ { br_stats.prot_id[x]=protocol;br_stats.prot_counter[x]++;
+ }
+ }
+
+ for (x=BR_PROTOCOL_HASH(protocol); br_stats.protocols[x]!=0;) {
+ if (br_stats.protocols[x]==protocol) return !br_stats.policy;
+ x++;
+ if (x==BR_MAX_PROTOCOLS) x=0;
+ }
+ return br_stats.policy;
+}
+
+/* Add a protocol to be handled opposite to the standard policy of the bridge */
+
+int br_add_exempt_protocol(unsigned short p)
+{
+ unsigned x;
+ if (p == 0) return -EINVAL;
+ if (br_stats.exempt_protocols > BR_MAX_PROTOCOLS-2) return -EXFULL;
+ for (x=BR_PROTOCOL_HASH(p);br_stats.protocols[x]!=0;) {
+ if (br_stats.protocols[x]==p) return 0; /* Attempt to add the protocol a second time */
+ x++;
+ if (x==BR_MAX_PROTOCOLS) x=0;
+ }
+ br_stats.protocols[x]=p;
+ br_stats.exempt_protocols++;
+ return 0;
+}
+
+/* Valid Policies are 0=No Protocols bridged 1=Bridge all protocols */
+int br_set_policy(int policy)
+{
+ if (policy>1) return -EINVAL;
+ br_stats.policy=policy;
+ /* Policy change means initializing the exempt table */
+ memset(br_stats.protocols,0,sizeof(br_stats.protocols));
+ br_stats.exempt_protocols = 0;
+ return 0;
+}
+
+
/** Elements of Procedure (4.6) **/
/*
@@ -611,6 +676,8 @@
register_netdevice_notifier(&br_dev_notifier);
br_stats.flags = 0; /*BR_UP | BR_DEBUG*/; /* enable bridge */
+ br_stats.policy = BR_ACCEPT; /* Enable bridge to accpet all protocols */
+ br_stats.exempt_protocols = 0;
/*start_hello_timer();*/
}
@@ -1137,7 +1204,6 @@
/* happen in net_bh() in dev.c) */
}
/* ok, forward this frame... */
- skb_device_lock(skb);
return(br_forward(skb, port));
default:
printk(KERN_DEBUG "br_receive_frame: port [%i] unknown state [%i]\n",
@@ -1454,7 +1520,7 @@
case SIOCSIFBR:
if (!suser())
return -EPERM;
- err = verify_area(VERIFY_READ, arg,
+ err = verify_area(VERIFY_READ , arg,
sizeof(struct br_cf));
if(err)
return err;
@@ -1514,6 +1580,20 @@
case BRCMD_DISABLE_DEBUG:
br_stats.flags &= ~BR_DEBUG;
break;
+ case BRCMD_SET_POLICY:
+ return br_set_policy(bcf.arg1);
+ case BRCMD_EXEMPT_PROTOCOL:
+ return br_add_exempt_protocol(bcf.arg1);
+ case BRCMD_ENABLE_PROT_STATS:
+ br_stats.flags |= BR_PROT_STATS;
+ break;
+ case BRCMD_DISABLE_PROT_STATS:
+ br_stats.flags &= ~BR_PROT_STATS;
+ break;
+ case BRCMD_ZERO_PROT_STATS:
+ memset(&br_stats.prot_id,0,sizeof(br_stats.prot_id));
+ memset(&br_stats.prot_counter,0,sizeof(br_stats.prot_counter));
+ break;
default:
return -EINVAL;
}
@@ -1539,4 +1619,4 @@
}
return(0);
}
-
+
diff -urN linux/net/core/dev.c linux.bridge/net/core/dev.c
--- linux/net/core/dev.c Thu Aug 1 05:43:04 1996
+++ linux.bridge/net/core/dev.c Fri Sep 13 05:24:24 1996
@@ -603,10 +603,11 @@
/*
* If we are bridging then pass the frame up to the
- * bridging code. If it is bridged then move on
+ * bridging code (if this protocol is to be bridged).
+ * If it is bridged then move on
*/
- if (br_stats.flags & BR_UP)
+ if (br_stats.flags & BR_UP && br_protocol_ok(ntohs(skb->protocol)))
{
/*
* We pass the bridge a complete frame. This means
|