Commit aaa4e704 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by David S. Miller

DECnet: Only use neigh_ops for adding the link layer header

Other users users of the neighbour table use neigh->output as the method
to decided when and which link-layer header to place on a packet.
DECnet has been using neigh->output to decide which DECnet headers to
place on a packet depending which neighbour the packet is destined for.

The DECnet usage isn't totally wrong but it can run into problems if the
neighbour output function is run for a second time as the teql driver
and the bridge netfilter code can do.

Therefore to avoid pathologic problems later down the line and make the
neighbour code easier to understand by refactoring the decnet output
code to only use a neighbour method to add a link layer header to a
packet.

This is done by moving the neigbhour operations lookup from
dn_to_neigh_output to dn_neigh_output_packet.
Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 616f4541
...@@ -22,6 +22,7 @@ int dn_neigh_router_hello(struct sk_buff *skb); ...@@ -22,6 +22,7 @@ int dn_neigh_router_hello(struct sk_buff *skb);
int dn_neigh_endnode_hello(struct sk_buff *skb); int dn_neigh_endnode_hello(struct sk_buff *skb);
void dn_neigh_pointopoint_hello(struct sk_buff *skb); void dn_neigh_pointopoint_hello(struct sk_buff *skb);
int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n); int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n);
int dn_to_neigh_output(struct sk_buff *skb);
extern struct neigh_table dn_neigh_table; extern struct neigh_table dn_neigh_table;
......
...@@ -49,41 +49,17 @@ ...@@ -49,41 +49,17 @@
#include <net/dn_route.h> #include <net/dn_route.h>
static int dn_neigh_construct(struct neighbour *); static int dn_neigh_construct(struct neighbour *);
static void dn_long_error_report(struct neighbour *, struct sk_buff *); static void dn_neigh_error_report(struct neighbour *, struct sk_buff *);
static void dn_short_error_report(struct neighbour *, struct sk_buff *); static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb);
static int dn_long_output(struct neighbour *, struct sk_buff *);
static int dn_short_output(struct neighbour *, struct sk_buff *);
static int dn_phase3_output(struct neighbour *, struct sk_buff *);
/*
* For talking to broadcast devices: Ethernet & PPP
*/
static const struct neigh_ops dn_long_ops = {
.family = AF_DECnet,
.error_report = dn_long_error_report,
.output = dn_long_output,
.connected_output = dn_long_output,
};
/* /*
* For talking to pointopoint and multidrop devices: DDCMP and X.25 * Operations for adding the link layer header.
*/ */
static const struct neigh_ops dn_short_ops = { static const struct neigh_ops dn_neigh_ops = {
.family = AF_DECnet, .family = AF_DECnet,
.error_report = dn_short_error_report, .error_report = dn_neigh_error_report,
.output = dn_short_output, .output = dn_neigh_output,
.connected_output = dn_short_output, .connected_output = dn_neigh_output,
};
/*
* For talking to DECnet phase III nodes
*/
static const struct neigh_ops dn_phase3_ops = {
.family = AF_DECnet,
.error_report = dn_short_error_report, /* Can use short version here */
.output = dn_phase3_output,
.connected_output = dn_phase3_output,
}; };
static u32 dn_neigh_hash(const void *pkey, static u32 dn_neigh_hash(const void *pkey,
...@@ -153,16 +129,9 @@ static int dn_neigh_construct(struct neighbour *neigh) ...@@ -153,16 +129,9 @@ static int dn_neigh_construct(struct neighbour *neigh)
__neigh_parms_put(neigh->parms); __neigh_parms_put(neigh->parms);
neigh->parms = neigh_parms_clone(parms); neigh->parms = neigh_parms_clone(parms);
if (dn_db->use_long)
neigh->ops = &dn_long_ops;
else
neigh->ops = &dn_short_ops;
rcu_read_unlock(); rcu_read_unlock();
if (dn->flags & DN_NDFLAG_P3) neigh->ops = &dn_neigh_ops;
neigh->ops = &dn_phase3_ops;
neigh->nud_state = NUD_NOARP; neigh->nud_state = NUD_NOARP;
neigh->output = neigh->ops->connected_output; neigh->output = neigh->ops->connected_output;
...@@ -194,24 +163,16 @@ static int dn_neigh_construct(struct neighbour *neigh) ...@@ -194,24 +163,16 @@ static int dn_neigh_construct(struct neighbour *neigh)
return 0; return 0;
} }
static void dn_long_error_report(struct neighbour *neigh, struct sk_buff *skb) static void dn_neigh_error_report(struct neighbour *neigh, struct sk_buff *skb)
{
printk(KERN_DEBUG "dn_long_error_report: called\n");
kfree_skb(skb);
}
static void dn_short_error_report(struct neighbour *neigh, struct sk_buff *skb)
{ {
printk(KERN_DEBUG "dn_short_error_report: called\n"); printk(KERN_DEBUG "dn_neigh_error_report: called\n");
kfree_skb(skb); kfree_skb(skb);
} }
static int dn_neigh_output_packet(struct sk_buff *skb) static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb)
{ {
struct dst_entry *dst = skb_dst(skb); struct dst_entry *dst = skb_dst(skb);
struct dn_route *rt = (struct dn_route *)dst; struct dn_route *rt = (struct dn_route *)dst;
struct neighbour *neigh = rt->n;
struct net_device *dev = neigh->dev; struct net_device *dev = neigh->dev;
char mac_addr[ETH_ALEN]; char mac_addr[ETH_ALEN];
unsigned int seq; unsigned int seq;
...@@ -233,6 +194,18 @@ static int dn_neigh_output_packet(struct sk_buff *skb) ...@@ -233,6 +194,18 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
return err; return err;
} }
static int dn_neigh_output_packet(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
struct dn_route *rt = (struct dn_route *)dst;
struct neighbour *neigh = rt->n;
return neigh->output(neigh, skb);
}
/*
* For talking to broadcast devices: Ethernet & PPP
*/
static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb) static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)
{ {
struct net_device *dev = neigh->dev; struct net_device *dev = neigh->dev;
...@@ -276,6 +249,9 @@ static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb) ...@@ -276,6 +249,9 @@ static int dn_long_output(struct neighbour *neigh, struct sk_buff *skb)
neigh->dev, dn_neigh_output_packet); neigh->dev, dn_neigh_output_packet);
} }
/*
* For talking to pointopoint and multidrop devices: DDCMP and X.25
*/
static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb) static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb)
{ {
struct net_device *dev = neigh->dev; struct net_device *dev = neigh->dev;
...@@ -313,7 +289,8 @@ static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb) ...@@ -313,7 +289,8 @@ static int dn_short_output(struct neighbour *neigh, struct sk_buff *skb)
} }
/* /*
* Phase 3 output is the same is short output, execpt that * For talking to DECnet phase III nodes
* Phase 3 output is the same as short output, execpt that
* it clears the area bits before transmission. * it clears the area bits before transmission.
*/ */
static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb) static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb)
...@@ -351,6 +328,32 @@ static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb) ...@@ -351,6 +328,32 @@ static int dn_phase3_output(struct neighbour *neigh, struct sk_buff *skb)
neigh->dev, dn_neigh_output_packet); neigh->dev, dn_neigh_output_packet);
} }
int dn_to_neigh_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
struct dn_route *rt = (struct dn_route *) dst;
struct neighbour *neigh = rt->n;
struct dn_neigh *dn = (struct dn_neigh *)neigh;
struct dn_dev *dn_db;
bool use_long;
rcu_read_lock();
dn_db = rcu_dereference(neigh->dev->dn_ptr);
if (dn_db == NULL) {
rcu_read_unlock();
return -EINVAL;
}
use_long = dn_db->use_long;
rcu_read_unlock();
if (dn->flags & DN_NDFLAG_P3)
return dn_phase3_output(neigh, skb);
if (use_long)
return dn_long_output(neigh, skb);
else
return dn_short_output(neigh, skb);
}
/* /*
* Unfortunately, the neighbour code uses the device in its hash * Unfortunately, the neighbour code uses the device in its hash
* function, so we don't get any advantage from it. This function * function, so we don't get any advantage from it. This function
......
...@@ -743,15 +743,6 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type ...@@ -743,15 +743,6 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
return NET_RX_DROP; return NET_RX_DROP;
} }
static int dn_to_neigh_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
struct dn_route *rt = (struct dn_route *) dst;
struct neighbour *n = rt->n;
return n->output(n, skb);
}
static int dn_output(struct sock *sk, struct sk_buff *skb) static int dn_output(struct sock *sk, struct sk_buff *skb)
{ {
struct dst_entry *dst = skb_dst(skb); struct dst_entry *dst = skb_dst(skb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment