Commit afab4c80 authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/home/davem/src/BK/network-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents d6266c68 399f8927
......@@ -642,8 +642,7 @@ int __devinit acenic_probe (ACE_PROBE_ARG)
(pdev->device == PCI_DEVICE_ID_SGI_ACENIC)))
continue;
dev = init_etherdev(NULL, sizeof(struct ace_private));
dev = alloc_etherdev(sizeof(struct ace_private));
if (dev == NULL) {
printk(KERN_ERR "acenic: Unable to allocate "
"net_device structure!\n");
......@@ -653,13 +652,6 @@ int __devinit acenic_probe (ACE_PROBE_ARG)
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
if (!dev->priv)
dev->priv = kmalloc(sizeof(*ap), GFP_KERNEL);
if (!dev->priv) {
printk(KERN_ERR "acenic: Unable to allocate memory\n");
return -ENOMEM;
}
ap = dev->priv;
ap->pdev = pdev;
......@@ -739,6 +731,12 @@ int __devinit acenic_probe (ACE_PROBE_ARG)
break;
}
if (register_netdev(dev)) {
printk(KERN_ERR "acenic: device registration failed\n");
kfree(dev);
continue;
}
switch(pdev->vendor) {
case PCI_VENDOR_ID_ALTEON:
if (pdev->device == PCI_DEVICE_ID_FARALLON_PN9100T) {
......
......@@ -70,7 +70,7 @@
*/
static struct net_device *alloc_netdev(int sizeof_priv, const char *mask,
struct net_device *alloc_netdev(int sizeof_priv, const char *mask,
void (*setup)(struct net_device *))
{
struct net_device *dev;
......@@ -96,6 +96,7 @@ static struct net_device *alloc_netdev(int sizeof_priv, const char *mask,
return dev;
}
EXPORT_SYMBOL(alloc_netdev);
static struct net_device *init_alloc_dev(int sizeof_priv)
{
......
......@@ -2676,7 +2676,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
*/
if (pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_GEM &&
!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) {
!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) {
pci_using_dac = 1;
} else {
err = pci_set_dma_mask(pdev, (u64) 0xffffffff);
......
......@@ -805,14 +805,14 @@ struct gem_txd {
u64 buffer;
};
#define TXDCTRL_BUFSZ 0x0000000000007fff /* Buffer Size */
#define TXDCTRL_CSTART 0x00000000001f8000 /* CSUM Start Offset */
#define TXDCTRL_COFF 0x000000001fe00000 /* CSUM Stuff Offset */
#define TXDCTRL_CENAB 0x0000000020000000 /* CSUM Enable */
#define TXDCTRL_EOF 0x0000000040000000 /* End of Frame */
#define TXDCTRL_SOF 0x0000000080000000 /* Start of Frame */
#define TXDCTRL_INTME 0x0000000100000000 /* "Interrupt Me" */
#define TXDCTRL_NOCRC 0x0000000200000000 /* No CRC Present */
#define TXDCTRL_BUFSZ 0x0000000000007fffULL /* Buffer Size */
#define TXDCTRL_CSTART 0x00000000001f8000ULL /* CSUM Start Offset */
#define TXDCTRL_COFF 0x000000001fe00000ULL /* CSUM Stuff Offset */
#define TXDCTRL_CENAB 0x0000000020000000ULL /* CSUM Enable */
#define TXDCTRL_EOF 0x0000000040000000ULL /* End of Frame */
#define TXDCTRL_SOF 0x0000000080000000ULL /* Start of Frame */
#define TXDCTRL_INTME 0x0000000100000000ULL /* "Interrupt Me" */
#define TXDCTRL_NOCRC 0x0000000200000000ULL /* No CRC Present */
/* GEM requires that RX descriptors are provided four at a time,
* aligned. Also, the RX ring may not wrap around. This means that
......@@ -840,13 +840,13 @@ struct gem_rxd {
u64 buffer;
};
#define RXDCTRL_TCPCSUM 0x000000000000ffff /* TCP Pseudo-CSUM */
#define RXDCTRL_BUFSZ 0x000000007fff0000 /* Buffer Size */
#define RXDCTRL_OWN 0x0000000080000000 /* GEM owns this entry */
#define RXDCTRL_HASHVAL 0x0ffff00000000000 /* Hash Value */
#define RXDCTRL_HPASS 0x1000000000000000 /* Passed Hash Filter */
#define RXDCTRL_ALTMAC 0x2000000000000000 /* Matched ALT MAC */
#define RXDCTRL_BAD 0x4000000000000000 /* Frame has bad CRC */
#define RXDCTRL_TCPCSUM 0x000000000000ffffULL /* TCP Pseudo-CSUM */
#define RXDCTRL_BUFSZ 0x000000007fff0000ULL /* Buffer Size */
#define RXDCTRL_OWN 0x0000000080000000ULL /* GEM owns this entry */
#define RXDCTRL_HASHVAL 0x0ffff00000000000ULL /* Hash Value */
#define RXDCTRL_HPASS 0x1000000000000000ULL /* Passed Hash Filter */
#define RXDCTRL_ALTMAC 0x2000000000000000ULL /* Matched ALT MAC */
#define RXDCTRL_BAD 0x4000000000000000ULL /* Frame has bad CRC */
#define RXDCTRL_FRESH(gp) \
((((RX_BUF_ALLOC_SIZE(gp) - RX_OFFSET) << 16) & RXDCTRL_BUFSZ) | \
......
......@@ -32,10 +32,6 @@
#include <asm/byteorder.h>
#include <asm/uaccess.h>
#ifndef PCI_DMA_BUS_IS_PHYS
#define PCI_DMA_BUS_IS_PHYS 1
#endif
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define TG3_VLAN_TAG_USED 1
#else
......@@ -55,8 +51,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "1.5"
#define DRV_MODULE_RELDATE "March 21, 2003"
#define DRV_MODULE_VERSION "1.6"
#define DRV_MODULE_RELDATE "June 11, 2003"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
......@@ -2234,73 +2230,17 @@ static void tg3_tx_timeout(struct net_device *dev)
schedule_work(&tp->reset_task);
}
#if !PCI_DMA_BUS_IS_PHYS
static void tg3_set_txd_addr(struct tg3 *tp, int entry, dma_addr_t mapping)
{
if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
txd->addr_hi = ((u64) mapping >> 32);
txd->addr_lo = ((u64) mapping & 0xffffffff);
} else {
unsigned long txd;
txd = (tp->regs +
NIC_SRAM_WIN_BASE +
NIC_SRAM_TX_BUFFER_DESC);
txd += (entry * TXD_SIZE);
if (sizeof(dma_addr_t) != sizeof(u32))
writel(((u64) mapping >> 32),
txd + TXD_ADDR + TG3_64BIT_REG_HIGH);
writel(((u64) mapping & 0xffffffff),
txd + TXD_ADDR + TG3_64BIT_REG_LOW);
}
}
#endif
static void tg3_set_txd(struct tg3 *, int, dma_addr_t, int, u32, u32);
static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
u32 guilty_entry, int guilty_len,
u32 last_plus_one, u32 *start, u32 mss)
{
struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
dma_addr_t new_addr;
u32 entry = *start;
int i;
#if !PCI_DMA_BUS_IS_PHYS
/* IOMMU, just map the guilty area again which is guaranteed to
* use different addresses.
*/
i = 0;
while (entry != guilty_entry) {
entry = NEXT_TX(entry);
i++;
}
if (i == 0) {
new_addr = pci_map_single(tp->pdev, skb->data, guilty_len,
PCI_DMA_TODEVICE);
} else {
skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1];
new_addr = pci_map_page(tp->pdev,
frag->page, frag->page_offset,
guilty_len, PCI_DMA_TODEVICE);
}
pci_unmap_single(tp->pdev, pci_unmap_addr(&tp->tx_buffers[guilty_entry],
mapping),
guilty_len, PCI_DMA_TODEVICE);
tg3_set_txd_addr(tp, guilty_entry, new_addr);
pci_unmap_addr_set(&tp->tx_buffers[guilty_entry], mapping,
new_addr);
*start = last_plus_one;
#else
/* Oh well, no IOMMU, have to allocate a whole new SKB. */
struct sk_buff *new_skb = skb_copy(skb, GFP_ATOMIC);
if (!new_skb) {
dev_kfree_skb(skb);
return -1;
......@@ -2337,7 +2277,6 @@ static int tigon3_4gb_hwbug_workaround(struct tg3 *tp, struct sk_buff *skb,
}
dev_kfree_skb(skb);
#endif
return 0;
}
......
......@@ -122,12 +122,6 @@ int tun_net_init(struct net_device *dev)
DBG(KERN_INFO "%s: tun_net_init\n", tun->name);
SET_MODULE_OWNER(dev);
dev->open = tun_net_open;
dev->hard_start_xmit = tun_net_xmit;
dev->stop = tun_net_close;
dev->get_stats = tun_net_stats;
switch (tun->flags & TUN_TYPE_MASK) {
case TUN_TUN_DEV:
/* Point-to-Point TUN Device */
......@@ -199,14 +193,14 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv,
skb_reserve(skb, 2);
memcpy_fromiovec(skb_put(skb, len), iv, len);
skb->dev = &tun->dev;
skb->dev = tun->dev;
switch (tun->flags & TUN_TYPE_MASK) {
case TUN_TUN_DEV:
skb->mac.raw = skb->data;
skb->protocol = pi.proto;
break;
case TUN_TAP_DEV:
skb->protocol = eth_type_trans(skb, &tun->dev);
skb->protocol = eth_type_trans(skb, tun->dev);
break;
};
......@@ -325,7 +319,7 @@ static ssize_t tun_chr_readv(struct file *file, const struct iovec *iv,
schedule();
continue;
}
netif_start_queue(&tun->dev);
netif_start_queue(tun->dev);
ret = tun_put_user(tun, skb, (struct iovec *) iv, len);
......@@ -347,6 +341,24 @@ static ssize_t tun_chr_read(struct file * file, char * buf,
return tun_chr_readv(file, &iv, 1, pos);
}
static void tun_setup(struct net_device *dev)
{
struct tun_struct *tun = dev->priv;
skb_queue_head_init(&tun->readq);
init_waitqueue_head(&tun->read_wait);
tun->owner = -1;
dev->init = tun_net_init;
tun->name = dev->name;
SET_MODULE_OWNER(dev);
dev->open = tun_net_open;
dev->hard_start_xmit = tun_net_xmit;
dev->stop = tun_net_close;
dev->get_stats = tun_net_stats;
dev->destructor = (void (*)(struct net_device *))kfree;
}
static int tun_set_iff(struct file *file, struct ifreq *ifr)
{
struct tun_struct *tun;
......@@ -367,30 +379,18 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
return -EPERM;
} else {
char *name;
/* Allocate new device */
if (!(tun = kmalloc(sizeof(struct tun_struct), GFP_KERNEL)) )
return -ENOMEM;
memset(tun, 0, sizeof(struct tun_struct));
skb_queue_head_init(&tun->readq);
init_waitqueue_head(&tun->read_wait);
tun->owner = -1;
tun->dev.init = tun_net_init;
tun->dev.priv = tun;
SET_MODULE_OWNER(&tun->dev);
unsigned long flags = 0;
err = -EINVAL;
/* Set dev type */
if (ifr->ifr_flags & IFF_TUN) {
/* TUN device */
tun->flags |= TUN_TUN_DEV;
flags |= TUN_TUN_DEV;
name = "tun%d";
} else if (ifr->ifr_flags & IFF_TAP) {
/* TAP device */
tun->flags |= TUN_TAP_DEV;
flags |= TUN_TAP_DEV;
name = "tap%d";
} else
goto failed;
......@@ -398,12 +398,27 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
if (*ifr->ifr_name)
name = ifr->ifr_name;
if ((err = dev_alloc_name(&tun->dev, name)) < 0)
goto failed;
if ((err = register_netdevice(&tun->dev)))
dev = alloc_netdev(sizeof(struct tun_struct), name,
tun_setup);
if (!dev)
return -ENOMEM;
tun = dev->priv;
tun->flags = flags;
if (strchr(dev->name, '%')) {
err = dev_alloc_name(dev, dev->name);
if (err < 0) {
kfree(dev);
goto failed;
}
}
if ((err = register_netdevice(tun->dev))) {
kfree(dev);
goto failed;
}
tun->name = tun->dev.name;
}
DBG(KERN_INFO "%s: tun_set_iff\n", tun->name);
......@@ -419,9 +434,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
strcpy(ifr->ifr_name, tun->name);
return 0;
failed:
kfree(tun);
failed:
return err;
}
......@@ -548,10 +561,8 @@ static int tun_chr_close(struct inode *inode, struct file *file)
/* Drop read queue */
skb_queue_purge(&tun->readq);
if (!(tun->flags & TUN_PERSIST)) {
dev_close(&tun->dev);
unregister_netdevice(&tun->dev);
}
if (!(tun->flags & TUN_PERSIST))
unregister_netdevice(tun->dev);
rtnl_unlock();
......@@ -574,11 +585,10 @@ static struct file_operations tun_fops = {
.fasync = tun_chr_fasync
};
static struct miscdevice tun_miscdev=
{
TUN_MINOR,
"net/tun",
&tun_fops
static struct miscdevice tun_miscdev = {
.minor = TUN_MINOR,
.name = "net/tun",
.fops = &tun_fops
};
int __init tun_init(void)
......
......@@ -40,7 +40,6 @@ extern int eth_header_parse(struct sk_buff *skb,
unsigned char *haddr);
extern struct net_device *init_etherdev(struct net_device *dev, int sizeof_priv);
extern struct net_device *alloc_etherdev(int sizeof_priv);
static inline void eth_copy_and_sum (struct sk_buff *dest, unsigned char *src, int len, int base)
{
memcpy (dest->data, src, len);
......
......@@ -40,7 +40,7 @@ struct tun_struct {
wait_queue_head_t read_wait;
struct sk_buff_head readq;
struct net_device dev;
struct net_device *dev;
struct net_device_stats stats;
struct fasync_struct *fasync;
......
......@@ -816,6 +816,8 @@ extern void tr_setup(struct net_device *dev);
extern void fc_setup(struct net_device *dev);
extern void fc_freedev(struct net_device *dev);
/* Support for loadable net-drivers */
extern struct net_device *alloc_netdev(int sizeof_priv, const char *name,
void (*setup)(struct net_device *));
extern int register_netdev(struct net_device *dev);
extern void unregister_netdev(struct net_device *dev);
/* Functions used for multicast support */
......
......@@ -111,7 +111,7 @@ struct arpt_counters
#define ARPT_INV_ARPHRD 0x0080 /* Invert the sense of ARP HRD. */
#define ARPT_INV_ARPPRO 0x0100 /* Invert the sense of ARP PRO. */
#define ARPT_INV_ARPHLN 0x0200 /* Invert the sense of ARP HLN. */
#define ARPT_INV_MASK 0x007F /* All possible flag bits mask. */
#define ARPT_INV_MASK 0x03FF /* All possible flag bits mask. */
/* This structure defines each of the firewall rules. Consists of 3
parts which are 1) general ARP header stuff 2) match specific
......
......@@ -334,6 +334,33 @@ static int unregister_vlan_device(const char *vlan_IF_name)
return ret;
}
static void vlan_setup(struct net_device *new_dev)
{
SET_MODULE_OWNER(new_dev);
/* new_dev->ifindex = 0; it will be set when added to
* the global list.
* iflink is set as well.
*/
new_dev->get_stats = vlan_dev_get_stats;
/* Make this thing known as a VLAN device */
new_dev->priv_flags |= IFF_802_1Q_VLAN;
/* Set us up to have no queue, as the underlying Hardware device
* can do all the queueing we could want.
*/
new_dev->tx_queue_len = 0;
/* set up method calls */
new_dev->change_mtu = vlan_dev_change_mtu;
new_dev->open = vlan_dev_open;
new_dev->stop = vlan_dev_stop;
new_dev->set_mac_address = vlan_dev_set_mac_address;
new_dev->set_multicast_list = vlan_dev_set_multicast_list;
new_dev->destructor = (void (*)(struct net_device *)) kfree;
}
/* Attach a VLAN device to a mac address (ie Ethernet Card).
* Returns the device that was created, or NULL if there was
* an error of some kind.
......@@ -344,8 +371,8 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
struct vlan_group *grp;
struct net_device *new_dev;
struct net_device *real_dev; /* the ethernet device */
int malloc_size = 0;
int r;
char name[IFNAMSIZ];
#ifdef VLAN_DEBUG
printk(VLAN_DBG "%s: if_name -:%s:- vid: %i\n",
......@@ -403,21 +430,6 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
goto out_unlock;
}
malloc_size = (sizeof(struct net_device));
new_dev = (struct net_device *) kmalloc(malloc_size, GFP_KERNEL);
VLAN_MEM_DBG("net_device malloc, addr: %p size: %i\n",
new_dev, malloc_size);
if (new_dev == NULL)
goto out_unlock;
memset(new_dev, 0, malloc_size);
/* Set us up to have no queue, as the underlying Hardware device
* can do all the queueing we could want.
*/
new_dev->tx_queue_len = 0;
/* Gotta set up the fields for the device. */
#ifdef VLAN_DEBUG
printk(VLAN_DBG "About to allocate name, vlan_name_type: %i\n",
......@@ -426,54 +438,44 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
switch (vlan_name_type) {
case VLAN_NAME_TYPE_RAW_PLUS_VID:
/* name will look like: eth1.0005 */
sprintf(new_dev->name, "%s.%.4i", real_dev->name, VLAN_ID);
snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev->name, VLAN_ID);
break;
case VLAN_NAME_TYPE_PLUS_VID_NO_PAD:
/* Put our vlan.VID in the name.
* Name will look like: vlan5
*/
sprintf(new_dev->name, "vlan%i", VLAN_ID);
snprintf(name, IFNAMSIZ, "vlan%i", VLAN_ID);
break;
case VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD:
/* Put our vlan.VID in the name.
* Name will look like: eth0.5
*/
sprintf(new_dev->name, "%s.%i", real_dev->name, VLAN_ID);
snprintf(name, IFNAMSIZ, "%s.%i", real_dev->name, VLAN_ID);
break;
case VLAN_NAME_TYPE_PLUS_VID:
/* Put our vlan.VID in the name.
* Name will look like: vlan0005
*/
default:
sprintf(new_dev->name, "vlan%.4i", VLAN_ID);
snprintf(name, IFNAMSIZ, "vlan%.4i", VLAN_ID);
};
new_dev = alloc_netdev(sizeof(struct vlan_dev_info), name,
vlan_setup);
if (new_dev == NULL)
goto out_unlock;
#ifdef VLAN_DEBUG
printk(VLAN_DBG "Allocated new name -:%s:-\n", new_dev->name);
#endif
/* set up method calls */
new_dev->init = vlan_dev_init;
new_dev->destructor = vlan_dev_destruct;
SET_MODULE_OWNER(new_dev);
/* new_dev->ifindex = 0; it will be set when added to
* the global list.
* iflink is set as well.
*/
new_dev->get_stats = vlan_dev_get_stats;
/* IFF_BROADCAST|IFF_MULTICAST; ??? */
new_dev->flags = real_dev->flags;
new_dev->flags &= ~IFF_UP;
/* Make this thing known as a VLAN device */
new_dev->priv_flags |= IFF_802_1Q_VLAN;
/* need 4 bytes for extra VLAN header info,
* hope the underlying device can handle it.
*/
new_dev->mtu = real_dev->mtu;
new_dev->change_mtu = vlan_dev_change_mtu;
/* TODO: maybe just assign it to be ETHERNET? */
new_dev->type = real_dev->type;
......@@ -484,24 +486,14 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
new_dev->hard_header_len += VLAN_HLEN;
}
new_dev->priv = kmalloc(sizeof(struct vlan_dev_info),
GFP_KERNEL);
VLAN_MEM_DBG("new_dev->priv malloc, addr: %p size: %i\n",
new_dev->priv,
sizeof(struct vlan_dev_info));
if (new_dev->priv == NULL)
goto out_free_newdev;
memset(new_dev->priv, 0, sizeof(struct vlan_dev_info));
memcpy(new_dev->broadcast, real_dev->broadcast, real_dev->addr_len);
memcpy(new_dev->dev_addr, real_dev->dev_addr, real_dev->addr_len);
new_dev->addr_len = real_dev->addr_len;
new_dev->open = vlan_dev_open;
new_dev->stop = vlan_dev_stop;
if (real_dev->features & NETIF_F_HW_VLAN_TX) {
new_dev->hard_header = real_dev->hard_header;
new_dev->hard_start_xmit = vlan_dev_hwaccel_hard_start_xmit;
......@@ -512,8 +504,6 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
new_dev->rebuild_header = vlan_dev_rebuild_header;
}
new_dev->hard_header_parse = real_dev->hard_header_parse;
new_dev->set_mac_address = vlan_dev_set_mac_address;
new_dev->set_multicast_list = vlan_dev_set_multicast_list;
VLAN_DEV_INFO(new_dev)->vlan_id = VLAN_ID; /* 1 through VLAN_VID_MASK */
VLAN_DEV_INFO(new_dev)->real_dev = real_dev;
......@@ -526,7 +516,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
#endif
if (register_netdevice(new_dev))
goto out_free_newdev_priv;
goto out_free_newdev;
/* So, got the sucker initialized, now lets place
* it into our local structure.
......@@ -572,9 +562,7 @@ static struct net_device *register_vlan_device(const char *eth_IF_name,
out_free_unregister:
unregister_netdev(new_dev);
out_free_newdev_priv:
kfree(new_dev->priv);
goto out_put_dev;
out_free_newdev:
kfree(new_dev);
......
......@@ -65,8 +65,6 @@ int vlan_dev_change_mtu(struct net_device *dev, int new_mtu);
int vlan_dev_set_mac_address(struct net_device *dev, void* addr);
int vlan_dev_open(struct net_device* dev);
int vlan_dev_stop(struct net_device* dev);
int vlan_dev_init(struct net_device* dev);
void vlan_dev_destruct(struct net_device* dev);
int vlan_dev_set_ingress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
int vlan_dev_set_egress_priority(char* dev_name, __u32 skb_prio, short vlan_prio);
int vlan_dev_set_vlan_flag(char* dev_name, __u32 flag, short flag_val);
......
......@@ -766,28 +766,6 @@ int vlan_dev_stop(struct net_device *dev)
vlan_flush_mc_list(dev);
return 0;
}
int vlan_dev_init(struct net_device *dev)
{
/* TODO: figure this out, maybe do nothing?? */
return 0;
}
void vlan_dev_destruct(struct net_device *dev)
{
if (dev) {
vlan_flush_mc_list(dev);
if (dev->priv) {
if (VLAN_DEV_INFO(dev)->dent)
BUG();
kfree(dev->priv);
dev->priv = NULL;
}
kfree(dev);
}
}
/** Taken from Gleb + Lennert's VLAN code, and modified... */
void vlan_dev_set_multicast_list(struct net_device *vlan_dev)
{
......
......@@ -110,10 +110,6 @@ static int br_dev_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
return -1;
}
static void br_dev_destruct(struct net_device *dev)
{
kfree(dev->priv);
}
void br_dev_setup(struct net_device *dev)
{
......@@ -124,10 +120,13 @@ void br_dev_setup(struct net_device *dev)
dev->hard_start_xmit = br_dev_xmit;
dev->open = br_dev_open;
dev->set_multicast_list = br_dev_set_multicast_list;
dev->destructor = br_dev_destruct;
dev->destructor = (void (*)(struct net_device *))kfree;
SET_MODULE_OWNER(dev);
dev->stop = br_dev_stop;
dev->accept_fastpath = br_dev_accept_fastpath;
dev->tx_queue_len = 0;
dev->set_mac_address = NULL;
dev->priv_flags = IFF_EBRIDGE;
ether_setup(dev);
}
......@@ -78,17 +78,14 @@ static struct net_bridge *new_nb(const char *name)
struct net_bridge *br;
struct net_device *dev;
if ((br = kmalloc(sizeof(*br), GFP_KERNEL)) == NULL)
dev = alloc_netdev(sizeof(struct net_bridge), name,
br_dev_setup);
if (!dev)
return NULL;
memset(br, 0, sizeof(*br));
dev = &br->dev;
strlcpy(dev->name, name, sizeof(dev->name));
dev->priv = br;
dev->priv_flags = IFF_EBRIDGE;
ether_setup(dev);
br_dev_setup(dev);
br = dev->priv;
br->dev = dev;
br->lock = SPIN_LOCK_UNLOCKED;
INIT_LIST_HEAD(&br->port_list);
......@@ -159,9 +156,9 @@ int br_add_bridge(const char *name)
if ((br = new_nb(name)) == NULL)
return -ENOMEM;
ret = register_netdev(&br->dev);
ret = register_netdev(br->dev);
if (ret)
kfree(br);
kfree(br->dev);
return ret;
}
......@@ -219,7 +216,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
br_stp_recalculate_bridge_id(br);
br_fdb_insert(br, p, dev->dev_addr, 1);
if ((br->dev.flags & IFF_UP) && (dev->flags & IFF_UP))
if ((br->dev->flags & IFF_UP) && (dev->flags & IFF_UP))
br_stp_enable_port(p);
spin_unlock_bh(&br->lock);
......
......@@ -40,7 +40,7 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
br->statistics.rx_bytes += skb->len;
indev = skb->dev;
skb->dev = &br->dev;
skb->dev = br->dev;
NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
br_pass_frame_up_finish);
......@@ -67,7 +67,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
br = p->br;
passedup = 0;
if (br->dev.flags & IFF_PROMISC) {
if (br->dev->flags & IFF_PROMISC) {
struct sk_buff *skb2;
skb2 = skb_clone(skb, GFP_ATOMIC);
......@@ -140,7 +140,7 @@ int br_handle_frame(struct sk_buff *skb)
return -1;
}
if (!memcmp(p->br->dev.dev_addr, dest, ETH_ALEN))
if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN))
skb->pkt_type = PACKET_HOST;
NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
......
......@@ -37,7 +37,7 @@
sizeof(struct bridge_skb_cb)))
#define has_bridge_parent(device) ((device)->br_port != NULL)
#define bridge_parent(device) (&((device)->br_port->br->dev))
#define bridge_parent(device) ((device)->br_port->br->dev)
/* We need these fake structures to make netfilter happy --
* lots of places assume that skb->dst != NULL, which isn't
......
......@@ -52,7 +52,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
break;
case NETDEV_DOWN:
if (br->dev.flags & IFF_UP) {
if (br->dev->flags & IFF_UP) {
spin_lock_bh(&br->lock);
br_stp_disable_port(p);
spin_unlock_bh(&br->lock);
......@@ -60,7 +60,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
break;
case NETDEV_UP:
if (!(br->dev.flags & IFF_UP)) {
if (!(br->dev->flags & IFF_UP)) {
spin_lock_bh(&br->lock);
br_stp_enable_port(p);
spin_unlock_bh(&br->lock);
......
......@@ -81,7 +81,7 @@ struct net_bridge
{
spinlock_t lock;
struct list_head port_list;
struct net_device dev;
struct net_device *dev;
struct net_device_stats statistics;
rwlock_t hash_lock;
struct hlist_head hash[BR_HASH_SIZE];
......
......@@ -26,7 +26,7 @@ static const char *br_port_state_names[] = {
void br_log_state(const struct net_bridge_port *p)
{
pr_info("%s: port %d(%s) entering %s state\n",
p->br->dev.name, p->port_no, p->dev->name,
p->br->dev->name, p->port_no, p->dev->name,
br_port_state_names[p->state]);
}
......@@ -130,7 +130,7 @@ void br_become_root_bridge(struct net_bridge *br)
br_topology_change_detection(br);
del_timer(&br->tcn_timer);
if (br->dev.flags & IFF_UP) {
if (br->dev->flags & IFF_UP) {
br_config_bpdu_generation(br);
mod_timer(&br->hello_timer, jiffies + br->hello_time);
}
......@@ -289,10 +289,10 @@ static inline void br_topology_change_acknowledged(struct net_bridge *br)
/* called under bridge lock */
void br_topology_change_detection(struct net_bridge *br)
{
if (!(br->dev.flags & IFF_UP))
if (!(br->dev->flags & IFF_UP))
return;
pr_info("%s: topology change detected", br->dev.name);
pr_info("%s: topology change detected", br->dev->name);
if (br_is_root_bridge(br)) {
printk(", propagating");
br->topology_change = 1;
......@@ -446,7 +446,7 @@ void br_received_tcn_bpdu(struct net_bridge_port *p)
{
if (br_is_designated_port(p)) {
pr_info("%s: received tcn bpdu on port %i(%s)\n",
p->br->dev.name, p->port_no, p->dev->name);
p->br->dev->name, p->port_no, p->dev->name);
br_topology_change_detection(p->br);
br_topology_change_acknowledge(p);
......
......@@ -145,7 +145,7 @@ void br_stp_handle_bpdu(struct sk_buff *skb)
spin_lock_bh(&br->lock);
if (p->state == BR_STATE_DISABLED
|| !(br->dev.flags & IFF_UP)
|| !(br->dev->flags & IFF_UP)
|| !br->stp_enabled
|| memcmp(buf, header, 6))
goto out;
......
......@@ -93,7 +93,7 @@ void br_stp_disable_port(struct net_bridge_port *p)
br = p->br;
printk(KERN_INFO "%s: port %i(%s) entering %s state\n",
br->dev.name, p->port_no, p->dev->name, "disabled");
br->dev->name, p->port_no, p->dev->name, "disabled");
wasroot = br_is_root_bridge(br);
br_become_designated_port(p);
......@@ -124,7 +124,7 @@ static void br_stp_change_bridge_id(struct net_bridge *br, unsigned char *addr)
memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN);
memcpy(br->bridge_id.addr, addr, ETH_ALEN);
memcpy(br->dev.dev_addr, addr, ETH_ALEN);
memcpy(br->dev->dev_addr, addr, ETH_ALEN);
list_for_each_entry(p, &br->port_list, list) {
if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN))
......
......@@ -38,9 +38,9 @@ static void br_hello_timer_expired(unsigned long arg)
{
struct net_bridge *br = (struct net_bridge *)arg;
pr_debug("%s: hello timer expired\n", br->dev.name);
pr_debug("%s: hello timer expired\n", br->dev->name);
spin_lock_bh(&br->lock);
if (br->dev.flags & IFF_UP) {
if (br->dev->flags & IFF_UP) {
br_config_bpdu_generation(br);
br->hello_timer.expires = jiffies + br->hello_time;
......@@ -61,7 +61,7 @@ static void br_message_age_timer_expired(unsigned long arg)
pr_info("%s: neighbor %.2x%.2x.%.2x:%.2x:%.2x:%.2x:%.2x:%.2x lost on port %d(%s)\n",
br->dev.name,
br->dev->name,
id->prio[0], id->prio[1],
id->addr[0], id->addr[1], id->addr[2],
id->addr[3], id->addr[4], id->addr[5],
......@@ -89,7 +89,7 @@ static void br_forward_delay_timer_expired(unsigned long arg)
struct net_bridge *br = p->br;
pr_debug("%s: %d(%s) forward delay timer\n",
br->dev.name, p->port_no, p->dev->name);
br->dev->name, p->port_no, p->dev->name);
spin_lock_bh(&br->lock);
if (p->state == BR_STATE_LISTENING) {
p->state = BR_STATE_LEARNING;
......@@ -108,9 +108,9 @@ static void br_tcn_timer_expired(unsigned long arg)
{
struct net_bridge *br = (struct net_bridge *) arg;
pr_debug("%s: tcn timer expired\n", br->dev.name);
pr_debug("%s: tcn timer expired\n", br->dev->name);
spin_lock_bh(&br->lock);
if (br->dev.flags & IFF_UP) {
if (br->dev->flags & IFF_UP) {
br_transmit_tcn(br);
br->tcn_timer.expires = jiffies + br->bridge_hello_time;
......@@ -123,7 +123,7 @@ static void br_topology_change_timer_expired(unsigned long arg)
{
struct net_bridge *br = (struct net_bridge *) arg;
pr_debug("%s: topo change timer expired\n", br->dev.name);
pr_debug("%s: topo change timer expired\n", br->dev->name);
spin_lock_bh(&br->lock);
br->topology_change_detected = 0;
br->topology_change = 0;
......@@ -135,7 +135,7 @@ static void br_hold_timer_expired(unsigned long arg)
struct net_bridge_port *p = (struct net_bridge_port *) arg;
pr_debug("%s: %d(%s) hold timer expired\n",
p->br->dev.name, p->port_no, p->dev->name);
p->br->dev->name, p->port_no, p->dev->name);
spin_lock_bh(&p->br->lock);
if (p->config_pending)
......
......@@ -22,7 +22,7 @@ static int ebt_target_redirect(struct sk_buff **pskb, unsigned int hooknr,
if (hooknr != NF_BR_BROUTING)
memcpy((**pskb).mac.ethernet->h_dest,
in->br_port->br->dev.dev_addr, ETH_ALEN);
in->br_port->br->dev->dev_addr, ETH_ALEN);
else {
memcpy((**pskb).mac.ethernet->h_dest,
in->dev_addr, ETH_ALEN);
......
......@@ -135,10 +135,10 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h,
if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT))
return 1;
if ((!in || !in->br_port) ? 0 : FWINV2(ebt_dev_check(
e->logical_in, &in->br_port->br->dev), EBT_ILOGICALIN))
e->logical_in, in->br_port->br->dev), EBT_ILOGICALIN))
return 1;
if ((!out || !out->br_port) ? 0 : FWINV2(ebt_dev_check(
e->logical_out, &out->br_port->br->dev), EBT_ILOGICALOUT))
e->logical_out, out->br_port->br->dev), EBT_ILOGICALOUT))
return 1;
if (e->bitmask & EBT_SOURCEMAC) {
......
......@@ -3005,14 +3005,15 @@ subsys_initcall(net_dev_init);
#ifdef CONFIG_HOTPLUG
struct net_hotplug_todo {
struct net_hotplug_todo *next;
struct list_head list;
char ifname[IFNAMSIZ];
int is_register;
};
static spinlock_t net_hotplug_list_lock = SPIN_LOCK_UNLOCKED;
static struct net_hotplug_todo *net_hotplug_list;
static DECLARE_MUTEX(net_hotplug_run);
static struct list_head net_hotplug_list = LIST_HEAD_INIT(net_hotplug_list);
static void net_run_hotplug_one(struct net_hotplug_todo *ent)
static inline void net_run_hotplug_one(struct net_hotplug_todo *ent)
{
char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action_str[32];
int i;
......@@ -3037,23 +3038,37 @@ static void net_run_hotplug_one(struct net_hotplug_todo *ent)
call_usermodehelper(argv [0], argv, envp, 0);
}
/* Run all queued hotplug requests.
* Requests are run in FIFO order.
*/
static void net_run_hotplug_todo(void)
{
struct net_hotplug_todo *list;
struct list_head list = LIST_HEAD_INIT(list);
/* This is racy but okay since any other requests will get
* processed when the other guy does rtnl_unlock.
*/
if (list_empty(&net_hotplug_list))
return;
/* Need to guard against multiple cpu's getting out of order. */
down(&net_hotplug_run);
/* Snapshot list, allow later requests */
spin_lock(&net_hotplug_list_lock);
list = net_hotplug_list;
net_hotplug_list = NULL;
list_splice_init(&net_hotplug_list, &list);
spin_unlock(&net_hotplug_list_lock);
while (list != NULL) {
struct net_hotplug_todo *next = list->next;
while (!list_empty(&list)) {
struct net_hotplug_todo *ent;
net_run_hotplug_one(list);
kfree(list);
list = next;
ent = list_entry(list.next, struct net_hotplug_todo, list);
list_del(&ent->list);
net_run_hotplug_one(ent);
kfree(ent);
}
up(&net_hotplug_run);
}
/* Notify userspace when a netdevice event occurs,
......@@ -3065,15 +3080,17 @@ static void net_run_sbin_hotplug(struct net_device *dev, int is_register)
{
struct net_hotplug_todo *ent = kmalloc(sizeof(*ent), GFP_KERNEL);
ASSERT_RTNL();
if (!ent)
return;
INIT_LIST_HEAD(&ent->list);
memcpy(ent->ifname, dev->name, IFNAMSIZ);
ent->is_register = is_register;
spin_lock(&net_hotplug_list_lock);
ent->next = net_hotplug_list;
net_hotplug_list = ent;
list_add(&ent->list, &net_hotplug_list);
spin_unlock(&net_hotplug_list_lock);
}
#endif
......@@ -1094,6 +1094,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
kfree(p);
return NULL;
}
p->sysctl_table = NULL;
write_lock_bh(&tbl->lock);
p->next = tbl->parms.next;
tbl->parms.next = p;
......@@ -1113,9 +1114,6 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
if (*p == parms) {
*p = parms->next;
write_unlock_bh(&tbl->lock);
#ifdef CONFIG_SYSCTL
neigh_sysctl_unregister(parms);
#endif
kfree(parms);
return;
}
......@@ -1178,9 +1176,6 @@ int neigh_table_clear(struct neigh_table *tbl)
}
}
write_unlock(&neigh_tbl_lock);
#ifdef CONFIG_SYSCTL
neigh_sysctl_unregister(&tbl->parms);
#endif
return 0;
}
......
......@@ -3,10 +3,6 @@
*
* Copyright (c) 2003 Stephen Hemminber <shemminger@osdl.org>
*
*
* TODO:
* last_tx
* last_rx
*/
#include <linux/config.h>
......@@ -16,33 +12,61 @@
#include <net/sock.h>
#include <linux/rtnetlink.h>
#define to_net_dev(class) container_of((class), struct net_device, class_dev)
#define to_class_dev(obj) container_of(obj,struct class_device,kobj)
#define to_net_dev(class) container_of(class, struct net_device, class_dev)
/* use same locking rules as GIF* ioctl's */
static ssize_t netdev_show(const struct class_device *cd, char *buf,
ssize_t (*format)(const struct net_device *, char *))
{
struct net_device *net = to_net_dev(cd);
ssize_t ret = -EINVAL;
read_lock(&dev_base_lock);
if (!net->deadbeaf)
ret = (*format)(net, buf);
read_unlock(&dev_base_lock);
return ret;
}
/* generate a show function for simple field */
/* generate a show function for simple field */
#define NETDEVICE_SHOW(field, format_string) \
static ssize_t show_##field(struct class_device *dev, char *buf) \
static ssize_t format_##field(const struct net_device *net, char *buf) \
{ \
return sprintf(buf, format_string, to_net_dev(dev)->field); \
return sprintf(buf, format_string, net->field); \
} \
static ssize_t show_##field(struct class_device *cd, char *buf) \
{ \
return netdev_show(cd, buf, format_##field); \
}
/* generate a store function for a field with locking */
#define NETDEVICE_STORE(field) \
static ssize_t \
store_##field(struct class_device *dev, const char *buf, size_t len) \
{ \
char *endp; \
long new = simple_strtol(buf, &endp, 16); \
\
if (endp == buf || new < 0) \
return -EINVAL; \
\
if (!capable(CAP_NET_ADMIN)) \
return -EPERM; \
\
rtnl_lock(); \
to_net_dev(dev)->field = new; \
rtnl_unlock(); \
return len; \
/* use same locking and permission rules as SIF* ioctl's */
static ssize_t netdev_store(struct class_device *dev,
const char *buf, size_t len,
int (*set)(struct net_device *, unsigned long))
{
struct net_device *net = to_net_dev(dev);
char *endp;
unsigned long new;
int ret = -EINVAL;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
new = simple_strtoul(buf, &endp, 0);
if (endp == buf)
goto err;
rtnl_lock();
if (!net->deadbeaf) {
if ((ret = (*set)(net, new)) == 0)
ret = len;
}
rtnl_unlock();
err:
return ret;
}
/* generate a read-only network device class attribute */
......@@ -56,6 +80,7 @@ NETDEVICE_ATTR(ifindex, "%d\n");
NETDEVICE_ATTR(features, "%#x\n");
NETDEVICE_ATTR(type, "%d\n");
/* use same locking rules as GIFHWADDR ioctl's */
static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
{
int i;
......@@ -72,12 +97,16 @@ static ssize_t format_addr(char *buf, const unsigned char *addr, int len)
static ssize_t show_address(struct class_device *dev, char *buf)
{
struct net_device *net = to_net_dev(dev);
if (net->deadbeaf)
return -EINVAL;
return format_addr(buf, net->dev_addr, net->addr_len);
}
static ssize_t show_broadcast(struct class_device *dev, char *buf)
{
struct net_device *net = to_net_dev(dev);
if (net->deadbeaf)
return -EINVAL;
return format_addr(buf, net->broadcast, net->addr_len);
}
......@@ -87,54 +116,45 @@ static CLASS_DEVICE_ATTR(broadcast, S_IRUGO, show_broadcast, NULL);
/* read-write attributes */
NETDEVICE_SHOW(mtu, "%d\n");
static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
static int change_mtu(struct net_device *net, unsigned long new_mtu)
{
char *endp;
int new_mtu;
int err;
new_mtu = simple_strtoul(buf, &endp, 10);
if (endp == buf)
return -EINVAL;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
rtnl_lock();
err = dev_set_mtu(to_net_dev(dev), new_mtu);
rtnl_unlock();
return dev_set_mtu(net, (int) new_mtu);
}
return err == 0 ? len : err;
static ssize_t store_mtu(struct class_device *dev, const char *buf, size_t len)
{
return netdev_store(dev, buf, len, change_mtu);
}
static CLASS_DEVICE_ATTR(mtu, S_IRUGO | S_IWUSR, show_mtu, store_mtu);
NETDEVICE_SHOW(flags, "%#x\n");
static int change_flags(struct net_device *net, unsigned long new_flags)
{
return dev_change_flags(net, (unsigned) new_flags);
}
static ssize_t store_flags(struct class_device *dev, const char *buf, size_t len)
{
unsigned long new_flags;
char *endp;
int err = 0;
return netdev_store(dev, buf, len, change_flags);
}
new_flags = simple_strtoul(buf, &endp, 16);
if (endp == buf)
return -EINVAL;
static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
if (!capable(CAP_NET_ADMIN))
return -EPERM;
rtnl_lock();
err = dev_change_flags(to_net_dev(dev), new_flags);
rtnl_unlock();
NETDEVICE_SHOW(tx_queue_len, "%lu\n");
return err ? err : len;
static int change_tx_queue_len(struct net_device *net, unsigned long new_len)
{
net->tx_queue_len = new_len;
return 0;
}
static CLASS_DEVICE_ATTR(flags, S_IRUGO | S_IWUSR, show_flags, store_flags);
static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, size_t len)
{
return netdev_store(dev, buf,len, change_tx_queue_len);
}
NETDEVICE_SHOW(tx_queue_len, "%lu\n");
NETDEVICE_STORE(tx_queue_len);
static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
store_tx_queue_len);
......@@ -237,16 +257,17 @@ netstat_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
{
struct netstat_fs_entry *entry
= container_of(attr, struct netstat_fs_entry, attr);
struct class_device *class_dev
= container_of(kobj->parent, struct class_device, kobj);
struct net_device *dev
= to_net_dev(class_dev);
struct net_device_stats *stats
= dev->get_stats ? dev->get_stats(dev) : NULL;
if (stats && entry->show)
return entry->show(stats, buf);
return -EINVAL;
= to_net_dev(to_class_dev(kobj->parent));
struct net_device_stats *stats;
ssize_t ret = -EINVAL;
read_lock(&dev_base_lock);
if (!dev->deadbeaf && entry->show && dev->get_stats &&
(stats = (*dev->get_stats)(dev)))
ret = entry->show(stats, buf);
read_unlock(&dev_base_lock);
return ret;
}
static struct sysfs_ops netstat_sysfs_ops = {
......@@ -278,17 +299,11 @@ int netdev_register_sysfs(struct net_device *net)
goto out_unreg;
}
net->stats_kobj.parent = NULL;
if (net->get_stats) {
struct kobject *k = &net->stats_kobj;
k->parent = kobject_get(&class_dev->kobj);
if (!k->parent) {
ret = -EBUSY;
goto out_unreg;
}
k->parent = &class_dev->kobj;
strlcpy(k->name, "statistics", KOBJ_NAME_LEN);
k->ktype = &netstat_ktype;
......
......@@ -197,7 +197,9 @@ static void inetdev_destroy(struct in_device *in_dev)
/* in_dev_put following below will kill the in_device */
write_unlock_bh(&inetdev_lock);
#ifdef CONFIG_SYSCTL
neigh_sysctl_unregister(in_dev->arp_parms);
#endif
neigh_parms_release(&arp_tbl, in_dev->arp_parms);
in_dev_put(in_dev);
}
......
......@@ -107,10 +107,6 @@ ipt_local_out_hook(unsigned int hook,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
/* FIXME: Push down to extensions --RR */
if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0)
return NF_DROP;
/* root is playing with raw sockets. */
if ((*pskb)->len < sizeof(struct iphdr)
|| (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
......
......@@ -145,10 +145,6 @@ ipt_local_hook(unsigned int hook,
u_int32_t saddr, daddr;
unsigned long nfmark;
/* FIXME: Push down to extensions --RR */
if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0)
return NF_DROP;
/* root is playing with raw sockets. */
if ((*pskb)->len < sizeof(struct iphdr)
|| (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
......
......@@ -1893,10 +1893,11 @@ static int addrconf_ifdown(struct net_device *dev, int how)
/* Shot the device (if unregistered) */
if (how == 1) {
neigh_parms_release(&nd_tbl, idev->nd_parms);
#ifdef CONFIG_SYSCTL
addrconf_sysctl_unregister(&idev->cnf);
neigh_sysctl_unregister(idev->nd_parms);
#endif
neigh_parms_release(&nd_tbl, idev->nd_parms);
in6_dev_put(idev);
}
return 0;
......
......@@ -1210,7 +1210,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
IPV6_TLV_ROUTERALERT, 2, 0, 0,
IPV6_TLV_PADN, 0 };
skb = sock_alloc_send_skb(sk, size + dev->hard_header_len+15, 0, &err);
skb = sock_alloc_send_skb(sk, size + dev->hard_header_len+15, 1, &err);
if (skb == 0)
return 0;
......@@ -1545,7 +1545,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
payload_len = len + sizeof(ra);
full_len = sizeof(struct ipv6hdr) + payload_len;
skb = sock_alloc_send_skb(sk, dev->hard_header_len + full_len + 15, 0, &err);
skb = sock_alloc_send_skb(sk, dev->hard_header_len + full_len + 15, 1, &err);
if (skb == NULL)
return;
......
......@@ -1487,6 +1487,9 @@ int __init ndisc_init(struct net_proto_family *ops)
void ndisc_cleanup(void)
{
#ifdef CONFIG_SYSCTL
neigh_sysctl_unregister(&nd_tbl.parms);
#endif
neigh_table_clear(&nd_tbl);
sock_release(ndisc_socket);
ndisc_socket = NULL; /* For safety. */
......
......@@ -596,10 +596,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
BUG_TRAP(FRAG6_CB(head)->offset == 0);
/* Unfragmented part is taken from the first segment. */
payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len;
nhoff = head->h.raw - head->nh.raw;
if (payload_len > 65535 + 8)
payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len - sizeof(struct frag_hdr);
if (payload_len > 65535)
goto out_oversize;
/* Head of list must not be cloned. */
......@@ -633,9 +631,10 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
* header in order to calculate ICV correctly. */
nhoff = fq->nhoffset;
head->nh.raw[nhoff] = head->h.raw[0];
memmove(head->head+8, head->head, (head->data-head->head)-8);
head->mac.raw += 8;
head->nh.raw += 8;
memmove(head->head + sizeof(struct frag_hdr), head->head,
(head->data - head->head) - sizeof(struct frag_hdr));
head->mac.raw += sizeof(struct frag_hdr);
head->nh.raw += sizeof(struct frag_hdr);
skb_shinfo(head)->frag_list = head->next;
head->h.raw = head->data;
......
......@@ -584,7 +584,7 @@ static struct sock *udp_v6_mcast_next(struct sock *sk,
for (; s; s = s->sk_next) {
struct inet_opt *inet = inet_sk(s);
if (inet->num == num && sk->sk_family == PF_INET6) {
if (inet->num == num && s->sk_family == PF_INET6) {
struct ipv6_pinfo *np = inet6_sk(s);
if (inet->dport) {
if (inet->dport != rmt_port)
......
......@@ -183,7 +183,7 @@ static int llc_seq_core_show(struct seq_file *seq, void *v)
timer_pending(&llc->pf_cycle_timer.timer),
timer_pending(&llc->rej_sent_timer.timer),
timer_pending(&llc->busy_state_timer.timer),
!!sk->sk_backlog.tail, sock_owned_by_user(sk));
!!sk->sk_backlog.tail, !!sock_owned_by_user(sk));
out:
return 0;
}
......
......@@ -190,6 +190,7 @@ EXPORT_SYMBOL(neigh_app_ns);
#endif
#ifdef CONFIG_SYSCTL
EXPORT_SYMBOL(neigh_sysctl_register);
EXPORT_SYMBOL(neigh_sysctl_unregister);
#endif
EXPORT_SYMBOL(pneigh_lookup);
EXPORT_SYMBOL(pneigh_enqueue);
......
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