Commit e2aa09ad authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/net-2.6

into home.osdl.org:/home/torvalds/v2.5/linux
parents 9ca5ce6c 39c09b95
......@@ -407,7 +407,7 @@ o <http://www.iptables.org/downloads.html>
Ip-route2
---------
o <ftp://ftp.inr.ac.ru/ip-routing/iproute2-2.2.4-now-ss991023.tar.gz>
o <ftp://ftp.tux.org/pub/net/ip-routing/iproute2-2.2.4-now-ss991023.tar.gz>
OProfile
--------
......
......@@ -47,7 +47,7 @@ This allows the kernel to exchange data with userspace applications. There
are two ways of doing this, the new way works with netlink sockets and I
have no experience with that yet. ANK uses it in his excellent iproute2
package, see for example rtmon.c. iproute2 can be found on
ftp://ftp.inr.ac.ru/ip-routing/iproute2*
ftp://ftp.tux.org/pub/net/ip-routing/iproute2*
The new way is described, partly in netlink(7), available on
http://www.europe.redhat.com/documentation/man-pages/man7/netlink.7.php3
......
......@@ -430,28 +430,3 @@ static int __init net_olddevs_init(void)
}
device_initcall(net_olddevs_init);
/*
* The @dev_base list is protected by @dev_base_lock and the rtln
* semaphore.
*
* Pure readers hold dev_base_lock for reading.
*
* Writers must hold the rtnl semaphore while they loop through the
* dev_base list, and hold dev_base_lock for writing when they do the
* actual updates. This allows pure readers to access the list even
* while a writer is preparing to update it.
*
* To put it another way, dev_base_lock is held for writing only to
* protect against pure readers; the rtnl semaphore provides the
* protection against other writers.
*
* See, for example usages, register_netdevice() and
* unregister_netdevice(), which must be called with the rtnl
* semaphore held.
*/
struct net_device *dev_base;
rwlock_t dev_base_lock = RW_LOCK_UNLOCKED;
EXPORT_SYMBOL(dev_base);
EXPORT_SYMBOL(dev_base_lock);
......@@ -517,7 +517,7 @@ static int pppoe_create(struct socket *sock)
sk->sk_protocol = PX_PROTO_OE;
sk->sk_destruct = pppoe_sk_free;
po = pppox_sk(sk) = kmalloc(sizeof(*po), GFP_KERNEL);
po = sk->sk_protinfo = kmalloc(sizeof(*po), GFP_KERNEL);
if (!po)
goto frees;
memset(po, 0, sizeof(*po));
......
......@@ -200,6 +200,152 @@ static inline int vlan_hwaccel_receive_skb(struct sk_buff *skb,
{
return __vlan_hwaccel_rx(skb, grp, vlan_tag, 1);
}
/**
* __vlan_put_tag - regular VLAN tag inserting
* @skb: skbuff to tag
* @tag: VLAN tag to insert
*
* Inserts the VLAN tag into @skb as part of the payload
* Returns a VLAN tagged skb. If a new skb is created, @skb is freed.
*
* Following the skb_unshare() example, in case of error, the calling function
* doesn't have to worry about freeing the original skb.
*/
static inline struct sk_buff *__vlan_put_tag(struct sk_buff *skb, unsigned short tag)
{
struct vlan_ethhdr *veth;
if (skb_headroom(skb) < VLAN_HLEN) {
struct sk_buff *sk_tmp = skb;
skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
kfree_skb(sk_tmp);
if (!skb) {
printk(KERN_ERR "vlan: failed to realloc headroom\n");
return NULL;
}
} else {
skb = skb_unshare(skb, GFP_ATOMIC);
if (!skb) {
printk(KERN_ERR "vlan: failed to unshare skbuff\n");
return NULL;
}
}
veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
/* Move the mac addresses to the beginning of the new header. */
memmove(skb->data, skb->data + VLAN_HLEN, 2 * VLAN_ETH_ALEN);
/* first, the ethernet type */
veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
/* now, the tag */
veth->h_vlan_TCI = htons(tag);
skb->protocol = __constant_htons(ETH_P_8021Q);
skb->mac.raw -= VLAN_HLEN;
skb->nh.raw -= VLAN_HLEN;
return skb;
}
/**
* __vlan_hwaccel_put_tag - hardware accelerated VLAN inserting
* @skb: skbuff to tag
* @tag: VLAN tag to insert
*
* Puts the VLAN tag in @skb->cb[] and lets the device do the rest
*/
static inline struct sk_buff *__vlan_hwaccel_put_tag(struct sk_buff *skb, unsigned short tag)
{
struct vlan_skb_tx_cookie *cookie;
cookie = VLAN_TX_SKB_CB(skb);
cookie->magic = VLAN_TX_COOKIE_MAGIC;
cookie->vlan_tag = tag;
return skb;
}
#define HAVE_VLAN_PUT_TAG
/**
* vlan_put_tag - inserts VLAN tag according to device features
* @skb: skbuff to tag
* @tag: VLAN tag to insert
*
* Assumes skb->dev is the target that will xmit this frame.
* Returns a VLAN tagged skb.
*/
static inline struct sk_buff *vlan_put_tag(struct sk_buff *skb, unsigned short tag)
{
if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
return __vlan_hwaccel_put_tag(skb, tag);
} else {
return __vlan_put_tag(skb, tag);
}
}
/**
* __vlan_get_tag - get the VLAN ID that is part of the payload
* @skb: skbuff to query
* @tag: buffer to store vlaue
*
* Returns error if the skb is not of VLAN type
*/
static inline int __vlan_get_tag(struct sk_buff *skb, unsigned short *tag)
{
struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb->data;
if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) {
return -EINVAL;
}
*tag = ntohs(veth->h_vlan_TCI);
return 0;
}
/**
* __vlan_hwaccel_get_tag - get the VLAN ID that is in @skb->cb[]
* @skb: skbuff to query
* @tag: buffer to store vlaue
*
* Returns error if @skb->cb[] is not set correctly
*/
static inline int __vlan_hwaccel_get_tag(struct sk_buff *skb, unsigned short *tag)
{
struct vlan_skb_tx_cookie *cookie;
cookie = VLAN_TX_SKB_CB(skb);
if (cookie->magic == VLAN_TX_COOKIE_MAGIC) {
*tag = cookie->vlan_tag;
return 0;
} else {
*tag = 0;
return -EINVAL;
}
}
#define HAVE_VLAN_GET_TAG
/**
* vlan_get_tag - get the VLAN ID from the skb
* @skb: skbuff to query
* @tag: buffer to store vlaue
*
* Returns error if the skb is not VLAN tagged
*/
static inline int vlan_get_tag(struct sk_buff *skb, unsigned short *tag)
{
if (skb->dev->features & NETIF_F_HW_VLAN_TX) {
return __vlan_hwaccel_get_tag(skb, tag);
} else {
return __vlan_get_tag(skb, tag);
}
}
#endif /* __KERNEL__ */
/* VLAN IOCTLs are found in sockios.h */
......
......@@ -90,6 +90,7 @@ asmlinkage int printk(const char * fmt, ...)
unsigned long int_sqrt(unsigned long);
extern int printk_ratelimit(void);
extern int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst);
static inline void console_silent(void)
{
......
......@@ -375,6 +375,10 @@ struct net_device
atomic_t refcnt;
/* delayed register/unregister */
struct list_head todo_list;
/* device name hash chain */
struct hlist_node name_hlist;
/* device index hash chain */
struct hlist_node index_hlist;
/* register/unregister state machine */
enum { NETREG_UNINITIALIZED=0,
......
......@@ -52,6 +52,9 @@ extern int strnicmp(const char *, const char *, __kernel_size_t);
#ifndef __HAVE_ARCH_STRCHR
extern char * strchr(const char *,int);
#endif
#ifndef __HAVE_ARCH_STRNCHR
extern char * strnchr(const char *, size_t, int);
#endif
#ifndef __HAVE_ARCH_STRRCHR
extern char * strrchr(const char *,int);
#endif
......
......@@ -5,6 +5,8 @@
#include <linux/if_arp.h>
#include <net/neighbour.h>
#define HAVE_ARP_CREATE
extern struct neigh_table arp_tbl;
extern void arp_init(void);
......@@ -19,6 +21,12 @@ extern int arp_bind_neighbour(struct dst_entry *dst);
extern int arp_mc_map(u32 addr, u8 *haddr, struct net_device *dev, int dir);
extern void arp_ifdown(struct net_device *dev);
extern struct sk_buff *arp_create(int type, int ptype, u32 dest_ip,
struct net_device *dev, u32 src_ip,
unsigned char *dest_hw, unsigned char *src_hw,
unsigned char *target_hw);
extern void arp_xmit(struct sk_buff *skb);
extern struct neigh_ops arp_broken_ops;
#endif /* _ARP_H */
......@@ -784,12 +784,6 @@ void tty_write_message(struct tty_struct *tty, char *msg)
return;
}
/* minimum time in jiffies between messages */
int printk_ratelimit_jiffies = 5*HZ;
/* number of messages we send before ratelimiting */
int printk_ratelimit_burst = 10;
/*
* printk rate limiting, lifted from the networking subsystem.
*
......@@ -797,7 +791,7 @@ int printk_ratelimit_burst = 10;
* every printk_ratelimit_jiffies to make a denial-of-service
* attack impossible.
*/
int printk_ratelimit(void)
int __printk_ratelimit(int ratelimit_jiffies, int ratelimit_burst)
{
static spinlock_t ratelimit_lock = SPIN_LOCK_UNLOCKED;
static unsigned long toks = 10*5*HZ;
......@@ -809,12 +803,12 @@ int printk_ratelimit(void)
spin_lock_irqsave(&ratelimit_lock, flags);
toks += now - last_msg;
last_msg = now;
if (toks > (printk_ratelimit_burst * printk_ratelimit_jiffies))
toks = printk_ratelimit_burst * printk_ratelimit_jiffies;
if (toks >= printk_ratelimit_jiffies) {
if (toks > (ratelimit_burst * ratelimit_jiffies))
toks = ratelimit_burst * ratelimit_jiffies;
if (toks >= ratelimit_jiffies) {
int lost = missed;
missed = 0;
toks -= printk_ratelimit_jiffies;
toks -= ratelimit_jiffies;
spin_unlock_irqrestore(&ratelimit_lock, flags);
if (lost)
printk(KERN_WARNING "printk: %d messages suppressed.\n", lost);
......@@ -824,4 +818,17 @@ int printk_ratelimit(void)
spin_unlock_irqrestore(&ratelimit_lock, flags);
return 0;
}
EXPORT_SYMBOL(__printk_ratelimit);
/* minimum time in jiffies between messages */
int printk_ratelimit_jiffies = 5*HZ;
/* number of messages we send before ratelimiting */
int printk_ratelimit_burst = 10;
int printk_ratelimit(void)
{
return __printk_ratelimit(printk_ratelimit_jiffies,
printk_ratelimit_burst);
}
EXPORT_SYMBOL(printk_ratelimit);
......@@ -273,6 +273,22 @@ char * strrchr(const char * s, int c)
}
#endif
#ifndef __HAVE_ARCH_STRNCHR
/**
* strnchr - Find a character in a length limited string
* @s: The string to be searched
* @count: The number of characters to be searched
* @c: The character to search for
*/
char *strnchr(const char *s, size_t count, int c)
{
for (; count-- && *s != '\0'; ++s)
if (*s == (char) c)
return (char *) s;
return NULL;
}
#endif
#ifndef __HAVE_ARCH_STRLEN
/**
* strlen - Find the length of a string
......
......@@ -445,6 +445,7 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
*/
if (veth->h_vlan_proto != __constant_htons(ETH_P_8021Q)) {
int orig_headroom = skb_headroom(skb);
unsigned short veth_TCI;
/* This is not a VLAN frame...but we can fix that! */
......@@ -454,33 +455,7 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
printk(VLAN_DBG "%s: proto to encap: 0x%hx (hbo)\n",
__FUNCTION__, htons(veth->h_vlan_proto));
#endif
if (skb_headroom(skb) < VLAN_HLEN) {
struct sk_buff *sk_tmp = skb;
skb = skb_realloc_headroom(sk_tmp, VLAN_HLEN);
kfree_skb(sk_tmp);
if (skb == NULL) {
stats->tx_dropped++;
return 0;
}
VLAN_DEV_INFO(dev)->cnt_inc_headroom_on_tx++;
} else {
if (!(skb = skb_unshare(skb, GFP_ATOMIC))) {
printk(KERN_ERR "vlan: failed to unshare skbuff\n");
stats->tx_dropped++;
return 0;
}
}
veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN);
/* Move the mac addresses to the beginning of the new header. */
memmove(skb->data, skb->data + VLAN_HLEN, 12);
/* first, the ethernet type */
/* put_unaligned(__constant_htons(ETH_P_8021Q), &veth->h_vlan_proto); */
veth->h_vlan_proto = __constant_htons(ETH_P_8021Q);
/* Now, construct the second two bytes. This field looks something
/* Construct the second two bytes. This field looks something
* like:
* usr_priority: 3 bits (high bits)
* CFI 1 bit
......@@ -489,10 +464,16 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
veth_TCI = VLAN_DEV_INFO(dev)->vlan_id;
veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb);
veth->h_vlan_TCI = htons(veth_TCI);
}
skb = __vlan_put_tag(skb, veth_TCI);
if (!skb) {
stats->tx_dropped++;
return 0;
}
skb->dev = VLAN_DEV_INFO(dev)->real_dev;
if (orig_headroom < VLAN_HLEN) {
VLAN_DEV_INFO(dev)->cnt_inc_headroom_on_tx++;
}
}
#ifdef VLAN_DEBUG
printk(VLAN_DBG "%s: about to send skb: %p to dev: %s\n",
......@@ -506,10 +487,7 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
stats->tx_packets++; /* for statics only */
stats->tx_bytes += skb->len;
skb->protocol = __constant_htons(ETH_P_8021Q);
skb->mac.raw -= VLAN_HLEN;
skb->nh.raw -= VLAN_HLEN;
skb->dev = VLAN_DEV_INFO(dev)->real_dev;
dev_queue_xmit(skb);
return 0;
......@@ -518,17 +496,22 @@ int vlan_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_device_stats *stats = vlan_dev_get_stats(dev);
struct vlan_skb_tx_cookie *cookie;
unsigned short veth_TCI;
/* Construct the second two bytes. This field looks something
* like:
* usr_priority: 3 bits (high bits)
* CFI 1 bit
* VLAN ID 12 bits (low bits)
*/
veth_TCI = VLAN_DEV_INFO(dev)->vlan_id;
veth_TCI |= vlan_dev_get_egress_qos_mask(dev, skb);
skb = __vlan_hwaccel_put_tag(skb, veth_TCI);
stats->tx_packets++;
stats->tx_bytes += skb->len;
skb->dev = VLAN_DEV_INFO(dev)->real_dev;
cookie = VLAN_TX_SKB_CB(skb);
cookie->magic = VLAN_TX_COOKIE_MAGIC;
cookie->vlan_tag = (VLAN_DEV_INFO(dev)->vlan_id |
vlan_dev_get_egress_qos_mask(dev, skb));
dev_queue_xmit(skb);
return 0;
......
......@@ -145,7 +145,7 @@ config DECNET
To find some tools to use with the kernel layer support, please
look at Patrick Caulfield's web site:
<http://linux.dreamtime.org/decnet/>.
<http://linux-decnet.sourceforge.net/>.
More detailed documentation is available in
<file:Documentation/networking/decnet.txt>.
......@@ -436,7 +436,7 @@ config X25
(say Y to "LAPB Data Link Driver" below if you want that).
You can read more about X.25 at <http://www.sangoma.com/x25.htm> and
<http://www.cisco.com/univercd/data/doc/software/11_0/rpcg/cx25.htm>.
<http://www.cisco.com/univercd/cc/td/doc/product/software/ios11/cbook/cx25.htm>.
Information about X.25 for Linux is contained in the files
<file:Documentation/networking/x25.txt> and
<file:Documentation/networking/x25-iface.txt>.
......@@ -571,7 +571,7 @@ config NET_FASTROUTE
At the moment, few devices support fast switching (tulip is one of
them, a modified 8390 driver can be found at
<ftp://ftp.inr.ac.ru/ip-routing/fastroute/fastroute-8390.tar.gz>).
<ftp://ftp.tux.org/pub/net/ip-routing/fastroute/fastroute-8390.tar.gz>).
If unsure, say N.
......@@ -583,7 +583,7 @@ config NET_HW_FLOWCONTROL
during periods of extreme congestion. At the moment only a couple
of device drivers support it (really only one -- tulip, a modified
8390 driver can be found at
<ftp://ftp.inr.ac.ru/ip-routing/fastroute/fastroute-8390.tar.gz>).
<ftp://ftp.tux.org/pub/net/ip-routing/fastroute/fastroute-8390.tar.gz>).
Really, this option is applicable to any machine attached to a fast
enough network, and even a 10 Mb NIC is able to kill a not very slow
......@@ -614,7 +614,7 @@ config NET_SCHED
This code is considered to be experimental.
To administer these schedulers, you'll need the user-level utilities
from the package iproute2+tc at <ftp://ftp.inr.ac.ru/ip-routing/>.
from the package iproute2+tc at <ftp://ftp.tux.org/pub/net/ip-routing/>.
That package also contains some documentation; for more, check out
<http://snafu.freedom.org/linux2.2/iproute-notes.html>.
......
......@@ -160,6 +160,47 @@ static void sample_queue(unsigned long dummy);
static struct timer_list samp_timer = TIMER_INITIALIZER(sample_queue, 0, 0);
#endif
/*
* The @dev_base list is protected by @dev_base_lock and the rtln
* semaphore.
*
* Pure readers hold dev_base_lock for reading.
*
* Writers must hold the rtnl semaphore while they loop through the
* dev_base list, and hold dev_base_lock for writing when they do the
* actual updates. This allows pure readers to access the list even
* while a writer is preparing to update it.
*
* To put it another way, dev_base_lock is held for writing only to
* protect against pure readers; the rtnl semaphore provides the
* protection against other writers.
*
* See, for example usages, register_netdevice() and
* unregister_netdevice(), which must be called with the rtnl
* semaphore held.
*/
struct net_device *dev_base;
struct net_device **dev_tail = &dev_base;
rwlock_t dev_base_lock = RW_LOCK_UNLOCKED;
EXPORT_SYMBOL(dev_base);
EXPORT_SYMBOL(dev_base_lock);
#define NETDEV_HASHBITS 8
static struct hlist_head dev_name_head[1<<NETDEV_HASHBITS];
static struct hlist_head dev_index_head[1<<NETDEV_HASHBITS];
static inline struct hlist_head *dev_name_hash(const char *name)
{
unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ));
return &dev_name_head[hash & ((1<<NETDEV_HASHBITS)-1)];
}
static inline struct hlist_head *dev_index_hash(int ifindex)
{
return &dev_index_head[ifindex & ((1<<NETDEV_HASHBITS)-1)];
}
/*
* Our notifier list
*/
......@@ -443,12 +484,15 @@ __setup("netdev=", netdev_boot_setup);
struct net_device *__dev_get_by_name(const char *name)
{
struct net_device *dev;
struct hlist_node *p;
for (dev = dev_base; dev; dev = dev->next)
hlist_for_each(p, dev_name_hash(name)) {
struct net_device *dev
= hlist_entry(p, struct net_device, name_hlist);
if (!strncmp(dev->name, name, IFNAMSIZ))
break;
return dev;
return dev;
}
return NULL;
}
/**
......@@ -516,12 +560,15 @@ int __dev_get(const char *name)
struct net_device *__dev_get_by_index(int ifindex)
{
struct net_device *dev;
struct hlist_node *p;
for (dev = dev_base; dev; dev = dev->next)
hlist_for_each(p, dev_index_hash(ifindex)) {
struct net_device *dev
= hlist_entry(p, struct net_device, index_hlist);
if (dev->ifindex == ifindex)
break;
return dev;
return dev;
}
return NULL;
}
......@@ -673,30 +720,55 @@ int dev_valid_name(const char *name)
int dev_alloc_name(struct net_device *dev, const char *name)
{
int i;
char buf[32];
char *p;
int i = 0;
char buf[IFNAMSIZ];
const char *p;
const int max_netdevices = 8*PAGE_SIZE;
long *inuse;
struct net_device *d;
/*
* Verify the string as this thing may have come from
* the user. There must be either one "%d" and no other "%"
* characters, or no "%" characters at all.
*/
p = strchr(name, '%');
if (p && (p[1] != 'd' || strchr(p + 2, '%')))
return -EINVAL;
p = strnchr(name, IFNAMSIZ-1, '%');
if (p) {
/*
* Verify the string as this thing may have come from
* the user. There must be either one "%d" and no other "%"
* characters.
*/
if (p[1] != 'd' || strchr(p + 2, '%'))
return -EINVAL;
/*
* If you need over 100 please also fix the algorithm...
*/
for (i = 0; i < 100; i++) {
snprintf(buf, sizeof(buf), name, i);
if (!__dev_get_by_name(buf)) {
strcpy(dev->name, buf);
return i;
/* Use one page as a bit array of possible slots */
inuse = (long *) get_zeroed_page(GFP_ATOMIC);
if (!inuse)
return -ENOMEM;
for (d = dev_base; d; d = d->next) {
if (!sscanf(d->name, name, &i))
continue;
if (i < 0 || i >= max_netdevices)
continue;
/* avoid cases where sscanf is not exact inverse of printf */
snprintf(buf, sizeof(buf), name, i);
if (!strncmp(buf, d->name, IFNAMSIZ))
set_bit(i, inuse);
}
i = find_first_zero_bit(inuse, max_netdevices);
free_page((unsigned long) inuse);
}
return -ENFILE; /* Over 100 of the things .. bail out! */
snprintf(buf, sizeof(buf), name, i);
if (!__dev_get_by_name(buf)) {
strlcpy(dev->name, buf, IFNAMSIZ);
return i;
}
/* It is possible to run out of possible slots
* when the name is long and there isn't enough space left
* for the digits, or if all bits are used.
*/
return -ENFILE;
}
......@@ -729,6 +801,9 @@ int dev_change_name(struct net_device *dev, char *newname)
else
strlcpy(dev->name, newname, IFNAMSIZ);
hlist_del(&dev->name_hlist);
hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
class_device_rename(&dev->class_dev, dev->name);
notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
return 0;
......@@ -2717,7 +2792,8 @@ static inline void net_set_todo(struct net_device *dev)
int register_netdevice(struct net_device *dev)
{
struct net_device *d, **dp;
struct hlist_head *head;
struct hlist_node *p;
int ret;
BUG_ON(dev_boot_phase);
......@@ -2758,13 +2834,17 @@ int register_netdevice(struct net_device *dev)
if (dev->iflink == -1)
dev->iflink = dev->ifindex;
/* Check for existence, and append to tail of chain */
ret = -EEXIST;
for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
if (d == dev || !strcmp(d->name, dev->name))
goto out_err;
}
/* Check for existence of name */
head = dev_name_hash(dev->name);
hlist_for_each(p, head) {
struct net_device *d
= hlist_entry(p, struct net_device, name_hlist);
if (!strncmp(d->name, dev->name, IFNAMSIZ)) {
ret = -EEXIST;
goto out_err;
}
}
/* Fix illegal SG+CSUM combinations. */
if ((dev->features & NETIF_F_SG) &&
!(dev->features & (NETIF_F_IP_CSUM |
......@@ -2793,7 +2873,10 @@ int register_netdevice(struct net_device *dev)
dev->next = NULL;
dev_init_scheduler(dev);
write_lock_bh(&dev_base_lock);
*dp = dev;
*dev_tail = dev;
dev_tail = &dev->next;
hlist_add_head(&dev->name_hlist, head);
hlist_add_head(&dev->index_hlist, dev_index_hash(dev->ifindex));
dev_hold(dev);
dev->reg_state = NETREG_REGISTERING;
write_unlock_bh(&dev_base_lock);
......@@ -3015,6 +3098,10 @@ int unregister_netdevice(struct net_device *dev)
for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
if (d == dev) {
write_lock_bh(&dev_base_lock);
hlist_del(&dev->name_hlist);
hlist_del(&dev->index_hlist);
if (dev_tail == &dev->next)
dev_tail = dp;
*dp = d->next;
write_unlock_bh(&dev_base_lock);
break;
......@@ -3091,6 +3178,12 @@ static int __init net_dev_init(void)
for (i = 0; i < 16; i++)
INIT_LIST_HEAD(&ptype_base[i]);
for (i = 0; i < ARRAY_SIZE(dev_name_head); i++)
INIT_HLIST_HEAD(&dev_name_head[i]);
for (i = 0; i < ARRAY_SIZE(dev_index_head); i++)
INIT_HLIST_HEAD(&dev_index_head[i]);
/*
* Initialise the packet receive queues.
*/
......
......@@ -41,37 +41,11 @@ int net_msg_cost = 5*HZ;
int net_msg_burst = 10;
/*
* This enforces a rate limit: not more than one kernel message
* every 5secs to make a denial-of-service attack impossible.
*
* All warning printk()s should be guarded by this function.
* All net warning printk()s should be guarded by this function.
*/
int net_ratelimit(void)
{
static spinlock_t ratelimit_lock = SPIN_LOCK_UNLOCKED;
static unsigned long toks = 10*5*HZ;
static unsigned long last_msg;
static int missed;
unsigned long flags;
unsigned long now = jiffies;
spin_lock_irqsave(&ratelimit_lock, flags);
toks += now - last_msg;
last_msg = now;
if (toks > net_msg_burst)
toks = net_msg_burst;
if (toks >= net_msg_cost) {
int lost = missed;
missed = 0;
toks -= net_msg_cost;
spin_unlock_irqrestore(&ratelimit_lock, flags);
if (lost)
printk(KERN_WARNING "NET: %d messages suppressed.\n", lost);
return 1;
}
missed++;
spin_unlock_irqrestore(&ratelimit_lock, flags);
return 0;
return __printk_ratelimit(net_msg_cost, net_msg_burst);
}
EXPORT_SYMBOL(net_random);
......
......@@ -22,8 +22,9 @@ config DECNET_ROUTER
network link driver", "Routing messages" and "Network packet
filtering". The first two are required to allow configuration via
rtnetlink (you will need Alexey Kuznetsov's iproute2 package
from <ftp://ftp.inr.ac.ru/>). The "Network packet filtering" option
will be required for the forthcoming routing daemon to work.
from <ftp://ftp.tux.org/pub/net/ip-routing/>). The "Network packet
filtering" option will be required for the forthcoming routing daemon
to work.
See <file:Documentation/networking/decnet.txt> for more information.
......
......@@ -71,7 +71,7 @@ config IP_MULTIPLE_TABLES
documentation at <http://www.compendium.com.ar/policy-routing.txt>
and <ftp://post.tepkom.ru/pub/vol2/Linux/docs/advanced-routing.tex>.
You will need supporting software from
<ftp://ftp.inr.ac.ru/ip-routing/>.
<ftp://ftp.tux.org/pub/net/ip-routing/>.
If unsure, say N.
......
......@@ -67,6 +67,10 @@
* now it is in net/core/neighbour.c.
* Krzysztof Halasa: Added Frame Relay ARP support.
* Arnaldo C. Melo : convert /proc/net/arp to seq_file
* Shmulik Hen: Split arp_send to arp_create and
* arp_xmit so intermediate drivers like
* bonding can change the skb before
* sending (e.g. insert 8021q tag).
*/
#include <linux/module.h>
......@@ -487,26 +491,18 @@ static inline int arp_fwd_proxy(struct in_device *in_dev, struct rtable *rt)
*/
/*
* Create and send an arp packet. If (dest_hw == NULL), we create a broadcast
* Create an arp packet. If (dest_hw == NULL), we create a broadcast
* message.
*/
void arp_send(int type, int ptype, u32 dest_ip,
struct net_device *dev, u32 src_ip,
unsigned char *dest_hw, unsigned char *src_hw,
unsigned char *target_hw)
struct sk_buff *arp_create(int type, int ptype, u32 dest_ip,
struct net_device *dev, u32 src_ip,
unsigned char *dest_hw, unsigned char *src_hw,
unsigned char *target_hw)
{
struct sk_buff *skb;
struct arphdr *arp;
unsigned char *arp_ptr;
/*
* No arp on this interface.
*/
if (dev->flags&IFF_NOARP)
return;
/*
* Allocate a buffer
*/
......@@ -514,7 +510,7 @@ void arp_send(int type, int ptype, u32 dest_ip,
skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4)
+ LL_RESERVED_SPACE(dev), GFP_ATOMIC);
if (skb == NULL)
return;
return NULL;
skb_reserve(skb, LL_RESERVED_SPACE(dev));
skb->nh.raw = skb->data;
......@@ -594,12 +590,46 @@ void arp_send(int type, int ptype, u32 dest_ip,
arp_ptr+=dev->addr_len;
memcpy(arp_ptr, &dest_ip, 4);
/* Send it off, maybe filter it using firewalling first. */
NF_HOOK(NF_ARP, NF_ARP_OUT, skb, NULL, dev, dev_queue_xmit);
return;
return skb;
out:
kfree_skb(skb);
return NULL;
}
/*
* Send an arp packet.
*/
void arp_xmit(struct sk_buff *skb)
{
/* Send it off, maybe filter it using firewalling first. */
NF_HOOK(NF_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit);
}
/*
* Create and send an arp packet.
*/
void arp_send(int type, int ptype, u32 dest_ip,
struct net_device *dev, u32 src_ip,
unsigned char *dest_hw, unsigned char *src_hw,
unsigned char *target_hw)
{
struct sk_buff *skb;
/*
* No arp on this interface.
*/
if (dev->flags&IFF_NOARP)
return;
skb = arp_create(type, ptype, dest_ip, dev, src_ip,
dest_hw, src_hw, target_hw);
if (skb == NULL) {
return;
}
arp_xmit(skb);
}
static void parp_redo(struct sk_buff *skb)
......@@ -1437,6 +1467,8 @@ static int __init arp_proc_init(void)
EXPORT_SYMBOL(arp_broken_ops);
EXPORT_SYMBOL(arp_find);
EXPORT_SYMBOL(arp_rcv);
EXPORT_SYMBOL(arp_create);
EXPORT_SYMBOL(arp_xmit);
EXPORT_SYMBOL(arp_send);
EXPORT_SYMBOL(arp_tbl);
......
......@@ -707,8 +707,10 @@ static void ndisc_recv_ns(struct sk_buff *skb)
struct ndisc_options ndopts;
struct net_device *dev = skb->dev;
struct inet6_ifaddr *ifp;
struct inet6_dev *idev = NULL;
struct neighbour *neigh;
int addr_type = ipv6_addr_type(saddr);
int dad = ipv6_addr_any(saddr);
int inc;
if (ipv6_addr_is_multicast(&msg->target)) {
if (net_ratelimit())
......@@ -720,7 +722,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
* RFC2461 7.1.1:
* DAD has to be destined for solicited node multicast address.
*/
if (addr_type == IPV6_ADDR_ANY &&
if (dad &&
!(daddr->s6_addr32[0] == htonl(0xff020000) &&
daddr->s6_addr32[1] == htonl(0x00000000) &&
daddr->s6_addr32[2] == htonl(0x00000001) &&
......@@ -750,13 +752,15 @@ static void ndisc_recv_ns(struct sk_buff *skb)
* there MUST NOT be source link-layer address option
* in the message.
*/
if (addr_type == IPV6_ADDR_ANY) {
if (dad) {
if (net_ratelimit())
printk(KERN_WARNING "ICMP6 NS: bad DAD packet (link-layer address option)\n");
return;
}
}
inc = ipv6_addr_is_multicast(daddr);
if ((ifp = ipv6_get_ifaddr(&msg->target, dev, 1)) != NULL) {
if (ifp->flags & IFA_F_TENTATIVE) {
/* Address is tentative. If the source
......@@ -764,146 +768,89 @@ static void ndisc_recv_ns(struct sk_buff *skb)
does DAD, otherwise we ignore solicitations
until DAD timer expires.
*/
if (addr_type == IPV6_ADDR_ANY) {
if (dev->type == ARPHRD_IEEE802_TR) {
unsigned char *sadr = skb->mac.raw ;
if (((sadr[8] &0x7f) != (dev->dev_addr[0] & 0x7f)) ||
(sadr[9] != dev->dev_addr[1]) ||
(sadr[10] != dev->dev_addr[2]) ||
(sadr[11] != dev->dev_addr[3]) ||
(sadr[12] != dev->dev_addr[4]) ||
(sadr[13] != dev->dev_addr[5]))
{
addrconf_dad_failure(ifp) ;
}
} else {
addrconf_dad_failure(ifp);
if (!dad)
goto out;
if (dev->type == ARPHRD_IEEE802_TR) {
unsigned char *sadr = skb->mac.raw;
if (((sadr[8] ^ dev->dev_addr[0]) & 0x7f) == 0 &&
sadr[9] == dev->dev_addr[1] &&
sadr[10] == dev->dev_addr[2] &&
sadr[11] == dev->dev_addr[3] &&
sadr[12] == dev->dev_addr[4] &&
sadr[13] == dev->dev_addr[5]) {
/* looped-back to us */
goto out;
}
} else
in6_ifa_put(ifp);
return;
}
if (addr_type == IPV6_ADDR_ANY) {
struct in6_addr maddr;
ipv6_addr_all_nodes(&maddr);
ndisc_send_na(dev, NULL, &maddr, &ifp->addr,
ifp->idev->cnf.forwarding, 0,
1, 1);
in6_ifa_put(ifp);
}
addrconf_dad_failure(ifp);
return;
}
if (addr_type & IPV6_ADDR_UNICAST) {
if (ipv6_addr_is_multicast(daddr))
nd_tbl.stats.rcv_probes_mcast++;
else
nd_tbl.stats.rcv_probes_ucast++;
/*
* update / create cache entry
* for the source address
*/
neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
if (neigh || !dev->hard_header) {
ndisc_send_na(dev, neigh, saddr, &ifp->addr,
ifp->idev->cnf.forwarding, 1,
1, 1);
if (neigh)
neigh_release(neigh);
}
}
in6_ifa_put(ifp);
} else if (ipv6_chk_acast_addr(dev, &msg->target)) {
struct inet6_dev *idev = in6_dev_get(dev);
/* anycast */
idev = ifp->idev;
} else {
idev = in6_dev_get(dev);
if (!idev) {
/* XXX: count this drop? */
return;
}
if (addr_type == IPV6_ADDR_ANY) {
struct in6_addr maddr;
ipv6_addr_all_nodes(&maddr);
ndisc_send_na(dev, NULL, &maddr, &msg->target,
idev->cnf.forwarding, 0, 0, 1);
in6_dev_put(idev);
return;
}
if (addr_type & IPV6_ADDR_UNICAST) {
int inc = ipv6_addr_is_multicast(daddr);
if (inc)
nd_tbl.stats.rcv_probes_mcast++;
else
nd_tbl.stats.rcv_probes_ucast++;
/*
* update / create cache entry
* for the source address
*/
neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, skb->dev);
if (neigh || !dev->hard_header) {
ndisc_send_na(dev, neigh, saddr,
&msg->target,
idev->cnf.forwarding, 1, 0, inc);
if (neigh)
neigh_release(neigh);
}
}
in6_dev_put(idev);
} else {
struct inet6_dev *in6_dev = in6_dev_get(dev);
if (in6_dev && in6_dev->cnf.forwarding &&
(addr_type & IPV6_ADDR_UNICAST ||
addr_type == IPV6_ADDR_ANY) &&
pneigh_lookup(&nd_tbl, &msg->target, dev, 0)) {
int inc = ipv6_addr_is_multicast(daddr);
if (skb->stamp.tv_sec == 0 ||
skb->pkt_type == PACKET_HOST ||
inc == 0 ||
in6_dev->nd_parms->proxy_delay == 0) {
if (inc)
nd_tbl.stats.rcv_probes_mcast++;
else
nd_tbl.stats.rcv_probes_ucast++;
if (addr_type & IPV6_ADDR_UNICAST) {
neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
if (neigh) {
ndisc_send_na(dev, neigh, saddr, &msg->target,
0, 1, 0, 1);
neigh_release(neigh);
}
} else {
/* proxy should also protect against DAD */
struct in6_addr maddr;
ipv6_addr_all_nodes(&maddr);
ndisc_send_na(dev, NULL, &maddr, &msg->target,
0, 0, 0, 1);
}
} else {
if (ipv6_chk_acast_addr(dev, &msg->target) ||
(idev->cnf.forwarding &&
pneigh_lookup(&nd_tbl, &msg->target, dev, 0))) {
if (skb->stamp.tv_sec != 0 &&
skb->pkt_type != PACKET_HOST &&
inc != 0 &&
idev->nd_parms->proxy_delay != 0) {
/*
* for anycast or proxy,
* sender should delay its response
* by a random time between 0 and
* MAX_ANYCAST_DELAY_TIME seconds.
* (RFC2461) -- yoshfuji
*/
struct sk_buff *n = skb_clone(skb, GFP_ATOMIC);
if (n)
pneigh_enqueue(&nd_tbl, in6_dev->nd_parms, n);
in6_dev_put(in6_dev);
return;
pneigh_enqueue(&nd_tbl, idev->nd_parms, n);
goto out;
}
}
if (in6_dev)
in6_dev_put(in6_dev);
} else
goto out;
}
if (dad) {
struct in6_addr maddr;
ipv6_addr_all_nodes(&maddr);
ndisc_send_na(dev, NULL, &maddr, &msg->target,
idev->cnf.forwarding, 0, (ifp != NULL), 1);
goto out;
}
if (inc)
nd_tbl.stats.rcv_probes_mcast++;
else
nd_tbl.stats.rcv_probes_ucast++;
/*
* update / create cache entry
* for the source address
*/
neigh = neigh_event_ns(&nd_tbl, lladdr, saddr, dev);
if (neigh || !dev->hard_header) {
ndisc_send_na(dev, neigh, saddr, &msg->target,
idev->cnf.forwarding,
1, (ifp != NULL && inc), inc);
if (neigh)
neigh_release(neigh);
}
out:
if (ifp)
in6_ifa_put(ifp);
else
in6_dev_put(idev);
return;
}
......
......@@ -230,7 +230,7 @@ static int netlink_create(struct socket *sock, int protocol)
sock_init_data(sock,sk);
sk_set_owner(sk, THIS_MODULE);
nlk = nlk_sk(sk) = kmalloc(sizeof(*nlk), GFP_KERNEL);
nlk = sk->sk_protinfo = kmalloc(sizeof(*nlk), GFP_KERNEL);
if (!nlk) {
sk_free(sk);
return -ENOMEM;
......
......@@ -961,7 +961,7 @@ static int packet_create(struct socket *sock, int protocol)
sock_init_data(sock,sk);
sk_set_owner(sk, THIS_MODULE);
po = pkt_sk(sk) = kmalloc(sizeof(*po), GFP_KERNEL);
po = sk->sk_protinfo = kmalloc(sizeof(*po), GFP_KERNEL);
if (!po)
goto out_free;
memset(po, 0, sizeof(*po));
......
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