patch-2.3.99-pre9 linux/drivers/net/pppoe.c
Next file: linux/drivers/net/setup.c
Previous file: linux/drivers/net/ppp_synctty.c
Back to the patch index
Back to the overall index
- Lines: 197
- Date:
Mon May 22 09:50:55 2000
- Orig file:
v2.3.99-pre8/linux/drivers/net/pppoe.c
- Orig date:
Fri May 12 14:18:55 2000
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c
@@ -33,6 +33,7 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/init.h>
+#include <linux/if_ether.h>
#include <linux/if_pppox.h>
#include <net/sock.h>
#include <linux/ppp_channel.h>
@@ -46,10 +47,12 @@
static int __attribute__((unused)) pppoe_debug = 7;
-#define PPPOE_HASH_SIZE 16
+#define PPPOE_HASH_BITS 4
+#define PPPOE_HASH_SIZE (1<<PPPOE_HASH_BITS)
int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb);
+int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
struct proto_ops pppoe_ops;
@@ -81,23 +84,18 @@
static int hash_item(unsigned long sid, unsigned char *addr)
{
- int i = 0;
- union {
- char c[sizeof(unsigned long)];
- unsigned long i;
- } hash;
-
- hash.i = sid;
-
- for (i = 0; i < ETH_ALEN; ++i)
- hash.c[0] = hash.c[0] ^ addr[i];
-
- for (i = 1; i < sizeof(int); ++i)
- hash.c[0] = hash.c[0] ^ hash.c[i];
+ char hash=0;
+ int i,j;
+ for (i = 0; i < ETH_ALEN ; ++i){
+ for (j = 0; j < 8/PPPOE_HASH_BITS ; ++j){
+ hash ^= addr[i] >> ( j * PPPOE_HASH_BITS );
+ }
+ }
- i = (int) (hash.c[0] & (PPPOE_HASH_SIZE - 1));
+ for (i = 0; i < (sizeof(unsigned long)*8) / PPPOE_HASH_BITS ; ++i)
+ hash ^= sid >> (i*PPPOE_HASH_BITS);
- return i;
+ return hash & ( PPPOE_HASH_SIZE - 1 );
}
static struct pppox_opt *item_hash_table[PPPOE_HASH_SIZE] = { 0, };
@@ -105,7 +103,7 @@
/**********************************************************************
*
* Set/get/delete/rehash items (internal versions)
- *
+ *
**********************************************************************/
static struct pppox_opt *__get_item(unsigned long sid, unsigned char *addr)
{
@@ -162,7 +160,7 @@
return ret;
}
-static struct pppox_opt *__find_on_dev(struct net_device *dev,
+static struct pppox_opt *__find_on_dev(struct net_device *dev,
struct pppox_opt *start)
{
struct pppox_opt *po;
@@ -195,9 +193,9 @@
/**********************************************************************
*
* Set/get/delete/rehash items
- *
+ *
**********************************************************************/
-static inline struct pppox_opt *get_item(unsigned long sid,
+static inline struct pppox_opt *get_item(unsigned long sid,
unsigned char *addr)
{
struct pppox_opt *po;
@@ -239,7 +237,7 @@
return ret;
}
-static struct pppox_opt *find_on_dev(struct net_device *dev,
+static struct pppox_opt *find_on_dev(struct net_device *dev,
struct pppox_opt *start)
{
struct pppox_opt *po;
@@ -255,7 +253,7 @@
* Certain device events require that sockets be unconnected
*
**************************************************************************/
-static int pppoe_device_event(struct notifier_block *this,
+static int pppoe_device_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
int error = NOTIFY_DONE;
@@ -277,7 +275,7 @@
if (po->sk->state & PPPOX_CONNECTED)
pppox_unbind_sock(po->sk);
-
+
if (po->sk->state & PPPOX_CONNECTED) {
lock_sock(po->sk);
po->sk->shutdown = RCV_SHUTDOWN&SEND_SHUTDOWN;
@@ -313,7 +311,7 @@
* Receive a PPPoE Session frame.
*
***********************************************************************/
-static int pppoe_rcv(struct sk_buff *skb,
+static int pppoe_rcv(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt)
@@ -336,6 +334,19 @@
skb_pull(skb, sizeof(struct pppoe_hdr));
ppp_input(&po->chan, skb);
+ } else if( sk->state & PPPOX_RELAY ){
+ struct pppox_opt *relay_po;
+
+ relay_po = get_item_by_addr( &po->pppoe_relay );
+
+ if( relay_po == NULL ||
+ !( relay_po->sk->state & PPPOX_CONNECTED ) )
+ goto abort;
+
+ skb_pull(skb, sizeof(struct pppoe_hdr));
+ if( !__pppoe_xmit( relay_po->sk , skb) )
+ goto abort;
+
} else {
sock_queue_rcv_skb(sk, skb);
}
@@ -353,7 +364,7 @@
* -- This is solely for detection of PADT frames
*
***********************************************************************/
-static int pppoe_disc_rcv(struct sk_buff *skb,
+static int pppoe_disc_rcv(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt)
@@ -539,7 +550,7 @@
dev = dev_get_by_name(sp->sa_addr.pppoe.dev);
- error = -ENODEV;
+ error = -ENODEV;
if (!dev)
goto end;
@@ -768,13 +779,11 @@
/************************************************************************
*
- * xmit function called by generic PPP driver
- * sends PPP frame over PPPoE socket
+ * xmit function for internal use.
*
***********************************************************************/
-int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
{
- struct sock *sk = (struct sock *) chan->private;
struct net_device *dev = sk->protinfo.pppox->pppoe_dev;
struct pppoe_hdr hdr;
struct pppoe_hdr *ph;
@@ -832,6 +841,20 @@
abort:
return 0;
}
+
+
+/************************************************************************
+ *
+ * xmit function called by generic PPP driver
+ * sends PPP frame over PPPoE socket
+ *
+ ***********************************************************************/
+int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+ struct sock *sk = (struct sock *) chan->private;
+ return __pppoe_xmit(sk, skb);
+}
+
struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL };
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)