Merge branch 'neigh_cleanups'
Eric W. Biederman says: ==================== Neighbour table and ax25 cleanups While looking at the neighbour table to what it would take to allow using next hops in a different address family than the current packets I found a partial resolution for my issues and I stumbled upon some work that makes the neighbour table code easier to understand and maintain. Long ago in a much younger kernel ax25 found a hack to use dev_rebuild_header to transmit it's packets instead of going through what today is ndo_start_xmit. When the neighbour table was rewritten into it's current form the ax25 code was such a challenge that arp_broken_ops appeard in arp.c and neigh_compat_output appeared in neighbour.c to keep the ax25 hack alive. With a little bit of work I was able to remove some of the hack that is the ax25 transmit path for ip packets and to isolate what remains into a slightly more readable piece of code in ax25_ip.c. Removing the need for the generic code to worry about ax25 special cases. After cleaning up the old ax25 hacks I also performed a little bit of work on neigh_resolve_output to remove the need for a dst entry and to ensure cached headers get a deterministic protocol value in their cached header. This guarantees that a cached header will not be different depending on which protocol of packet is transmitted, and it allows packets to be transmitted that don't have a dst entry. There remains a small amount of code that takes advantage of when packets have a dst entry but that is something different. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b898441f4e
@ -237,18 +237,6 @@ static int fwnet_header_create(struct sk_buff *skb, struct net_device *net,
|
||||
return -net->hard_header_len;
|
||||
}
|
||||
|
||||
static int fwnet_header_rebuild(struct sk_buff *skb)
|
||||
{
|
||||
struct fwnet_header *h = (struct fwnet_header *)skb->data;
|
||||
|
||||
if (get_unaligned_be16(&h->h_proto) == ETH_P_IP)
|
||||
return arp_find((unsigned char *)&h->h_dest, skb);
|
||||
|
||||
dev_notice(&skb->dev->dev, "unable to resolve type %04x addresses\n",
|
||||
be16_to_cpu(h->h_proto));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fwnet_header_cache(const struct neighbour *neigh,
|
||||
struct hh_cache *hh, __be16 type)
|
||||
{
|
||||
@ -282,7 +270,6 @@ static int fwnet_header_parse(const struct sk_buff *skb, unsigned char *haddr)
|
||||
|
||||
static const struct header_ops fwnet_header_ops = {
|
||||
.create = fwnet_header_create,
|
||||
.rebuild = fwnet_header_rebuild,
|
||||
.cache = fwnet_header_cache,
|
||||
.cache_update = fwnet_header_cache_update,
|
||||
.parse = fwnet_header_parse,
|
||||
|
@ -1951,38 +1951,6 @@ static int isdn_net_header(struct sk_buff *skb, struct net_device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
/* We don't need to send arp, because we have point-to-point connections. */
|
||||
static int
|
||||
isdn_net_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
isdn_net_local *lp = netdev_priv(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
|
||||
struct ethhdr *eth = (struct ethhdr *) skb->data;
|
||||
|
||||
/*
|
||||
* Only ARP/IP is currently supported
|
||||
*/
|
||||
|
||||
if (eth->h_proto != htons(ETH_P_IP)) {
|
||||
printk(KERN_WARNING
|
||||
"isdn_net: %s don't know how to resolve type %d addresses?\n",
|
||||
dev->name, (int) eth->h_proto);
|
||||
memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Try to get ARP to resolve the header.
|
||||
*/
|
||||
#ifdef CONFIG_INET
|
||||
ret = arp_find(eth->h_dest, skb);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
|
||||
__be16 type)
|
||||
{
|
||||
@ -2005,7 +1973,6 @@ static void isdn_header_cache_update(struct hh_cache *hh,
|
||||
|
||||
static const struct header_ops isdn_header_ops = {
|
||||
.create = isdn_net_header,
|
||||
.rebuild = isdn_net_rebuild_header,
|
||||
.cache = isdn_header_cache,
|
||||
.cache_update = isdn_header_cache_update,
|
||||
};
|
||||
|
@ -1190,7 +1190,6 @@ static int dvb_net_stop(struct net_device *dev)
|
||||
static const struct header_ops dvb_header_ops = {
|
||||
.create = eth_header,
|
||||
.parse = eth_header_parse,
|
||||
.rebuild = eth_rebuild_header,
|
||||
};
|
||||
|
||||
|
||||
|
@ -104,7 +104,6 @@ EXPORT_SYMBOL(arcnet_timeout);
|
||||
static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, const void *daddr,
|
||||
const void *saddr, unsigned len);
|
||||
static int arcnet_rebuild_header(struct sk_buff *skb);
|
||||
static int go_tx(struct net_device *dev);
|
||||
|
||||
static int debug = ARCNET_DEBUG;
|
||||
@ -312,7 +311,6 @@ static int choose_mtu(void)
|
||||
|
||||
static const struct header_ops arcnet_header_ops = {
|
||||
.create = arcnet_header,
|
||||
.rebuild = arcnet_rebuild_header,
|
||||
};
|
||||
|
||||
static const struct net_device_ops arcnet_netdev_ops = {
|
||||
@ -538,59 +536,6 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
|
||||
return proto->build_header(skb, dev, type, _daddr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Rebuild the ARCnet hard header. This is called after an ARP (or in the
|
||||
* future other address resolution) has completed on this sk_buff. We now
|
||||
* let ARP fill in the destination field.
|
||||
*/
|
||||
static int arcnet_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
struct arcnet_local *lp = netdev_priv(dev);
|
||||
int status = 0; /* default is failure */
|
||||
unsigned short type;
|
||||
uint8_t daddr=0;
|
||||
struct ArcProto *proto;
|
||||
/*
|
||||
* XXX: Why not use skb->mac_len?
|
||||
*/
|
||||
if (skb->network_header - skb->mac_header != 2) {
|
||||
BUGMSG(D_NORMAL,
|
||||
"rebuild_header: shouldn't be here! (hdrsize=%d)\n",
|
||||
(int)(skb->network_header - skb->mac_header));
|
||||
return 0;
|
||||
}
|
||||
type = *(uint16_t *) skb_pull(skb, 2);
|
||||
BUGMSG(D_DURING, "rebuild header for protocol %Xh\n", type);
|
||||
|
||||
if (type == ETH_P_IP) {
|
||||
#ifdef CONFIG_INET
|
||||
BUGMSG(D_DURING, "rebuild header for ethernet protocol %Xh\n", type);
|
||||
status = arp_find(&daddr, skb) ? 1 : 0;
|
||||
BUGMSG(D_DURING, " rebuilt: dest is %d; protocol %Xh\n",
|
||||
daddr, type);
|
||||
#endif
|
||||
} else {
|
||||
BUGMSG(D_NORMAL,
|
||||
"I don't understand ethernet protocol %Xh addresses!\n", type);
|
||||
dev->stats.tx_errors++;
|
||||
dev->stats.tx_aborted_errors++;
|
||||
}
|
||||
|
||||
/* if we couldn't resolve the address... give up. */
|
||||
if (!status)
|
||||
return 0;
|
||||
|
||||
/* add the _real_ header this time! */
|
||||
proto = arc_proto_map[lp->default_proto[daddr]];
|
||||
proto->build_header(skb, dev, type, daddr);
|
||||
|
||||
return 1; /* success */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Called by the kernel in order to transmit a packet. */
|
||||
netdev_tx_t arcnet_send_packet(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
|
@ -284,18 +284,6 @@ static int sp_close(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the frame type ID */
|
||||
static int sp_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, const void *daddr,
|
||||
const void *saddr, unsigned len)
|
||||
{
|
||||
#ifdef CONFIG_INET
|
||||
if (type != ETH_P_AX25)
|
||||
return ax25_hard_header(skb, dev, type, daddr, saddr, len);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp_set_mac_address(struct net_device *dev, void *addr)
|
||||
{
|
||||
struct sockaddr_ax25 *sa = addr;
|
||||
@ -309,25 +297,12 @@ static int sp_set_mac_address(struct net_device *dev, void *addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sp_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
#ifdef CONFIG_INET
|
||||
return ax25_rebuild_header(skb);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct header_ops sp_header_ops = {
|
||||
.create = sp_header,
|
||||
.rebuild = sp_rebuild_header,
|
||||
};
|
||||
|
||||
static const struct net_device_ops sp_netdev_ops = {
|
||||
.ndo_open = sp_open_dev,
|
||||
.ndo_stop = sp_close,
|
||||
.ndo_start_xmit = sp_xmit,
|
||||
.ndo_set_mac_address = sp_set_mac_address,
|
||||
.ndo_neigh_construct = ax25_neigh_construct,
|
||||
};
|
||||
|
||||
static void sp_setup(struct net_device *dev)
|
||||
@ -337,10 +312,11 @@ static void sp_setup(struct net_device *dev)
|
||||
dev->destructor = free_netdev;
|
||||
dev->mtu = SIXP_MTU;
|
||||
dev->hard_header_len = AX25_MAX_HEADER_LEN;
|
||||
dev->header_ops = &sp_header_ops;
|
||||
dev->header_ops = &ax25_header_ops;
|
||||
|
||||
dev->addr_len = AX25_ADDR_LEN;
|
||||
dev->type = ARPHRD_AX25;
|
||||
dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
|
||||
dev->tx_queue_len = 10;
|
||||
|
||||
/* Only activated in AX.25 mode */
|
||||
|
@ -1109,6 +1109,7 @@ static const struct net_device_ops baycom_netdev_ops = {
|
||||
.ndo_do_ioctl = baycom_ioctl,
|
||||
.ndo_start_xmit = baycom_send_packet,
|
||||
.ndo_set_mac_address = baycom_set_mac_address,
|
||||
.ndo_neigh_construct = ax25_neigh_construct,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1146,6 +1147,7 @@ static void baycom_probe(struct net_device *dev)
|
||||
dev->header_ops = &ax25_header_ops;
|
||||
|
||||
dev->type = ARPHRD_AX25; /* AF_AX25 device */
|
||||
dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
|
||||
dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
|
||||
dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */
|
||||
dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */
|
||||
|
@ -469,6 +469,7 @@ static const struct net_device_ops bpq_netdev_ops = {
|
||||
.ndo_start_xmit = bpq_xmit,
|
||||
.ndo_set_mac_address = bpq_set_mac_address,
|
||||
.ndo_do_ioctl = bpq_ioctl,
|
||||
.ndo_neigh_construct = ax25_neigh_construct,
|
||||
};
|
||||
|
||||
static void bpq_setup(struct net_device *dev)
|
||||
@ -486,6 +487,7 @@ static void bpq_setup(struct net_device *dev)
|
||||
#endif
|
||||
|
||||
dev->type = ARPHRD_AX25;
|
||||
dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
|
||||
dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
|
||||
dev->mtu = AX25_DEF_PACLEN;
|
||||
dev->addr_len = AX25_ADDR_LEN;
|
||||
|
@ -433,6 +433,7 @@ module_exit(dmascc_exit);
|
||||
static void __init dev_setup(struct net_device *dev)
|
||||
{
|
||||
dev->type = ARPHRD_AX25;
|
||||
dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
|
||||
dev->hard_header_len = AX25_MAX_HEADER_LEN;
|
||||
dev->mtu = 1500;
|
||||
dev->addr_len = AX25_ADDR_LEN;
|
||||
@ -447,6 +448,7 @@ static const struct net_device_ops scc_netdev_ops = {
|
||||
.ndo_start_xmit = scc_send_packet,
|
||||
.ndo_do_ioctl = scc_ioctl,
|
||||
.ndo_set_mac_address = scc_set_mac_address,
|
||||
.ndo_neigh_construct = ax25_neigh_construct,
|
||||
};
|
||||
|
||||
static int __init setup_adapter(int card_base, int type, int n)
|
||||
|
@ -626,6 +626,7 @@ static const struct net_device_ops hdlcdrv_netdev = {
|
||||
.ndo_start_xmit = hdlcdrv_send_packet,
|
||||
.ndo_do_ioctl = hdlcdrv_ioctl,
|
||||
.ndo_set_mac_address = hdlcdrv_set_mac_address,
|
||||
.ndo_neigh_construct = ax25_neigh_construct,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -676,6 +677,7 @@ static void hdlcdrv_setup(struct net_device *dev)
|
||||
dev->header_ops = &ax25_header_ops;
|
||||
|
||||
dev->type = ARPHRD_AX25; /* AF_AX25 device */
|
||||
dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
|
||||
dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
|
||||
dev->mtu = AX25_DEF_PACLEN; /* eth_mtu is the default */
|
||||
dev->addr_len = AX25_ADDR_LEN; /* sizeof an ax.25 address */
|
||||
|
@ -573,32 +573,6 @@ static int ax_open_dev(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
|
||||
|
||||
/* Return the frame type ID */
|
||||
static int ax_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, const void *daddr,
|
||||
const void *saddr, unsigned len)
|
||||
{
|
||||
#ifdef CONFIG_INET
|
||||
if (type != ETH_P_AX25)
|
||||
return ax25_hard_header(skb, dev, type, daddr, saddr, len);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ax_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
#ifdef CONFIG_INET
|
||||
return ax25_rebuild_header(skb);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CONFIG_{AX25,AX25_MODULE} */
|
||||
|
||||
/* Open the low-level part of the AX25 channel. Easy! */
|
||||
static int ax_open(struct net_device *dev)
|
||||
{
|
||||
@ -662,16 +636,12 @@ static int ax_close(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct header_ops ax_header_ops = {
|
||||
.create = ax_header,
|
||||
.rebuild = ax_rebuild_header,
|
||||
};
|
||||
|
||||
static const struct net_device_ops ax_netdev_ops = {
|
||||
.ndo_open = ax_open_dev,
|
||||
.ndo_stop = ax_close,
|
||||
.ndo_start_xmit = ax_xmit,
|
||||
.ndo_set_mac_address = ax_set_mac_address,
|
||||
.ndo_neigh_construct = ax25_neigh_construct,
|
||||
};
|
||||
|
||||
static void ax_setup(struct net_device *dev)
|
||||
@ -681,8 +651,9 @@ static void ax_setup(struct net_device *dev)
|
||||
dev->hard_header_len = 0;
|
||||
dev->addr_len = 0;
|
||||
dev->type = ARPHRD_AX25;
|
||||
dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
|
||||
dev->tx_queue_len = 10;
|
||||
dev->header_ops = &ax_header_ops;
|
||||
dev->header_ops = &ax25_header_ops;
|
||||
dev->netdev_ops = &ax_netdev_ops;
|
||||
|
||||
|
||||
|
@ -1550,6 +1550,7 @@ static const struct net_device_ops scc_netdev_ops = {
|
||||
.ndo_set_mac_address = scc_net_set_mac_address,
|
||||
.ndo_get_stats = scc_net_get_stats,
|
||||
.ndo_do_ioctl = scc_net_ioctl,
|
||||
.ndo_neigh_construct = ax25_neigh_construct,
|
||||
};
|
||||
|
||||
/* ----> Initialize device <----- */
|
||||
@ -1567,6 +1568,7 @@ static void scc_net_setup(struct net_device *dev)
|
||||
dev->flags = 0;
|
||||
|
||||
dev->type = ARPHRD_AX25;
|
||||
dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
|
||||
dev->hard_header_len = AX25_MAX_HEADER_LEN + AX25_BPQ_HEADER_LEN;
|
||||
dev->mtu = AX25_DEF_PACLEN;
|
||||
dev->addr_len = AX25_ADDR_LEN;
|
||||
|
@ -1100,6 +1100,7 @@ static const struct net_device_ops yam_netdev_ops = {
|
||||
.ndo_start_xmit = yam_send_packet,
|
||||
.ndo_do_ioctl = yam_ioctl,
|
||||
.ndo_set_mac_address = yam_set_mac_address,
|
||||
.ndo_neigh_construct = ax25_neigh_construct,
|
||||
};
|
||||
|
||||
static void yam_setup(struct net_device *dev)
|
||||
@ -1128,6 +1129,7 @@ static void yam_setup(struct net_device *dev)
|
||||
dev->header_ops = &ax25_header_ops;
|
||||
|
||||
dev->type = ARPHRD_AX25;
|
||||
dev->neigh_priv_len = sizeof(struct ax25_neigh_priv);
|
||||
dev->hard_header_len = AX25_MAX_HEADER_LEN;
|
||||
dev->mtu = AX25_MTU;
|
||||
dev->addr_len = AX25_ADDR_LEN;
|
||||
|
@ -336,7 +336,6 @@ static int ipvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
static const struct header_ops ipvlan_header_ops = {
|
||||
.create = ipvlan_hard_header,
|
||||
.rebuild = eth_rebuild_header,
|
||||
.parse = eth_header_parse,
|
||||
.cache = eth_header_cache,
|
||||
.cache_update = eth_header_cache_update,
|
||||
|
@ -550,7 +550,6 @@ static int macvlan_hard_header(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
static const struct header_ops macvlan_hard_header_ops = {
|
||||
.create = macvlan_hard_header,
|
||||
.rebuild = eth_rebuild_header,
|
||||
.parse = eth_header_parse,
|
||||
.cache = eth_header_cache,
|
||||
.cache_update = eth_header_cache_update,
|
||||
|
@ -798,7 +798,6 @@ static void prism2_tx_timeout(struct net_device *dev)
|
||||
|
||||
const struct header_ops hostap_80211_ops = {
|
||||
.create = eth_header,
|
||||
.rebuild = eth_rebuild_header,
|
||||
.cache = eth_header_cache,
|
||||
.cache_update = eth_header_cache_update,
|
||||
.parse = hostap_80211_header_parse,
|
||||
|
@ -35,7 +35,6 @@ extern const struct header_ops eth_header_ops;
|
||||
|
||||
int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
|
||||
const void *daddr, const void *saddr, unsigned len);
|
||||
int eth_rebuild_header(struct sk_buff *skb);
|
||||
int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr);
|
||||
int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
|
||||
__be16 type);
|
||||
|
@ -261,7 +261,6 @@ struct header_ops {
|
||||
unsigned short type, const void *daddr,
|
||||
const void *saddr, unsigned int len);
|
||||
int (*parse)(const struct sk_buff *skb, unsigned char *haddr);
|
||||
int (*rebuild)(struct sk_buff *skb);
|
||||
int (*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type);
|
||||
void (*cache_update)(struct hh_cache *hh,
|
||||
const struct net_device *dev,
|
||||
@ -1346,7 +1345,7 @@ enum netdev_priv_flags {
|
||||
* if one wants to override the ndo_*() functions
|
||||
* @ethtool_ops: Management operations
|
||||
* @fwd_ops: Management operations
|
||||
* @header_ops: Includes callbacks for creating,parsing,rebuilding,etc
|
||||
* @header_ops: Includes callbacks for creating,parsing,caching,etc
|
||||
* of Layer 2 headers.
|
||||
*
|
||||
* @flags: Interface flags (a la BSD)
|
||||
@ -2399,15 +2398,6 @@ static inline int dev_parse_header(const struct sk_buff *skb,
|
||||
return dev->header_ops->parse(skb, haddr);
|
||||
}
|
||||
|
||||
static inline int dev_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
const struct net_device *dev = skb->dev;
|
||||
|
||||
if (!dev->header_ops || !dev->header_ops->rebuild)
|
||||
return 0;
|
||||
return dev->header_ops->rebuild(skb);
|
||||
}
|
||||
|
||||
typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len);
|
||||
int register_gifconf(unsigned int family, gifconf_func_t *gifconf);
|
||||
static inline int unregister_gifconf(unsigned int family)
|
||||
|
@ -47,7 +47,6 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32
|
||||
}
|
||||
|
||||
void arp_init(void);
|
||||
int arp_find(unsigned char *haddr, struct sk_buff *skb);
|
||||
int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg);
|
||||
void arp_send(int type, int ptype, __be32 dest_ip,
|
||||
struct net_device *dev, __be32 src_ip,
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <net/neighbour.h>
|
||||
|
||||
#define AX25_T1CLAMPLO 1
|
||||
#define AX25_T1CLAMPHI (30 * HZ)
|
||||
@ -366,10 +367,11 @@ int ax25_kiss_rcv(struct sk_buff *, struct net_device *, struct packet_type *,
|
||||
struct net_device *);
|
||||
|
||||
/* ax25_ip.c */
|
||||
int ax25_hard_header(struct sk_buff *, struct net_device *, unsigned short,
|
||||
const void *, const void *, unsigned int);
|
||||
int ax25_rebuild_header(struct sk_buff *);
|
||||
int ax25_neigh_construct(struct neighbour *neigh);
|
||||
extern const struct header_ops ax25_header_ops;
|
||||
struct ax25_neigh_priv {
|
||||
struct neigh_ops ops;
|
||||
};
|
||||
|
||||
/* ax25_out.c */
|
||||
ax25_cb *ax25_send_frame(struct sk_buff *, int, ax25_address *, ax25_address *,
|
||||
|
@ -193,6 +193,7 @@ struct neigh_table {
|
||||
int family;
|
||||
int entry_size;
|
||||
int key_len;
|
||||
__be16 protocol;
|
||||
__u32 (*hash)(const void *pkey,
|
||||
const struct net_device *dev,
|
||||
__u32 *hash_rnd);
|
||||
@ -268,7 +269,6 @@ void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
|
||||
int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
|
||||
int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb);
|
||||
int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb);
|
||||
int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb);
|
||||
int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb);
|
||||
struct neighbour *neigh_event_ns(struct neigh_table *tbl,
|
||||
u8 *lladdr, void *saddr,
|
||||
|
21
net/802/fc.c
21
net/802/fc.c
@ -75,29 +75,8 @@ static int fc_header(struct sk_buff *skb, struct net_device *dev,
|
||||
return -hdr_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* A neighbour discovery of some species (eg arp) has completed. We
|
||||
* can now send the packet.
|
||||
*/
|
||||
|
||||
static int fc_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
#ifdef CONFIG_INET
|
||||
struct fch_hdr *fch=(struct fch_hdr *)skb->data;
|
||||
struct fcllc *fcllc=(struct fcllc *)(skb->data+sizeof(struct fch_hdr));
|
||||
if(fcllc->ethertype != htons(ETH_P_IP)) {
|
||||
printk("fc_rebuild_header: Don't know how to resolve type %04X addresses ?\n", ntohs(fcllc->ethertype));
|
||||
return 0;
|
||||
}
|
||||
return arp_find(fch->daddr, skb);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct header_ops fc_header_ops = {
|
||||
.create = fc_header,
|
||||
.rebuild = fc_rebuild_header,
|
||||
};
|
||||
|
||||
static void fc_setup(struct net_device *dev)
|
||||
|
@ -87,31 +87,6 @@ static int fddi_header(struct sk_buff *skb, struct net_device *dev,
|
||||
return -hl;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Rebuild the FDDI MAC header. This is called after an ARP
|
||||
* (or in future other address resolution) has completed on
|
||||
* this sk_buff. We now let ARP fill in the other fields.
|
||||
*/
|
||||
|
||||
static int fddi_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
struct fddihdr *fddi = (struct fddihdr *)skb->data;
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
if (fddi->hdr.llc_snap.ethertype == htons(ETH_P_IP))
|
||||
/* Try to get ARP to resolve the header and fill destination address */
|
||||
return arp_find(fddi->daddr, skb);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
printk("%s: Don't know how to resolve type %04X addresses.\n",
|
||||
skb->dev->name, ntohs(fddi->hdr.llc_snap.ethertype));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determine the packet's protocol ID and fill in skb fields.
|
||||
* This routine is called before an incoming packet is passed
|
||||
@ -177,7 +152,6 @@ EXPORT_SYMBOL(fddi_change_mtu);
|
||||
|
||||
static const struct header_ops fddi_header_ops = {
|
||||
.create = fddi_header,
|
||||
.rebuild = fddi_rebuild_header,
|
||||
};
|
||||
|
||||
|
||||
|
@ -90,33 +90,6 @@ static int hippi_header(struct sk_buff *skb, struct net_device *dev,
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Rebuild the HIPPI MAC header. This is called after an ARP has
|
||||
* completed on this sk_buff. We now let ARP fill in the other fields.
|
||||
*/
|
||||
|
||||
static int hippi_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
struct hippi_hdr *hip = (struct hippi_hdr *)skb->data;
|
||||
|
||||
/*
|
||||
* Only IP is currently supported
|
||||
*/
|
||||
|
||||
if(hip->snap.ethertype != htons(ETH_P_IP))
|
||||
{
|
||||
printk(KERN_DEBUG "%s: unable to resolve type %X addresses.\n",skb->dev->name,ntohs(hip->snap.ethertype));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't support dynamic ARP on HIPPI, but we use the ARP
|
||||
* static ARP tables to hold the I-FIELDs.
|
||||
*/
|
||||
return arp_find(hip->le.daddr, skb);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determine the packet's protocol ID.
|
||||
*/
|
||||
@ -186,7 +159,6 @@ EXPORT_SYMBOL(hippi_neigh_setup_dev);
|
||||
|
||||
static const struct header_ops hippi_header_ops = {
|
||||
.create = hippi_header,
|
||||
.rebuild = hippi_rebuild_header,
|
||||
};
|
||||
|
||||
|
||||
|
@ -36,39 +36,6 @@
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/netpoll.h>
|
||||
|
||||
/*
|
||||
* Rebuild the Ethernet MAC header. This is called after an ARP
|
||||
* (or in future other address resolution) has completed on this
|
||||
* sk_buff. We now let ARP fill in the other fields.
|
||||
*
|
||||
* This routine CANNOT use cached dst->neigh!
|
||||
* Really, it is used only when dst->neigh is wrong.
|
||||
*
|
||||
* TODO: This needs a checkup, I'm ignorant here. --BLG
|
||||
*/
|
||||
static int vlan_dev_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data);
|
||||
|
||||
switch (veth->h_vlan_encapsulated_proto) {
|
||||
#ifdef CONFIG_INET
|
||||
case htons(ETH_P_IP):
|
||||
|
||||
/* TODO: Confirm this will work with VLAN headers... */
|
||||
return arp_find(veth->h_dest, skb);
|
||||
#endif
|
||||
default:
|
||||
pr_debug("%s: unable to resolve type %X addresses\n",
|
||||
dev->name, ntohs(veth->h_vlan_encapsulated_proto));
|
||||
|
||||
ether_addr_copy(veth->h_source, dev->dev_addr);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the VLAN header for an arbitrary protocol layer
|
||||
*
|
||||
@ -534,7 +501,6 @@ static int vlan_dev_get_lock_subclass(struct net_device *dev)
|
||||
|
||||
static const struct header_ops vlan_header_ops = {
|
||||
.create = vlan_dev_hard_header,
|
||||
.rebuild = vlan_dev_rebuild_header,
|
||||
.parse = eth_header_parse,
|
||||
};
|
||||
|
||||
@ -554,7 +520,6 @@ static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev
|
||||
|
||||
static const struct header_ops vlan_passthru_header_ops = {
|
||||
.create = vlan_passthru_hard_header,
|
||||
.rebuild = dev_rebuild_header,
|
||||
.parse = eth_header_parse,
|
||||
};
|
||||
|
||||
|
@ -46,9 +46,9 @@
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
|
||||
int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, const void *daddr,
|
||||
const void *saddr, unsigned int len)
|
||||
static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, const void *daddr,
|
||||
const void *saddr, unsigned int len)
|
||||
{
|
||||
unsigned char *buff;
|
||||
|
||||
@ -100,7 +100,7 @@ int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
|
||||
return -AX25_HEADER_LEN; /* Unfinished header */
|
||||
}
|
||||
|
||||
int ax25_rebuild_header(struct sk_buff *skb)
|
||||
static int ax25_neigh_xmit(struct sk_buff *skb)
|
||||
{
|
||||
struct sk_buff *ourskb;
|
||||
unsigned char *bp = skb->data;
|
||||
@ -115,9 +115,6 @@ int ax25_rebuild_header(struct sk_buff *skb)
|
||||
dst = (ax25_address *)(bp + 1);
|
||||
src = (ax25_address *)(bp + 8);
|
||||
|
||||
if (arp_find(bp + 1, skb))
|
||||
return 1;
|
||||
|
||||
route = ax25_get_route(dst, NULL);
|
||||
if (route) {
|
||||
digipeat = route->digipeat;
|
||||
@ -129,6 +126,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
|
||||
dev = skb->dev;
|
||||
|
||||
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
|
||||
kfree_skb(skb);
|
||||
goto put;
|
||||
}
|
||||
|
||||
@ -215,28 +213,74 @@ put:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ax25_neigh_output(struct neighbour *neigh, struct sk_buff *skb)
|
||||
{
|
||||
/* Except for calling ax25_neigh_xmit instead of
|
||||
* dev_queue_xmit this is neigh_resolve_output.
|
||||
*/
|
||||
int rc = 0;
|
||||
|
||||
if (!neigh_event_send(neigh, skb)) {
|
||||
int err;
|
||||
struct net_device *dev = neigh->dev;
|
||||
unsigned int seq;
|
||||
|
||||
do {
|
||||
__skb_pull(skb, skb_network_offset(skb));
|
||||
seq = read_seqbegin(&neigh->ha_lock);
|
||||
err = dev_hard_header(skb, dev, ntohs(skb->protocol),
|
||||
neigh->ha, NULL, skb->len);
|
||||
} while (read_seqretry(&neigh->ha_lock, seq));
|
||||
|
||||
if (err >= 0) {
|
||||
ax25_neigh_xmit(skb);
|
||||
} else
|
||||
goto out_kfree_skb;
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
|
||||
out_kfree_skb:
|
||||
rc = -EINVAL;
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
int ax25_neigh_construct(struct neighbour *neigh)
|
||||
{
|
||||
/* This trouble could be saved if ax25 would right a proper
|
||||
* dev_queue_xmit function.
|
||||
*/
|
||||
struct ax25_neigh_priv *priv = neighbour_priv(neigh);
|
||||
|
||||
if (neigh->tbl->family != AF_INET)
|
||||
return -EINVAL;
|
||||
|
||||
priv->ops = *neigh->ops;
|
||||
priv->ops.output = ax25_neigh_output;
|
||||
priv->ops.connected_output = ax25_neigh_output;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* INET */
|
||||
|
||||
int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, const void *daddr,
|
||||
const void *saddr, unsigned int len)
|
||||
static int ax25_hard_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, const void *daddr,
|
||||
const void *saddr, unsigned int len)
|
||||
{
|
||||
return -AX25_HEADER_LEN;
|
||||
}
|
||||
|
||||
int ax25_rebuild_header(struct sk_buff *skb)
|
||||
int ax25_neigh_construct(struct neighbour *neigh)
|
||||
{
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const struct header_ops ax25_header_ops = {
|
||||
.create = ax25_hard_header,
|
||||
.rebuild = ax25_rebuild_header,
|
||||
};
|
||||
|
||||
EXPORT_SYMBOL(ax25_hard_header);
|
||||
EXPORT_SYMBOL(ax25_rebuild_header);
|
||||
EXPORT_SYMBOL(ax25_header_ops);
|
||||
EXPORT_SYMBOL(ax25_neigh_construct);
|
||||
|
||||
|
@ -1263,10 +1263,10 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
|
||||
EXPORT_SYMBOL(neigh_event_ns);
|
||||
|
||||
/* called with read_lock_bh(&n->lock); */
|
||||
static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
|
||||
static void neigh_hh_init(struct neighbour *n)
|
||||
{
|
||||
struct net_device *dev = dst->dev;
|
||||
__be16 prot = dst->ops->protocol;
|
||||
struct net_device *dev = n->dev;
|
||||
__be16 prot = n->tbl->protocol;
|
||||
struct hh_cache *hh = &n->hh;
|
||||
|
||||
write_lock_bh(&n->lock);
|
||||
@ -1280,43 +1280,19 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
|
||||
write_unlock_bh(&n->lock);
|
||||
}
|
||||
|
||||
/* This function can be used in contexts, where only old dev_queue_xmit
|
||||
* worked, f.e. if you want to override normal output path (eql, shaper),
|
||||
* but resolution is not made yet.
|
||||
*/
|
||||
|
||||
int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
|
||||
__skb_pull(skb, skb_network_offset(skb));
|
||||
|
||||
if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
|
||||
skb->len) < 0 &&
|
||||
dev_rebuild_header(skb))
|
||||
return 0;
|
||||
|
||||
return dev_queue_xmit(skb);
|
||||
}
|
||||
EXPORT_SYMBOL(neigh_compat_output);
|
||||
|
||||
/* Slow and careful. */
|
||||
|
||||
int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
|
||||
{
|
||||
struct dst_entry *dst = skb_dst(skb);
|
||||
int rc = 0;
|
||||
|
||||
if (!dst)
|
||||
goto discard;
|
||||
|
||||
if (!neigh_event_send(neigh, skb)) {
|
||||
int err;
|
||||
struct net_device *dev = neigh->dev;
|
||||
unsigned int seq;
|
||||
|
||||
if (dev->header_ops->cache && !neigh->hh.hh_len)
|
||||
neigh_hh_init(neigh, dst);
|
||||
neigh_hh_init(neigh);
|
||||
|
||||
do {
|
||||
__skb_pull(skb, skb_network_offset(skb));
|
||||
@ -1332,8 +1308,6 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
discard:
|
||||
neigh_dbg(1, "%s: dst=%p neigh=%p\n", __func__, dst, neigh);
|
||||
out_kfree_skb:
|
||||
rc = -EINVAL;
|
||||
kfree_skb(skb);
|
||||
|
@ -97,6 +97,7 @@ struct neigh_table dn_neigh_table = {
|
||||
.family = PF_DECnet,
|
||||
.entry_size = NEIGH_ENTRY_SIZE(sizeof(struct dn_neigh)),
|
||||
.key_len = sizeof(__le16),
|
||||
.protocol = cpu_to_be16(ETH_P_DNA_RT),
|
||||
.hash = dn_neigh_hash,
|
||||
.constructor = dn_neigh_construct,
|
||||
.id = "dn_neigh_cache",
|
||||
|
@ -112,39 +112,6 @@ int eth_header(struct sk_buff *skb, struct net_device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL(eth_header);
|
||||
|
||||
/**
|
||||
* eth_rebuild_header- rebuild the Ethernet MAC header.
|
||||
* @skb: socket buffer to update
|
||||
*
|
||||
* This is called after an ARP or IPV6 ndisc it's resolution on this
|
||||
* sk_buff. We now let protocol (ARP) fill in the other fields.
|
||||
*
|
||||
* This routine CANNOT use cached dst->neigh!
|
||||
* Really, it is used only when dst->neigh is wrong.
|
||||
*/
|
||||
int eth_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
struct ethhdr *eth = (struct ethhdr *)skb->data;
|
||||
struct net_device *dev = skb->dev;
|
||||
|
||||
switch (eth->h_proto) {
|
||||
#ifdef CONFIG_INET
|
||||
case htons(ETH_P_IP):
|
||||
return arp_find(eth->h_dest, skb);
|
||||
#endif
|
||||
default:
|
||||
netdev_dbg(dev,
|
||||
"%s: unable to resolve type %X addresses.\n",
|
||||
dev->name, ntohs(eth->h_proto));
|
||||
|
||||
memcpy(eth->h_source, dev->dev_addr, ETH_ALEN);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(eth_rebuild_header);
|
||||
|
||||
/**
|
||||
* eth_get_headlen - determine the the length of header for an ethernet frame
|
||||
* @data: pointer to start of frame
|
||||
@ -369,7 +336,6 @@ EXPORT_SYMBOL(eth_validate_addr);
|
||||
const struct header_ops eth_header_ops ____cacheline_aligned = {
|
||||
.create = eth_header,
|
||||
.parse = eth_header_parse,
|
||||
.rebuild = eth_rebuild_header,
|
||||
.cache = eth_header_cache,
|
||||
.cache_update = eth_header_cache_update,
|
||||
};
|
||||
|
103
net/ipv4/arp.c
103
net/ipv4/arp.c
@ -149,17 +149,10 @@ static const struct neigh_ops arp_direct_ops = {
|
||||
.connected_output = neigh_direct_output,
|
||||
};
|
||||
|
||||
static const struct neigh_ops arp_broken_ops = {
|
||||
.family = AF_INET,
|
||||
.solicit = arp_solicit,
|
||||
.error_report = arp_error_report,
|
||||
.output = neigh_compat_output,
|
||||
.connected_output = neigh_compat_output,
|
||||
};
|
||||
|
||||
struct neigh_table arp_tbl = {
|
||||
.family = AF_INET,
|
||||
.key_len = 4,
|
||||
.protocol = cpu_to_be16(ETH_P_IP),
|
||||
.hash = arp_hash,
|
||||
.constructor = arp_constructor,
|
||||
.proxy_redo = parp_redo,
|
||||
@ -260,35 +253,6 @@ static int arp_constructor(struct neighbour *neigh)
|
||||
in old paradigm.
|
||||
*/
|
||||
|
||||
#if 1
|
||||
/* So... these "amateur" devices are hopeless.
|
||||
The only thing, that I can say now:
|
||||
It is very sad that we need to keep ugly obsolete
|
||||
code to make them happy.
|
||||
|
||||
They should be moved to more reasonable state, now
|
||||
they use rebuild_header INSTEAD OF hard_start_xmit!!!
|
||||
Besides that, they are sort of out of date
|
||||
(a lot of redundant clones/copies, useless in 2.1),
|
||||
I wonder why people believe that they work.
|
||||
*/
|
||||
switch (dev->type) {
|
||||
default:
|
||||
break;
|
||||
case ARPHRD_ROSE:
|
||||
#if IS_ENABLED(CONFIG_AX25)
|
||||
case ARPHRD_AX25:
|
||||
#if IS_ENABLED(CONFIG_NETROM)
|
||||
case ARPHRD_NETROM:
|
||||
#endif
|
||||
neigh->ops = &arp_broken_ops;
|
||||
neigh->output = neigh->ops->output;
|
||||
return 0;
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
if (neigh->type == RTN_MULTICAST) {
|
||||
neigh->nud_state = NUD_NOARP;
|
||||
arp_mc_map(addr, neigh->ha, dev, 1);
|
||||
@ -433,71 +397,6 @@ static int arp_filter(__be32 sip, __be32 tip, struct net_device *dev)
|
||||
return flag;
|
||||
}
|
||||
|
||||
/* OBSOLETE FUNCTIONS */
|
||||
|
||||
/*
|
||||
* Find an arp mapping in the cache. If not found, post a request.
|
||||
*
|
||||
* It is very UGLY routine: it DOES NOT use skb->dst->neighbour,
|
||||
* even if it exists. It is supposed that skb->dev was mangled
|
||||
* by a virtual device (eql, shaper). Nobody but broken devices
|
||||
* is allowed to use this function, it is scheduled to be removed. --ANK
|
||||
*/
|
||||
|
||||
static int arp_set_predefined(int addr_hint, unsigned char *haddr,
|
||||
__be32 paddr, struct net_device *dev)
|
||||
{
|
||||
switch (addr_hint) {
|
||||
case RTN_LOCAL:
|
||||
pr_debug("arp called for own IP address\n");
|
||||
memcpy(haddr, dev->dev_addr, dev->addr_len);
|
||||
return 1;
|
||||
case RTN_MULTICAST:
|
||||
arp_mc_map(paddr, haddr, dev, 1);
|
||||
return 1;
|
||||
case RTN_BROADCAST:
|
||||
memcpy(haddr, dev->broadcast, dev->addr_len);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int arp_find(unsigned char *haddr, struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
__be32 paddr;
|
||||
struct neighbour *n;
|
||||
|
||||
if (!skb_dst(skb)) {
|
||||
pr_debug("arp_find is called with dst==NULL\n");
|
||||
kfree_skb(skb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
paddr = rt_nexthop(skb_rtable(skb), ip_hdr(skb)->daddr);
|
||||
if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr,
|
||||
paddr, dev))
|
||||
return 0;
|
||||
|
||||
n = __neigh_lookup(&arp_tbl, &paddr, dev, 1);
|
||||
|
||||
if (n) {
|
||||
n->used = jiffies;
|
||||
if (n->nud_state & NUD_VALID || neigh_event_send(n, skb) == 0) {
|
||||
neigh_ha_snapshot(haddr, n, dev);
|
||||
neigh_release(n);
|
||||
return 0;
|
||||
}
|
||||
neigh_release(n);
|
||||
} else
|
||||
kfree_skb(skb);
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(arp_find);
|
||||
|
||||
/* END OF OBSOLETE FUNCTIONS */
|
||||
|
||||
/*
|
||||
* Check if we can use proxy ARP for this path
|
||||
*/
|
||||
|
@ -117,6 +117,7 @@ static const struct neigh_ops ndisc_direct_ops = {
|
||||
struct neigh_table nd_tbl = {
|
||||
.family = AF_INET6,
|
||||
.key_len = sizeof(struct in6_addr),
|
||||
.protocol = cpu_to_be16(ETH_P_IPV6),
|
||||
.hash = ndisc_hash,
|
||||
.constructor = ndisc_constructor,
|
||||
.pconstructor = pndisc_constructor,
|
||||
|
@ -65,36 +65,6 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
|
||||
static int nr_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
unsigned char *bp = skb->data;
|
||||
|
||||
if (arp_find(bp + 7, skb))
|
||||
return 1;
|
||||
|
||||
bp[6] &= ~AX25_CBIT;
|
||||
bp[6] &= ~AX25_EBIT;
|
||||
bp[6] |= AX25_SSSID_SPARE;
|
||||
bp += AX25_ADDR_LEN;
|
||||
|
||||
bp[6] &= ~AX25_CBIT;
|
||||
bp[6] |= AX25_EBIT;
|
||||
bp[6] |= AX25_SSSID_SPARE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int nr_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int nr_header(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type,
|
||||
const void *daddr, const void *saddr, unsigned int len)
|
||||
@ -188,7 +158,6 @@ static netdev_tx_t nr_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
static const struct header_ops nr_header_ops = {
|
||||
.create = nr_header,
|
||||
.rebuild= nr_rebuild_header,
|
||||
};
|
||||
|
||||
static const struct net_device_ops nr_netdev_ops = {
|
||||
|
@ -41,6 +41,9 @@ static int rose_header(struct sk_buff *skb, struct net_device *dev,
|
||||
{
|
||||
unsigned char *buff = skb_push(skb, ROSE_MIN_LEN + 2);
|
||||
|
||||
if (daddr)
|
||||
memcpy(buff + 7, daddr, dev->addr_len);
|
||||
|
||||
*buff++ = ROSE_GFI | ROSE_Q_BIT;
|
||||
*buff++ = 0x00;
|
||||
*buff++ = ROSE_DATA;
|
||||
@ -53,43 +56,6 @@ static int rose_header(struct sk_buff *skb, struct net_device *dev,
|
||||
return -37;
|
||||
}
|
||||
|
||||
static int rose_rebuild_header(struct sk_buff *skb)
|
||||
{
|
||||
#ifdef CONFIG_INET
|
||||
struct net_device *dev = skb->dev;
|
||||
struct net_device_stats *stats = &dev->stats;
|
||||
unsigned char *bp = (unsigned char *)skb->data;
|
||||
struct sk_buff *skbn;
|
||||
unsigned int len;
|
||||
|
||||
if (arp_find(bp + 7, skb)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
|
||||
kfree_skb(skb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (skb->sk != NULL)
|
||||
skb_set_owner_w(skbn, skb->sk);
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
len = skbn->len;
|
||||
|
||||
if (!rose_route_frame(skbn, NULL)) {
|
||||
kfree_skb(skbn);
|
||||
stats->tx_errors++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
stats->tx_packets++;
|
||||
stats->tx_bytes += len;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rose_set_mac_address(struct net_device *dev, void *addr)
|
||||
{
|
||||
struct sockaddr *sa = addr;
|
||||
@ -134,19 +100,26 @@ static int rose_close(struct net_device *dev)
|
||||
static netdev_tx_t rose_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct net_device_stats *stats = &dev->stats;
|
||||
unsigned int len = skb->len;
|
||||
|
||||
if (!netif_running(dev)) {
|
||||
printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n");
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
dev_kfree_skb(skb);
|
||||
stats->tx_errors++;
|
||||
|
||||
if (!rose_route_frame(skb, NULL)) {
|
||||
dev_kfree_skb(skb);
|
||||
stats->tx_errors++;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
stats->tx_packets++;
|
||||
stats->tx_bytes += len;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static const struct header_ops rose_header_ops = {
|
||||
.create = rose_header,
|
||||
.rebuild = rose_rebuild_header,
|
||||
};
|
||||
|
||||
static const struct net_device_ops rose_netdev_ops = {
|
||||
|
Loading…
Reference in New Issue
Block a user