File: advanced.bridge.patch

package info (click to toggle)
bridgex 0.25
  • links: PTS
  • area: main
  • in suites: hamm, slink
  • size: 80 kB
  • ctags: 156
  • sloc: ansic: 522; makefile: 40; sh: 28
file content (206 lines) | stat: -rw-r--r-- 6,280 bytes parent folder | download
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