Commit 3c6bf5ce authored by Linus Torvalds's avatar Linus Torvalds

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

into home.osdl.org:/home/torvalds/v2.5/linux
parents 5ade138f 54cdf53b
......@@ -1632,8 +1632,8 @@ L: linux-scsi@vger.kernel.org
S: Maintained
SCTP PROTOCOL
P: Jon Grimm
M: jgrimm2@us.ibm.com
P: Sridhar Samudrala
M: sri@us.ibm.com
L: lksctp-developers@lists.sourceforge.net
S: Supported
......
......@@ -154,6 +154,8 @@ static struct pci_device_id tg3_pci_tbl[] __devinitdata = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ 0, }
......
......@@ -5832,6 +5832,7 @@
1737 Linksys
173b Altima (nee Broadcom)
03e8 AC1000 Gigabit Ethernet
03e9 AC1001 Gigabit Ethernet
03ea AC9100 Gigabit Ethernet
1743 Peppercon AG
8139 ROL/F-100 Fast Ethernet Adapter with ROL
......
......@@ -16,6 +16,7 @@
#define RTF_DEFAULT 0x00010000 /* default - learned via ND */
#define RTF_ALLONLINK 0x00020000 /* fallback, no routers on link */
#define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */
#define RTF_PREFIX_RT 0x00080000 /* A prefix only route - RA */
#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */
#define RTF_EXPIRES 0x00400000
......
......@@ -33,6 +33,23 @@ struct ebt_counter
uint64_t bcnt;
};
struct ebt_replace
{
char name[EBT_TABLE_MAXNAMELEN];
unsigned int valid_hooks;
/* nr of rules in the table */
unsigned int nentries;
/* total size of the entries */
unsigned int entries_size;
/* start of the chains */
struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
/* nr of counters userspace expects back */
unsigned int num_counters;
/* where the kernel will put the old counters */
struct ebt_counter *counters;
char *entries;
};
struct ebt_entries {
/* this field is always set to zero
* See EBT_ENTRY_OR_ENTRIES.
......@@ -47,7 +64,7 @@ struct ebt_entries {
/* nr. of entries */
unsigned int nentries;
/* entry list */
char data[0];
char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
};
/* used for the bitmask of struct ebt_entry */
......@@ -87,7 +104,7 @@ struct ebt_entry_match
} u;
/* size of data */
unsigned int match_size;
unsigned char data[0];
unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
};
struct ebt_entry_watcher
......@@ -98,7 +115,7 @@ struct ebt_entry_watcher
} u;
/* size of data */
unsigned int watcher_size;
unsigned char data[0];
unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
};
struct ebt_entry_target
......@@ -109,7 +126,7 @@ struct ebt_entry_target
} u;
/* size of data */
unsigned int target_size;
unsigned char data[0];
unsigned char data[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
};
#define EBT_STANDARD_TARGET "standard"
......@@ -143,24 +160,7 @@ struct ebt_entry {
unsigned int target_offset;
/* sizeof ebt_entry + matches + watchers + target */
unsigned int next_offset;
unsigned char elems[0];
};
struct ebt_replace
{
char name[EBT_TABLE_MAXNAMELEN];
unsigned int valid_hooks;
/* nr of rules in the table */
unsigned int nentries;
/* total size of the entries */
unsigned int entries_size;
/* start of the chains */
struct ebt_entries *hook_entry[NF_BR_NUMHOOKS];
/* nr of counters userspace expects back */
unsigned int num_counters;
/* where the kernel will put the old counters */
struct ebt_counter *counters;
char *entries;
unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
};
/* {g,s}etsockopt numbers */
......@@ -263,6 +263,8 @@ struct ebt_table
struct module *me;
};
#define EBT_ALIGN(s) (((s) + (__alignof__(struct ebt_replace)-1)) & \
~(__alignof__(struct ebt_replace)-1))
extern int ebt_register_table(struct ebt_table *table);
extern void ebt_unregister_table(struct ebt_table *table);
extern int ebt_register_match(struct ebt_match *match);
......
......@@ -9,7 +9,8 @@ enum ipt_reject_with {
IPT_ICMP_ECHOREPLY,
IPT_ICMP_NET_PROHIBITED,
IPT_ICMP_HOST_PROHIBITED,
IPT_TCP_RESET
IPT_TCP_RESET,
IPT_ICMP_ADMIN_PROHIBITED
};
struct ipt_reject_info {
......
......@@ -1757,6 +1757,7 @@
#define PCI_VENDOR_ID_ALTIMA 0x173b
#define PCI_DEVICE_ID_ALTIMA_AC1000 0x03e8
#define PCI_DEVICE_ID_ALTIMA_AC1001 0x03e9
#define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea
#define PCI_VENDOR_ID_SYMPHONY 0x1c1c
......
......@@ -168,6 +168,7 @@ enum rt_scope_t
#define RTM_F_NOTIFY 0x100 /* Notify user of route change */
#define RTM_F_CLONED 0x200 /* This route is cloned */
#define RTM_F_EQUALIZE 0x400 /* Multipath equalizer: NI */
#define RTM_F_PREFIX 0x800 /* Prefix addresses */
/* Reserved table identifiers */
......@@ -458,6 +459,40 @@ struct ifinfomsg
unsigned ifi_change; /* IFF_* change mask */
};
/* The struct should be in sync with struct net_device_stats */
struct rtnl_link_stats
{
__u32 rx_packets; /* total packets received */
__u32 tx_packets; /* total packets transmitted */
__u32 rx_bytes; /* total bytes received */
__u32 tx_bytes; /* total bytes transmitted */
__u32 rx_errors; /* bad packets received */
__u32 tx_errors; /* packet transmit problems */
__u32 rx_dropped; /* no space in linux buffers */
__u32 tx_dropped; /* no space available in linux */
__u32 multicast; /* multicast packets received */
__u32 collisions;
/* detailed rx_errors: */
__u32 rx_length_errors;
__u32 rx_over_errors; /* receiver ring buff overflow */
__u32 rx_crc_errors; /* recved pkt with crc error */
__u32 rx_frame_errors; /* recv'd frame alignment error */
__u32 rx_fifo_errors; /* recv'r fifo overrun */
__u32 rx_missed_errors; /* receiver missed packet */
/* detailed tx_errors */
__u32 tx_aborted_errors;
__u32 tx_carrier_errors;
__u32 tx_fifo_errors;
__u32 tx_heartbeat_errors;
__u32 tx_window_errors;
/* for cslip etc */
__u32 rx_compressed;
__u32 tx_compressed;
};
enum
{
IFLA_UNSPEC,
......@@ -599,6 +634,22 @@ extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const voi
({ if (skb_tailroom(skb) < (int)RTA_SPACE(attrlen)) goto rtattr_failure; \
__rta_fill(skb, attrtype, attrlen, data); })
static inline struct rtattr *
__rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
{
struct rtattr *rta;
int size = RTA_LENGTH(attrlen);
rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size));
rta->rta_type = attrtype;
rta->rta_len = size;
return rta;
}
#define __RTA_PUT(skb, attrtype, attrlen) \
({ if (skb_tailroom(skb) < (int)RTA_SPACE(attrlen)) goto rtattr_failure; \
__rta_reserve(skb, attrtype, attrlen); })
extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change);
extern struct semaphore rtnl_sem;
......
......@@ -1031,7 +1031,7 @@ static void lane2_associate_ind (struct net_device *dev, u8 *mac_addr,
#define LEC_ARP_REFRESH_INTERVAL (3*HZ)
static void lec_arp_check_expire(unsigned long data);
static __inline__ void lec_arp_expire_arp(unsigned long data);
static void lec_arp_expire_arp(unsigned long data);
void dump_arp_table(struct lec_priv *priv);
/*
......@@ -1371,7 +1371,7 @@ lec_arp_destroy(struct lec_priv *priv)
struct lec_arp_table *entry, *next;
int i;
del_timer(&priv->lec_arp_timer);
del_timer_sync(&priv->lec_arp_timer);
/*
* Remove all entries
......@@ -1386,7 +1386,7 @@ lec_arp_destroy(struct lec_priv *priv)
entry = priv->lec_arp_empty_ones;
while(entry) {
next = entry->next;
del_timer(&entry->timer);
del_timer_sync(&entry->timer);
lec_arp_clear_vccs(entry);
kfree(entry);
entry = next;
......@@ -1395,7 +1395,7 @@ lec_arp_destroy(struct lec_priv *priv)
entry = priv->lec_no_forward;
while(entry) {
next = entry->next;
del_timer(&entry->timer);
del_timer_sync(&entry->timer);
lec_arp_clear_vccs(entry);
kfree(entry);
entry = next;
......@@ -1404,7 +1404,7 @@ lec_arp_destroy(struct lec_priv *priv)
entry = priv->mcast_fwds;
while(entry) {
next = entry->next;
del_timer(&entry->timer);
/* No timer, LANEv2 7.1.20 and 2.3.5.3 */
lec_arp_clear_vccs(entry);
kfree(entry);
entry = next;
......@@ -1478,8 +1478,6 @@ lec_arp_expire_arp(unsigned long data)
entry = (struct lec_arp_table *)data;
del_timer(&entry->timer);
DPRINTK("lec_arp_expire_arp\n");
if (entry->status == ESI_ARP_PENDING) {
if (entry->no_tries <= entry->priv->max_retry_count) {
......@@ -1489,8 +1487,7 @@ lec_arp_expire_arp(unsigned long data)
send_to_lecd(entry->priv, l_arp_xmt, entry->mac_addr, NULL, NULL);
entry->no_tries++;
}
entry->timer.expires = jiffies + (1*HZ);
add_timer(&entry->timer);
mod_timer(&entry->timer, jiffies + (1*HZ));
}
}
......@@ -1562,8 +1559,6 @@ lec_arp_check_expire(unsigned long data)
unsigned long time_to_check;
int i;
del_timer(&priv->lec_arp_timer);
DPRINTK("lec_arp_check_expire %p,%d\n",priv,
atomic_read(&priv->lec_arp_users));
DPRINTK("expire: eo:%p nf:%p\n",priv->lec_arp_empty_ones,
......@@ -1621,8 +1616,8 @@ lec_arp_check_expire(unsigned long data)
}
lec_arp_put(priv);
}
priv->lec_arp_timer.expires = jiffies + LEC_ARP_REFRESH_INTERVAL;
add_timer(&priv->lec_arp_timer);
mod_timer(&priv->lec_arp_timer, jiffies + LEC_ARP_REFRESH_INTERVAL);
}
/*
* Try to find vcc where mac_address is attached.
......
......@@ -110,23 +110,38 @@ static int br_dev_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
return -1;
}
/* convert later to direct kfree */
static void br_dev_free(struct net_device *dev)
{
struct net_bridge *br = dev->priv;
WARN_ON(!list_empty(&br->port_list));
WARN_ON(!list_empty(&br->age_list));
BUG_ON(timer_pending(&br->hello_timer));
BUG_ON(timer_pending(&br->tcn_timer));
BUG_ON(timer_pending(&br->topology_change_timer));
BUG_ON(timer_pending(&br->gc_timer));
kfree(dev);
}
void br_dev_setup(struct net_device *dev)
{
memset(dev->dev_addr, 0, ETH_ALEN);
ether_setup(dev);
dev->do_ioctl = br_dev_do_ioctl;
dev->get_stats = br_dev_get_stats;
dev->hard_start_xmit = br_dev_xmit;
dev->open = br_dev_open;
dev->set_multicast_list = br_dev_set_multicast_list;
dev->destructor = (void (*)(struct net_device *))kfree;
dev->destructor = br_dev_free;
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);
}
......@@ -41,6 +41,13 @@ static int br_initial_port_cost(struct net_device *dev)
static void destroy_nbp(void *arg)
{
struct net_bridge_port *p = arg;
p->dev->br_port = NULL;
BUG_ON(timer_pending(&p->message_age_timer));
BUG_ON(timer_pending(&p->forward_delay_timer));
BUG_ON(timer_pending(&p->hold_timer));
dev_put(p->dev);
kfree(p);
}
......@@ -53,16 +60,19 @@ static void del_nbp(struct net_bridge_port *p)
br_stp_disable_port(p);
dev_set_promiscuity(dev, -1);
dev->br_port = NULL;
list_del_rcu(&p->list);
br_fdb_delete_by_port(p->br, p);
del_timer(&p->message_age_timer);
del_timer(&p->forward_delay_timer);
del_timer(&p->hold_timer);
call_rcu(&p->rcu, destroy_nbp, p);
}
static void del_ifs(struct net_bridge *br)
static void del_br(struct net_bridge *br)
{
struct list_head *p, *n;
......@@ -71,6 +81,10 @@ static void del_ifs(struct net_bridge *br)
del_nbp(list_entry(p, struct net_bridge_port, list));
}
spin_unlock_bh(&br->lock);
del_timer_sync(&br->gc_timer);
unregister_netdevice(br->dev);
}
static struct net_bridge *new_nb(const char *name)
......@@ -182,15 +196,14 @@ int br_del_bridge(const char *name)
ret = -EBUSY;
}
else {
del_ifs((struct net_bridge *) dev->priv);
unregister_netdevice(dev);
}
else
del_br(dev->priv);
rtnl_unlock();
return ret;
}
/* called under bridge lock */
int br_add_if(struct net_bridge *br, struct net_device *dev)
{
struct net_bridge_port *p;
......@@ -205,7 +218,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
return -ELOOP;
dev_hold(dev);
spin_lock_bh(&br->lock);
if ((p = new_nbp(br, dev)) == NULL) {
spin_unlock_bh(&br->lock);
dev_put(dev);
......@@ -218,26 +230,21 @@ int br_add_if(struct net_bridge *br, struct net_device *dev)
br_fdb_insert(br, p, dev->dev_addr, 1);
if ((br->dev->flags & IFF_UP) && (dev->flags & IFF_UP))
br_stp_enable_port(p);
spin_unlock_bh(&br->lock);
return 0;
}
/* called under bridge lock */
int br_del_if(struct net_bridge *br, struct net_device *dev)
{
struct net_bridge_port *p;
int retval = 0;
spin_lock_bh(&br->lock);
if ((p = dev->br_port) == NULL || p->br != br)
retval = -EINVAL;
else {
del_nbp(p);
br_stp_recalculate_bridge_id(br);
}
spin_unlock_bh(&br->lock);
return -EINVAL;
return retval;
del_nbp(p);
br_stp_recalculate_bridge_id(br);
return 0;
}
int br_get_bridge_ifindices(int *indices, int num)
......@@ -274,13 +281,8 @@ void __exit br_cleanup_bridges(void)
rtnl_lock();
for (dev = dev_base; dev; dev = nxt) {
nxt = dev->next;
if (dev->priv_flags & IFF_EBRIDGE) {
pr_debug("cleanup %s\n", dev->name);
del_ifs((struct net_bridge *) dev->priv);
unregister_netdevice(dev);
}
if (dev->priv_flags & IFF_EBRIDGE)
del_br(dev->priv);
}
rtnl_unlock();
......
......@@ -59,10 +59,12 @@ static int br_ioctl_device(struct net_bridge *br,
if (dev == NULL)
return -EINVAL;
spin_lock_bh(&br->lock);
if (cmd == BRCTL_ADD_IF)
ret = br_add_if(br, dev);
else
ret = br_del_if(br, dev);
spin_unlock_bh(&br->lock);
dev_put(dev);
return ret;
......
......@@ -38,39 +38,27 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
br = p->br;
spin_lock_bh(&br->lock);
switch (event)
{
case NETDEV_CHANGEADDR:
spin_lock_bh(&br->lock);
br_fdb_changeaddr(p, dev->dev_addr);
br_stp_recalculate_bridge_id(br);
spin_unlock_bh(&br->lock);
break;
case NETDEV_GOING_DOWN:
/* extend the protocol to send some kind of notification? */
break;
case NETDEV_DOWN:
if (br->dev->flags & IFF_UP) {
spin_lock_bh(&br->lock);
br_stp_disable_port(p);
spin_unlock_bh(&br->lock);
}
br_stp_disable_port(p);
break;
case NETDEV_UP:
if (!(br->dev->flags & IFF_UP)) {
spin_lock_bh(&br->lock);
br_stp_enable_port(p);
spin_unlock_bh(&br->lock);
}
br_stp_enable_port(p);
break;
case NETDEV_UNREGISTER:
br_del_if(br, dev);
break;
}
spin_unlock_bh(&br->lock);
return NOTIFY_DONE;
}
......@@ -20,7 +20,11 @@
#include "br_private_stp.h"
static const char *br_port_state_names[] = {
"disabled", "learning", "forwarding", "blocking",
[BR_STATE_DISABLED] = "disabled",
[BR_STATE_LISTENING] = "listening",
[BR_STATE_LEARNING] = "learning",
[BR_STATE_FORWARDING] = "forwarding",
[BR_STATE_BLOCKING] = "blocking",
};
void br_log_state(const struct net_bridge_port *p)
......@@ -289,22 +293,20 @@ 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))
return;
int isroot = br_is_root_bridge(br);
pr_info("%s: topology change detected, %s\n", br->dev->name,
isroot ? "propgating" : "sending tcn bpdu");
pr_info("%s: topology change detected", br->dev->name);
if (br_is_root_bridge(br)) {
printk(", propagating");
if (isroot) {
br->topology_change = 1;
mod_timer(&br->topology_change_timer, jiffies
+ br->bridge_forward_delay + br->bridge_max_age);
} else if (!br->topology_change_detected) {
printk(", sending tcn bpdu");
br_transmit_tcn(br);
mod_timer(&br->tcn_timer, jiffies + br->bridge_hello_time);
}
printk("\n");
br->topology_change_detected = 1;
}
......
......@@ -43,8 +43,7 @@ void br_stp_enable_bridge(struct net_bridge *br)
struct net_bridge_port *p;
spin_lock_bh(&br->lock);
br->hello_timer.expires = jiffies + br->hello_time;
add_timer(&br->hello_timer);
mod_timer(&br->hello_timer, jiffies + br->hello_time);
br_config_bpdu_generation(br);
list_for_each_entry(p, &br->port_list, list) {
......@@ -74,8 +73,6 @@ void br_stp_disable_bridge(struct net_bridge *br)
del_timer_sync(&br->hello_timer);
del_timer_sync(&br->topology_change_timer);
del_timer_sync(&br->tcn_timer);
del_timer_sync(&br->gc_timer);
}
/* called under bridge lock */
......
......@@ -43,8 +43,7 @@ static void br_hello_timer_expired(unsigned long arg)
if (br->dev->flags & IFF_UP) {
br_config_bpdu_generation(br);
br->hello_timer.expires = jiffies + br->hello_time;
add_timer(&br->hello_timer);
mod_timer(&br->hello_timer, jiffies + br->hello_time);
}
spin_unlock_bh(&br->lock);
}
......@@ -73,6 +72,8 @@ static void br_message_age_timer_expired(unsigned long arg)
* check is redundant. I'm leaving it in for now, though.
*/
spin_lock_bh(&br->lock);
if (p->state == BR_STATE_DISABLED)
goto unlock;
was_root = br_is_root_bridge(br);
br_become_designated_port(p);
......@@ -80,6 +81,7 @@ static void br_message_age_timer_expired(unsigned long arg)
br_port_state_selection(br);
if (br_is_root_bridge(br) && !was_root)
br_become_root_bridge(br);
unlock:
spin_unlock_bh(&br->lock);
}
......@@ -93,8 +95,8 @@ static void br_forward_delay_timer_expired(unsigned long arg)
spin_lock_bh(&br->lock);
if (p->state == BR_STATE_LISTENING) {
p->state = BR_STATE_LEARNING;
p->forward_delay_timer.expires = jiffies + br->forward_delay;
add_timer(&p->forward_delay_timer);
mod_timer(&p->forward_delay_timer,
jiffies + br->forward_delay);
} else if (p->state == BR_STATE_LEARNING) {
p->state = BR_STATE_FORWARDING;
if (br_is_designated_for_some_port(br))
......@@ -113,8 +115,7 @@ static void br_tcn_timer_expired(unsigned long arg)
if (br->dev->flags & IFF_UP) {
br_transmit_tcn(br);
br->tcn_timer.expires = jiffies + br->bridge_hello_time;
add_timer(&br->tcn_timer);
mod_timer(&br->tcn_timer,jiffies + br->bridge_hello_time);
}
spin_unlock_bh(&br->lock);
}
......
......@@ -99,7 +99,7 @@ static int ebt_arp_check(const char *tablename, unsigned int hookmask,
{
struct ebt_arp_info *info = (struct ebt_arp_info *)data;
if (datalen != sizeof(struct ebt_arp_info))
if (datalen != EBT_ALIGN(sizeof(struct ebt_arp_info)))
return -EINVAL;
if ((e->ethproto != __constant_htons(ETH_P_ARP) &&
e->ethproto != __constant_htons(ETH_P_RARP)) ||
......
......@@ -47,7 +47,7 @@ static int ebt_target_dnat_check(const char *tablename, unsigned int hookmask,
(hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))) &&
(strcmp(tablename, "broute") || hookmask & ~(1 << NF_BR_BROUTING)) )
return -EINVAL;
if (datalen != sizeof(struct ebt_nat_info))
if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
return -EINVAL;
if (INVALID_TARGET)
return -EINVAL;
......
......@@ -75,7 +75,7 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask,
{
struct ebt_ip_info *info = (struct ebt_ip_info *)data;
if (datalen != sizeof(struct ebt_ip_info))
if (datalen != EBT_ALIGN(sizeof(struct ebt_ip_info)))
return -EINVAL;
if (e->ethproto != __constant_htons(ETH_P_IP) ||
e->invflags & EBT_IPROTO)
......
......@@ -22,7 +22,7 @@ static int ebt_log_check(const char *tablename, unsigned int hookmask,
{
struct ebt_log_info *info = (struct ebt_log_info *)data;
if (datalen != sizeof(struct ebt_log_info))
if (datalen != EBT_ALIGN(sizeof(struct ebt_log_info)))
return -EINVAL;
if (info->bitmask & ~EBT_LOG_MASK)
return -EINVAL;
......
......@@ -35,7 +35,7 @@ static int ebt_target_mark_check(const char *tablename, unsigned int hookmask,
{
struct ebt_mark_t_info *info = (struct ebt_mark_t_info *)data;
if (datalen != sizeof(struct ebt_mark_t_info))
if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_t_info)))
return -EINVAL;
if (BASE_CHAIN && info->target == EBT_RETURN)
return -EINVAL;
......
......@@ -28,7 +28,7 @@ static int ebt_mark_check(const char *tablename, unsigned int hookmask,
{
struct ebt_mark_m_info *info = (struct ebt_mark_m_info *) data;
if (datalen != sizeof(struct ebt_mark_m_info))
if (datalen != EBT_ALIGN(sizeof(struct ebt_mark_m_info)))
return -EINVAL;
if (info->bitmask & ~EBT_MARK_MASK)
return -EINVAL;
......
......@@ -28,7 +28,7 @@ static int ebt_pkttype_check(const char *tablename, unsigned int hookmask,
{
struct ebt_pkttype_info *info = (struct ebt_pkttype_info *)data;
if (datalen != sizeof(struct ebt_pkttype_info))
if (datalen != EBT_ALIGN(sizeof(struct ebt_pkttype_info)))
return -EINVAL;
if (info->invert != 0 && info->invert != 1)
return -EINVAL;
......
......@@ -47,7 +47,7 @@ static int ebt_target_redirect_check(const char *tablename, unsigned int hookmas
{
struct ebt_redirect_info *info = (struct ebt_redirect_info *)data;
if (datalen != sizeof(struct ebt_redirect_info))
if (datalen != EBT_ALIGN(sizeof(struct ebt_redirect_info)))
return -EINVAL;
if (BASE_CHAIN && info->target == EBT_RETURN)
return -EINVAL;
......
......@@ -40,7 +40,7 @@ static int ebt_target_snat_check(const char *tablename, unsigned int hookmask,
{
struct ebt_nat_info *info = (struct ebt_nat_info *) data;
if (datalen != sizeof(struct ebt_nat_info))
if (datalen != EBT_ALIGN(sizeof(struct ebt_nat_info)))
return -EINVAL;
if (BASE_CHAIN && info->target == EBT_RETURN)
return -EINVAL;
......
......@@ -150,7 +150,7 @@ static int ebt_stp_check(const char *tablename, unsigned int hookmask,
const struct ebt_entry *e, void *data, unsigned int datalen)
{
struct ebt_stp_info *info = (struct ebt_stp_info *)data;
int len = sizeof(struct ebt_stp_info);
int len = EBT_ALIGN(sizeof(struct ebt_stp_info));
uint8_t bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
uint8_t msk[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
......
......@@ -35,7 +35,7 @@ MODULE_DESCRIPTION("802.1Q match module (ebtables extension), v"
MODULE_LICENSE("GPL");
#define DEBUG_MSG(...) if (debug) printk (KERN_DEBUG "ebt_vlan: " __VA_ARGS__)
#define DEBUG_MSG(args...) if (debug) printk (KERN_DEBUG "ebt_vlan: " args)
#define INV_FLAG(_inv_flag_) (info->invflags & _inv_flag_) ? "!" : ""
#define GET_BITMASK(_BIT_MASK_) info->bitmask & _BIT_MASK_
#define SET_BITMASK(_BIT_MASK_) info->bitmask |= _BIT_MASK_
......@@ -94,7 +94,7 @@ ebt_check_vlan(const char *tablename,
struct ebt_vlan_info *info = (struct ebt_vlan_info *) data;
/* Parameters buffer overflow check */
if (datalen != sizeof(struct ebt_vlan_info)) {
if (datalen != EBT_ALIGN(sizeof(struct ebt_vlan_info))) {
DEBUG_MSG
("passed size %d is not eq to ebt_vlan_info (%Zd)\n",
datalen, sizeof(struct ebt_vlan_info));
......
......@@ -256,10 +256,9 @@ int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
k = X + fentry->k;
goto load_b;
case BPF_LDX|BPF_B|BPF_MSH:
k = fentry->k;
if (k >= 0 && (unsigned int)k >= len)
if (fentry->k >= len)
return 0;
X = (data[k] & 0xf) << 2;
X = (data[fentry->k] & 0xf) << 2;
continue;
case BPF_LD|BPF_IMM:
A = fentry->k;
......
......@@ -186,7 +186,7 @@ struct netstat_fs_entry {
static ssize_t net_device_stat_show(unsigned long var, char *buf)
{
return sprintf(buf, "%ld\n", var);
return sprintf(buf, "%lu\n", var);
}
/* generate a read-only statistics attribute */
......
......@@ -625,66 +625,62 @@ int ip_route_me_harder(struct sk_buff **pskb)
{
struct iphdr *iph = (*pskb)->nh.iph;
struct rtable *rt;
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = iph->daddr,
.saddr = iph->saddr,
.tos = RT_TOS(iph->tos)|RTO_CONN,
#ifdef CONFIG_IP_ROUTE_FWMARK
.fwmark = (*pskb)->nfmark
#endif
} },
.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0,
};
struct net_device *dev_src = NULL;
int err;
/* accommodate ip_route_output_slow(), which expects the key src to be
0 or a local address; however some non-standard hacks like
ipt_REJECT.c:send_reset() can cause packets with foreign
saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */
if(fl.fl4_src && !(dev_src = ip_dev_find(fl.fl4_src)))
fl.fl4_src = 0;
if ((err=ip_route_output_key(&rt, &fl)) != 0) {
printk("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %d\n",
NIPQUAD(iph->daddr), NIPQUAD(iph->saddr),
(*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0,
RT_TOS(iph->tos)|RTO_CONN,
struct flowi fl = {};
struct dst_entry *odst;
unsigned int hh_len;
/* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
* packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook.
*/
if (inet_addr_type(iph->saddr) == RTN_LOCAL) {
fl.nl_u.ip4_u.daddr = iph->daddr;
fl.nl_u.ip4_u.saddr = iph->saddr;
fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
#ifdef CONFIG_IP_ROUTE_FWMARK
(*pskb)->nfmark,
#else
0UL,
fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
#endif
err);
goto out;
}
if (ip_route_output_key(&rt, &fl) != 0)
return -1;
/* Drop old route. */
dst_release((*pskb)->dst);
(*pskb)->dst = &rt->u.dst;
/* Drop old route. */
dst_release((*pskb)->dst);
(*pskb)->dst = &rt->u.dst;
} else {
/* non-local src, find valid iif to satisfy
* rp-filter when calling ip_route_input. */
fl.nl_u.ip4_u.daddr = iph->saddr;
if (ip_route_output_key(&rt, &fl) != 0)
return -1;
odst = (*pskb)->dst;
if (ip_route_input(*pskb, iph->daddr, iph->saddr,
RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
dst_release(&rt->u.dst);
return -1;
}
dst_release(&rt->u.dst);
dst_release(odst);
}
if ((*pskb)->dst->error)
return -1;
/* Change in oif may mean change in hh_len. */
if (skb_headroom(*pskb) < (*pskb)->dst->dev->hard_header_len) {
hh_len = (*pskb)->dst->dev->hard_header_len;
if (skb_headroom(*pskb) < hh_len) {
struct sk_buff *nskb;
nskb = skb_realloc_headroom(*pskb,
(*pskb)->dst->dev->hard_header_len);
if (!nskb) {
err = -ENOMEM;
goto out;
}
nskb = skb_realloc_headroom(*pskb, hh_len);
if (!nskb)
return -1;
if ((*pskb)->sk)
skb_set_owner_w(nskb, (*pskb)->sk);
kfree_skb(*pskb);
*pskb = nskb;
}
out:
if (dev_src)
dev_put(dev_src);
return err;
return 0;
}
int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
......
......@@ -47,6 +47,9 @@
* Also moved to /proc/net/pktgen/
* --ro
*
* Fix refcount off by one if first packet fails, potential null deref,
* memleak 030710- KJP
*
* See Documentation/networking/pktgen.txt for how to use this.
*/
......@@ -85,9 +88,9 @@
#define cycles() ((u32)get_cycles())
#define VERSION "pktgen version 1.2"
#define VERSION "pktgen version 1.3"
static char version[] __initdata =
"pktgen.c: v1.2: Packet Generator for packet performance testing.\n";
"pktgen.c: v1.3: Packet Generator for packet performance testing.\n";
/* Used to help with determining the pkts on receive */
......@@ -611,12 +614,11 @@ static void inject(struct pktgen_info* info)
kfree_skb(skb);
skb = fill_packet(odev, info);
if (skb == NULL) {
break;
goto out_reldev;
}
fp++;
fp_tmp = 0; /* reset counter */
}
atomic_inc(&skb->users);
}
nr_frags = skb_shinfo(skb)->nr_frags;
......@@ -624,7 +626,11 @@ static void inject(struct pktgen_info* info)
spin_lock_bh(&odev->xmit_lock);
if (!netif_queue_stopped(odev)) {
atomic_inc(&skb->users);
if (odev->hard_start_xmit(skb, odev)) {
atomic_dec(&skb->users);
if (net_ratelimit()) {
printk(KERN_INFO "Hard xmit error\n");
}
......@@ -729,15 +735,15 @@ static void inject(struct pktgen_info* info)
(unsigned long long) info->errors
);
}
kfree_skb(skb);
out_reldev:
if (odev) {
dev_put(odev);
odev = NULL;
}
/* TODO: Is this worth printing out (other than for debug?) */
printk("fp = %llu\n", (unsigned long long) fp);
return;
}
......@@ -953,7 +959,8 @@ static int proc_write(struct file *file, const char *user_buffer,
if (len < 0)
return len;
memset(name, 0, sizeof(name));
copy_from_user(name, &user_buffer[i], len);
if (copy_from_user(name, &user_buffer[i], len))
return -EFAULT;
i += len;
max = count -i;
......@@ -1083,18 +1090,20 @@ static int proc_write(struct file *file, const char *user_buffer,
if (len < 0)
return len;
memset(info->outdev, 0, sizeof(info->outdev));
copy_from_user(info->outdev, &user_buffer[i], len);
if (copy_from_user(info->outdev, &user_buffer[i], len))
return -EFAULT;
i += len;
sprintf(result, "OK: odev=%s", info->outdev);
return count;
}
if (!strcmp(name, "flag")) {
char f[32];
memset(f, 0, 32);
len = strn_len(&user_buffer[i], sizeof(f) - 1);
if (len < 0)
return len;
copy_from_user(f, &user_buffer[i], len);
memset(f, 0, 32);
if (copy_from_user(f, &user_buffer[i], len))
return -EFAULT;
i += len;
if (strcmp(f, "IPSRC_RND") == 0) {
info->flags |= F_IPSRC_RND;
......@@ -1146,7 +1155,8 @@ static int proc_write(struct file *file, const char *user_buffer,
if (len < 0)
return len;
memset(info->dst_min, 0, sizeof(info->dst_min));
copy_from_user(info->dst_min, &user_buffer[i], len);
if (copy_from_user(info->dst_min, &user_buffer[i], len))
return -EFAULT;
if(debug)
printk("pg: dst_min set to: %s\n", info->dst_min);
i += len;
......@@ -1158,7 +1168,8 @@ static int proc_write(struct file *file, const char *user_buffer,
if (len < 0)
return len;
memset(info->dst_max, 0, sizeof(info->dst_max));
copy_from_user(info->dst_max, &user_buffer[i], len);
if (copy_from_user(info->dst_max, &user_buffer[i], len))
return -EFAULT;
if(debug)
printk("pg: dst_max set to: %s\n", info->dst_max);
i += len;
......@@ -1170,7 +1181,8 @@ static int proc_write(struct file *file, const char *user_buffer,
if (len < 0)
return len;
memset(info->src_min, 0, sizeof(info->src_min));
copy_from_user(info->src_min, &user_buffer[i], len);
if (copy_from_user(info->src_min, &user_buffer[i], len))
return -EFAULT;
if(debug)
printk("pg: src_min set to: %s\n", info->src_min);
i += len;
......@@ -1182,7 +1194,8 @@ static int proc_write(struct file *file, const char *user_buffer,
if (len < 0)
return len;
memset(info->src_max, 0, sizeof(info->src_max));
copy_from_user(info->src_max, &user_buffer[i], len);
if (copy_from_user(info->src_max, &user_buffer[i], len))
return -EFAULT;
if(debug)
printk("pg: src_max set to: %s\n", info->src_max);
i += len;
......@@ -1197,7 +1210,8 @@ static int proc_write(struct file *file, const char *user_buffer,
if (len < 0)
return len;
memset(valstr, 0, sizeof(valstr));
copy_from_user(valstr, &user_buffer[i], len);
if (copy_from_user(valstr, &user_buffer[i], len))
return -EFAULT;
i += len;
for(*m = 0;*v && m < info->dst_mac + 6; v++) {
......@@ -1229,7 +1243,8 @@ static int proc_write(struct file *file, const char *user_buffer,
if (len < 0)
return len;
memset(valstr, 0, sizeof(valstr));
copy_from_user(valstr, &user_buffer[i], len);
if (copy_from_user(valstr, &user_buffer[i], len))
return -EFAULT;
i += len;
for(*m = 0;*v && m < info->src_mac + 6; v++) {
......
......@@ -191,9 +191,18 @@ static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
if (dev->master)
RTA_PUT(skb, IFLA_MASTER, sizeof(int), &dev->master->ifindex);
if (dev->get_stats) {
struct net_device_stats *stats = dev->get_stats(dev);
if (stats)
RTA_PUT(skb, IFLA_STATS, sizeof(*stats), stats);
unsigned long *stats = (unsigned long*)dev->get_stats(dev);
if (stats) {
struct rtattr *a;
__u32 *s;
int i;
int n = sizeof(struct rtnl_link_stats)/4;
a = __RTA_PUT(skb, IFLA_STATS, n*4);
s = RTA_DATA(a);
for (i=0; i<n; i++)
s[i] = stats[i];
}
}
nlh->nlmsg_len = skb->tail - b;
return skb->len;
......
......@@ -86,7 +86,7 @@ ctl_table core_table[] = {
{
.ctl_name = NET_CORE_NO_CONG_THRESH,
.procname = "no_cong_thresh",
.data = &no_cong,
.data = &no_cong_thresh,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
......
......@@ -2308,6 +2308,7 @@ static int dn_socket_seq_open(struct inode *inode, struct file *file)
}
static struct file_operations dn_socket_seq_fops = {
.owner = THIS_MODULE,
.open = dn_socket_seq_open,
.read = seq_read,
.llseek = seq_lseek,
......
......@@ -1443,6 +1443,7 @@ static int dn_dev_seq_open(struct inode *inode, struct file *file)
}
static struct file_operations dn_dev_seq_fops = {
.owner = THIS_MODULE,
.open = dn_dev_seq_open,
.read = seq_read,
.llseek = seq_lseek,
......
......@@ -1766,6 +1766,7 @@ static int dn_rt_cache_seq_open(struct inode *inode, struct file *file)
}
static struct file_operations dn_rt_cache_seq_fops = {
.owner = THIS_MODULE,
.open = dn_rt_cache_seq_open,
.read = seq_read,
.llseek = seq_lseek,
......
......@@ -1313,7 +1313,7 @@ void __init ip_init(void)
ip_rt_init();
inet_initpeers();
#ifdef CONFIG_IP_MULTICAST
#if defined(CONFIG_IP_MULTICAST) && defined(CONFIG_PROC_FS)
igmp_mc_proc_init();
#endif
}
......@@ -251,7 +251,7 @@ static void unexpect_related(struct ip_conntrack_expect *expect)
}
/* delete all unconfirmed expectations for this conntrack */
static void remove_expectations(struct ip_conntrack *ct)
static void remove_expectations(struct ip_conntrack *ct, int drop_refcount)
{
struct list_head *exp_entry, *next;
struct ip_conntrack_expect *exp;
......@@ -266,8 +266,11 @@ static void remove_expectations(struct ip_conntrack *ct)
* the un-established ones only */
if (exp->sibling) {
DEBUGP("remove_expectations: skipping established %p of %p\n", exp->sibling, ct);
/* Indicate that this expectations parent is dead */
exp->expectant = NULL;
if (drop_refcount) {
/* Indicate that this expectations parent is dead */
ip_conntrack_put(exp->expectant);
exp->expectant = NULL;
}
continue;
}
......@@ -292,7 +295,7 @@ clean_from_lists(struct ip_conntrack *ct)
&ct->tuplehash[IP_CT_DIR_REPLY]);
/* Destroy all un-established, pending expectations */
remove_expectations(ct);
remove_expectations(ct, 1);
}
static void
......@@ -1117,7 +1120,7 @@ static inline int unhelp(struct ip_conntrack_tuple_hash *i,
{
if (i->ctrack->helper == me) {
/* Get rid of any expected. */
remove_expectations(i->ctrack);
remove_expectations(i->ctrack, 0);
/* And *then* set helper to NULL */
i->ctrack->helper = NULL;
}
......
......@@ -54,7 +54,7 @@ MODULE_PARM_DESC(dcc_timeout, "timeout on for unestablished DCC channels");
#endif
static char *dccprotos[] = { "SEND ", "CHAT ", "MOVE ", "TSEND ", "SCHAT " };
#define MAXMATCHLEN 6
#define MINMATCHLEN 5
DECLARE_LOCK(ip_irc_lock);
struct module *ip_conntrack_irc = THIS_MODULE;
......@@ -87,9 +87,11 @@ int parse_dcc(char *data, char *data_end, u_int32_t * ip, u_int16_t * port,
*ip = simple_strtoul(data, &data, 10);
/* skip blanks between ip and port */
while (*data == ' ')
while (*data == ' ') {
if (data >= data_end)
return -1;
data++;
}
*port = simple_strtoul(data, &data, 10);
*ad_end_p = data;
......@@ -139,13 +141,17 @@ static int help(struct sk_buff *skb,
data = irc_buffer;
data_limit = irc_buffer + skb->len - dataoff;
while (data < (data_limit - (22 + MAXMATCHLEN))) {
/* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24
* 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
while (data < (data_limit - (19 + MINMATCHLEN))) {
if (memcmp(data, "\1DCC ", 5)) {
data++;
continue;
}
data += 5;
/* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
NIPQUAD(iph->saddr), ntohs(tcph.source),
......@@ -159,6 +165,9 @@ static int help(struct sk_buff *skb,
DEBUGP("DCC %s detected\n", dccprotos[i]);
data += strlen(dccprotos[i]);
/* we have at least
* (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
* data left (== 14/13 bytes) */
if (parse_dcc((char *)data, data_limit, &dcc_ip,
&dcc_port, &addr_beg_p, &addr_end_p)) {
/* unable to parse */
......
......@@ -9,6 +9,12 @@
Changes:
25 Aug 2001 Harald Welte <laforge@gnumonks.org>
- decrement and check TTL if not called from FORWARD hook
18 Jul 2003 Harald Welte <laforge@netfilter.org>
- merge Patrick McHardy's mirror fixes from 2.4.22 to
2.6.0-test1
19 Jul 2003 Harald Welte <laforge@netfilter.org>
- merge Patrick McHardy's rp_filter fixes from 2.4.22 to
2.6.0-test1
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
......@@ -32,7 +38,6 @@
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netdevice.h>
#include <linux/route.h>
struct in_device;
#include <net/route.h>
#if 0
......@@ -41,46 +46,58 @@ struct in_device;
#define DEBUGP(format, args...)
#endif
static int route_mirror(struct sk_buff *skb)
static inline struct rtable *route_mirror(struct sk_buff *skb, int local)
{
struct iphdr *iph = skb->nh.iph;
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->saddr,
.saddr = iph->daddr,
.tos = RT_TOS(iph->tos) | RTO_CONN } } };
struct dst_entry *odst;
struct flowi fl = {};
struct rtable *rt;
/* Backwards */
if (ip_route_output_key(&rt, &fl)) {
return 0;
if (local) {
fl.nl_u.ip4_u.daddr = iph->saddr;
fl.nl_u.ip4_u.saddr = iph->daddr;
fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
if (ip_route_output_key(&rt, &fl) != 0)
return NULL;
} else {
/* non-local src, find valid iif to satisfy
* rp-filter when calling ip_route_input(). */
fl.nl_u.ip4_u.daddr = iph->daddr;
if (ip_route_output_key(&rt, &fl) != 0)
return NULL;
odst = skb->dst;
if (ip_route_input(skb, iph->saddr, iph->daddr,
RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
dst_release(&rt->u.dst);
return NULL;
}
dst_release(&rt->u.dst);
rt = (struct rtable *)skb->dst;
skb->dst = odst;
}
/* check if the interface we are leaving by is the same as the
one we arrived on */
if (skb->dev == rt->u.dst.dev) {
/* Drop old route. */
dst_release(skb->dst);
skb->dst = &rt->u.dst;
return 1;
if (rt->u.dst.error) {
dst_release(&rt->u.dst);
rt = NULL;
}
return 0;
return rt;
}
static int ip_rewrite(struct sk_buff **pskb)
static inline void ip_rewrite(struct sk_buff *skb)
{
u32 odaddr, osaddr;
if (!skb_ip_make_writable(pskb, sizeof(struct iphdr)))
return 0;
odaddr = skb->nh.iph->saddr;
osaddr = skb->nh.iph->daddr;
odaddr = (*pskb)->nh.iph->saddr;
osaddr = (*pskb)->nh.iph->daddr;
(*pskb)->nfcache |= NFC_ALTERED;
skb->nfcache |= NFC_ALTERED;
/* Rewrite IP header */
(*pskb)->nh.iph->daddr = odaddr;
(*pskb)->nh.iph->saddr = osaddr;
return 1;
skb->nh.iph->daddr = odaddr;
skb->nh.iph->saddr = osaddr;
}
/* Stolen from ip_finish_output2 */
......@@ -113,31 +130,51 @@ static unsigned int ipt_mirror_target(struct sk_buff **pskb,
const void *targinfo,
void *userinfo)
{
if (((*pskb)->dst != NULL) && route_mirror(*pskb)) {
if (!ip_rewrite(pskb))
return NF_DROP;
struct rtable *rt;
struct sk_buff *nskb;
unsigned int hh_len;
/* If we are not at FORWARD hook (INPUT/PREROUTING),
* the TTL isn't decreased by the IP stack */
if (hooknum != NF_IP_FORWARD) {
if ((*pskb)->nh.iph->ttl <= 1) {
/* this will traverse normal stack, and
* thus call conntrack on the icmp packet */
icmp_send(*pskb, ICMP_TIME_EXCEEDED,
ICMP_EXC_TTL, 0);
return NF_DROP;
}
/* Made writable by ip_rewrite */
ip_decrease_ttl((*pskb)->nh.iph);
/* Make skb writable */
if (!skb_ip_make_writable(pskb, sizeof(struct iphdr)))
return 0;
/* If we are not at FORWARD hook (INPUT/PREROUTING),
* the TTL isn't decreased by the IP stack */
if (hooknum != NF_IP_FORWARD) {
if ((*pskb)->nh.iph->ttl <= 1) {
/* this will traverse normal stack, and
* thus call conntrack on the icmp packet */
icmp_send(*pskb, ICMP_TIME_EXCEEDED,
ICMP_EXC_TTL, 0);
return NF_DROP;
}
ip_decrease_ttl((*pskb)->nh.iph);
}
/* Don't let conntrack code see this packet:
it will think we are starting a new
connection! --RR */
ip_direct_send(*pskb);
if ((rt = route_mirror(*pskb, hooknum == NF_IP_LOCAL_IN)) == NULL)
return NF_DROP;
return NF_STOLEN;
hh_len = (rt->u.dst.dev->hard_header_len + 15) & ~15;
/* Copy skb (even if skb is about to be dropped, we can't just
* clone it because there may be other things, such as tcpdump,
* interested in it). We also need to expand headroom in case
* hh_len of incoming interface < hh_len of outgoing interface */
nskb = skb_copy_expand(*pskb, hh_len, skb_tailroom(*pskb), GFP_ATOMIC);
if (nskb == NULL) {
dst_release(&rt->u.dst);
return NF_DROP;
}
dst_release(nskb->dst);
nskb->dst = &rt->u.dst;
ip_rewrite(nskb);
/* Don't let conntrack code see this packet:
* it will think we are starting a new
* connection! --RR */
ip_direct_send(nskb);
return NF_DROP;
}
......
This diff is collapsed.
......@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_helper.h>
......@@ -34,6 +35,7 @@ match(const struct sk_buff *skb,
struct ip_conntrack_expect *exp;
struct ip_conntrack *ct;
enum ip_conntrack_info ctinfo;
int ret = 0;
ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
if (!ct) {
......@@ -47,23 +49,27 @@ match(const struct sk_buff *skb,
}
exp = ct->master;
READ_LOCK(&ip_conntrack_lock);
if (!exp->expectant) {
DEBUGP("ipt_helper: expectation %p without expectant !?!\n",
exp);
return 0;
goto out_unlock;
}
if (!exp->expectant->helper) {
DEBUGP("ipt_helper: master ct %p has no helper\n",
exp->expectant);
return 0;
goto out_unlock;
}
DEBUGP("master's name = %s , info->name = %s\n",
exp->expectant->helper->name, info->name);
return !strncmp(exp->expectant->helper->name, info->name,
strlen(exp->expectant->helper->name)) ^ info->invert;
ret = !strncmp(exp->expectant->helper->name, info->name,
strlen(exp->expectant->helper->name)) ^ info->invert;
out_unlock:
READ_UNLOCK(&ip_conntrack_lock);
return ret;
}
static int check(const char *tablename,
......
......@@ -130,7 +130,7 @@ static spinlock_t addrconf_verify_lock = SPIN_LOCK_UNLOCKED;
static int addrconf_ifdown(struct net_device *dev, int how);
static void addrconf_dad_start(struct inet6_ifaddr *ifp);
static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
static void addrconf_dad_timer(unsigned long data);
static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
static void addrconf_rs_timer(unsigned long data);
......@@ -710,7 +710,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
ift->prefered_lft = tmp_prefered_lft;
ift->tstamp = ifp->tstamp;
spin_unlock_bh(&ift->lock);
addrconf_dad_start(ift);
addrconf_dad_start(ift, 0);
in6_ifa_put(ift);
in6_dev_put(idev);
out:
......@@ -1247,7 +1247,7 @@ static void addrconf_add_mroute(struct net_device *dev)
rtmsg.rtmsg_dst_len = 8;
rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
rtmsg.rtmsg_ifindex = dev->ifindex;
rtmsg.rtmsg_flags = RTF_UP|RTF_ADDRCONF;
rtmsg.rtmsg_flags = RTF_UP;
rtmsg.rtmsg_type = RTMSG_NEWROUTE;
ip6_route_add(&rtmsg, NULL, NULL);
}
......@@ -1274,7 +1274,7 @@ static void addrconf_add_lroute(struct net_device *dev)
struct in6_addr addr;
ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0);
addrconf_prefix_route(&addr, 64, dev, 0, RTF_ADDRCONF);
addrconf_prefix_route(&addr, 64, dev, 0, 0);
}
static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
......@@ -1367,7 +1367,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
}
} else if (valid_lft) {
addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES);
dev, rt_expires, RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT);
}
if (rt)
dst_release(&rt->u.dst);
......@@ -1413,7 +1413,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
}
update_lft = create = 1;
addrconf_dad_start(ifp);
addrconf_dad_start(ifp, RTF_ADDRCONF|RTF_PREFIX_RT);
}
if (ifp) {
......@@ -1586,7 +1586,7 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen)
ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT);
if (!IS_ERR(ifp)) {
addrconf_dad_start(ifp);
addrconf_dad_start(ifp, 0);
in6_ifa_put(ifp);
return 0;
}
......@@ -1761,7 +1761,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr
ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, IFA_F_PERMANENT);
if (!IS_ERR(ifp)) {
addrconf_dad_start(ifp);
addrconf_dad_start(ifp, 0);
in6_ifa_put(ifp);
}
}
......@@ -2021,8 +2021,7 @@ static void addrconf_rs_timer(unsigned long data)
memset(&rtmsg, 0, sizeof(struct in6_rtmsg));
rtmsg.rtmsg_type = RTMSG_NEWROUTE;
rtmsg.rtmsg_metric = IP6_RT_PRIO_ADDRCONF;
rtmsg.rtmsg_flags = (RTF_ALLONLINK | RTF_ADDRCONF |
RTF_DEFAULT | RTF_UP);
rtmsg.rtmsg_flags = (RTF_ALLONLINK | RTF_DEFAULT | RTF_UP);
rtmsg.rtmsg_ifindex = ifp->idev->dev->ifindex;
......@@ -2036,7 +2035,7 @@ static void addrconf_rs_timer(unsigned long data)
/*
* Duplicate Address Detection
*/
static void addrconf_dad_start(struct inet6_ifaddr *ifp)
static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags)
{
struct net_device *dev;
unsigned long rand_num;
......@@ -2046,7 +2045,8 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp)
addrconf_join_solict(dev, &ifp->addr);
if (ifp->prefix_len != 128 && (ifp->flags&IFA_F_PERMANENT))
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, 0, RTF_ADDRCONF);
addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, 0,
flags);
net_srandom(ifp->addr.s6_addr32[3]);
rand_num = net_random() % (ifp->idev->cnf.rtr_solicit_delay ? : 1);
......
......@@ -1459,13 +1459,20 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
struct in6_addr *src,
int iif,
int type, u32 pid, u32 seq,
struct nlmsghdr *in_nlh)
struct nlmsghdr *in_nlh, int prefix)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
struct rta_cacheinfo ci;
if (prefix) { /* user wants prefix routes only */
if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
/* success since this is not a prefix route */
return 1;
}
}
if (!pid && in_nlh) {
pid = in_nlh->nlmsg_pid;
}
......@@ -1546,10 +1553,17 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
static int rt6_dump_route(struct rt6_info *rt, void *p_arg)
{
struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg;
struct rtmsg *rtm;
int prefix;
rtm = NLMSG_DATA(arg->cb->nlh);
if (rtm)
prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0;
else prefix = 0;
return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
NULL);
NULL, prefix);
}
static int fib6_dump_node(struct fib6_walker_t *w)
......@@ -1697,7 +1711,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
&fl.fl6_dst, &fl.fl6_src,
iif,
RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
nlh->nlmsg_seq, nlh);
nlh->nlmsg_seq, nlh, 0);
if (err < 0) {
err = -EMSGSIZE;
goto out_free;
......@@ -1723,7 +1737,7 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh)
netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
return;
}
if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh) < 0) {
if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh, 0) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
return;
......
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