Commit 7867b36d authored by David S. Miller's avatar David S. Miller

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

into kernel.bkbits.net:/home/davem/net-2.5
parents 21347414 98bcb391
...@@ -723,6 +723,12 @@ struct xfrm_algo_desc { ...@@ -723,6 +723,12 @@ struct xfrm_algo_desc {
struct sadb_alg desc; struct sadb_alg desc;
}; };
/* XFRM tunnel handlers. */
struct xfrm_tunnel {
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, void *info);
};
extern void xfrm_init(void); extern void xfrm_init(void);
extern void xfrm4_init(void); extern void xfrm4_init(void);
extern void xfrm4_fini(void); extern void xfrm4_fini(void);
...@@ -752,6 +758,8 @@ extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); ...@@ -752,6 +758,8 @@ extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl); extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl);
extern int xfrm4_rcv(struct sk_buff *skb); extern int xfrm4_rcv(struct sk_buff *skb);
extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler);
extern int xfrm6_rcv(struct sk_buff **pskb); extern int xfrm6_rcv(struct sk_buff **pskb);
extern int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir); extern int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir);
extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen); extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen);
......
...@@ -84,17 +84,20 @@ static int br_ioctl_device(struct net_bridge *br, ...@@ -84,17 +84,20 @@ static int br_ioctl_device(struct net_bridge *br,
case BRCTL_GET_PORT_LIST: case BRCTL_GET_PORT_LIST:
{ {
int i; int *indices;
int indices[256]; int ret = 0;
for (i=0;i<256;i++) indices = kmalloc(256*sizeof(int), GFP_KERNEL);
indices[i] = 0; if (indices == NULL)
return -ENOMEM;
memset(indices, 0, 256*sizeof(int));
br_get_port_ifindices(br, indices); br_get_port_ifindices(br, indices);
if (copy_to_user((void *)arg0, indices, 256*sizeof(int))) if (copy_to_user((void *)arg0, indices, 256*sizeof(int)))
return -EFAULT; ret = -EFAULT;
kfree(indices);
return 0; return ret;
} }
case BRCTL_SET_BRIDGE_FORWARD_DELAY: case BRCTL_SET_BRIDGE_FORWARD_DELAY:
...@@ -212,19 +215,24 @@ static int br_ioctl_deviceless(unsigned int cmd, ...@@ -212,19 +215,24 @@ static int br_ioctl_deviceless(unsigned int cmd,
case BRCTL_GET_BRIDGES: case BRCTL_GET_BRIDGES:
{ {
int i; int *indices;
int indices[64]; int ret = 0;
for (i=0;i<64;i++)
indices[i] = 0;
if (arg1 > 64) if (arg1 > 64)
arg1 = 64; arg1 = 64;
indices = kmalloc(arg1*sizeof(int), GFP_KERNEL);
if (indices == NULL)
return -ENOMEM;
memset(indices, 0, arg1*sizeof(int));
arg1 = br_get_bridge_ifindices(indices, arg1); arg1 = br_get_bridge_ifindices(indices, arg1);
if (copy_to_user((void *)arg0, indices, arg1*sizeof(int)))
return -EFAULT;
return arg1; ret = copy_to_user((void *)arg0, indices, arg1*sizeof(int))
? -EFAULT : arg1;
kfree(indices);
return ret;
} }
case BRCTL_ADD_BRIDGE: case BRCTL_ADD_BRIDGE:
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/netfilter_bridge/ebtables.h> #include <linux/netfilter_bridge/ebtables.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include <linux/brlock.h>
/* EBT_ACCEPT means the frame will be bridged /* EBT_ACCEPT means the frame will be bridged
* EBT_DROP means the frame will be routed * EBT_DROP means the frame will be routed
...@@ -70,18 +69,15 @@ static int __init init(void) ...@@ -70,18 +69,15 @@ static int __init init(void)
ret = ebt_register_table(&broute_table); ret = ebt_register_table(&broute_table);
if (ret < 0) if (ret < 0)
return ret; return ret;
br_write_lock_bh(BR_NETPROTO_LOCK);
/* see br_input.c */ /* see br_input.c */
br_should_route_hook = ebt_broute; br_should_route_hook = ebt_broute;
br_write_unlock_bh(BR_NETPROTO_LOCK);
return ret; return ret;
} }
static void __exit fini(void) static void __exit fini(void)
{ {
br_write_lock_bh(BR_NETPROTO_LOCK);
br_should_route_hook = NULL; br_should_route_hook = NULL;
br_write_unlock_bh(BR_NETPROTO_LOCK); synchronize_net();
ebt_unregister_table(&broute_table); ebt_unregister_table(&broute_table);
} }
......
...@@ -22,4 +22,4 @@ obj-$(CONFIG_INET_IPCOMP) += ipcomp.o ...@@ -22,4 +22,4 @@ obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
obj-$(CONFIG_IP_PNP) += ipconfig.o obj-$(CONFIG_IP_PNP) += ipconfig.o
obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_NETFILTER) += netfilter/
obj-y += xfrm4_policy.o xfrm4_state.o xfrm4_input.o obj-y += xfrm4_policy.o xfrm4_state.o xfrm4_input.o xfrm4_tunnel.o
...@@ -1161,12 +1161,14 @@ void ip_mc_down(struct in_device *in_dev) ...@@ -1161,12 +1161,14 @@ void ip_mc_down(struct in_device *in_dev)
ASSERT_RTNL(); ASSERT_RTNL();
#ifdef CONFIG_IP_MULTICAST
in_dev->mr_ifc_count = 0; in_dev->mr_ifc_count = 0;
if (del_timer(&in_dev->mr_ifc_timer)) if (del_timer(&in_dev->mr_ifc_timer))
atomic_dec(&in_dev->refcnt); atomic_dec(&in_dev->refcnt);
in_dev->mr_gq_running = 0; in_dev->mr_gq_running = 0;
if (del_timer(&in_dev->mr_gq_timer)) if (del_timer(&in_dev->mr_gq_timer))
atomic_dec(&in_dev->refcnt); atomic_dec(&in_dev->refcnt);
#endif
for (i=in_dev->mc_list; i; i=i->next) for (i=in_dev->mc_list; i; i=i->next)
igmp_group_dropped(i); igmp_group_dropped(i);
...@@ -1185,7 +1187,6 @@ void ip_mc_up(struct in_device *in_dev) ...@@ -1185,7 +1187,6 @@ void ip_mc_up(struct in_device *in_dev)
ASSERT_RTNL(); ASSERT_RTNL();
#ifdef CONFIG_IP_MULTICAST #ifdef CONFIG_IP_MULTICAST
in_dev->mc_lock = RW_LOCK_UNLOCKED;
in_dev->mr_gq_running = 0; in_dev->mr_gq_running = 0;
init_timer(&in_dev->mr_gq_timer); init_timer(&in_dev->mr_gq_timer);
in_dev->mr_gq_timer.data=(unsigned long) in_dev; in_dev->mr_gq_timer.data=(unsigned long) in_dev;
...@@ -1198,6 +1199,7 @@ void ip_mc_up(struct in_device *in_dev) ...@@ -1198,6 +1199,7 @@ void ip_mc_up(struct in_device *in_dev)
in_dev->mr_qrv = IGMP_Unsolicited_Report_Count; in_dev->mr_qrv = IGMP_Unsolicited_Report_Count;
#endif #endif
in_dev->mc_lock = RW_LOCK_UNLOCKED;
ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS); ip_mc_inc_group(in_dev, IGMP_ALL_HOSTS);
for (i=in_dev->mc_list; i; i=i->next) for (i=in_dev->mc_list; i; i=i->next)
......
...@@ -115,6 +115,7 @@ ...@@ -115,6 +115,7 @@
#include <net/protocol.h> #include <net/protocol.h>
#include <net/ipip.h> #include <net/ipip.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
#include <net/xfrm.h>
#define HASH_SIZE 16 #define HASH_SIZE 16
#define HASH(addr) ((addr^(addr>>4))&0xF) #define HASH(addr) ((addr^(addr>>4))&0xF)
...@@ -285,7 +286,7 @@ static void ipip_tunnel_uninit(struct net_device *dev) ...@@ -285,7 +286,7 @@ static void ipip_tunnel_uninit(struct net_device *dev)
dev_put(dev); dev_put(dev);
} }
void ipip_err(struct sk_buff *skb, u32 info) void ipip_err(struct sk_buff *skb, void *__unused)
{ {
#ifndef I_WISH_WORLD_WERE_PERFECT #ifndef I_WISH_WORLD_WERE_PERFECT
...@@ -468,11 +469,13 @@ void ipip_err(struct sk_buff *skb, u32 info) ...@@ -468,11 +469,13 @@ void ipip_err(struct sk_buff *skb, u32 info)
#endif #endif
} }
static inline void ipip_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb)
{ {
if (INET_ECN_is_ce(iph->tos) && struct iphdr *inner_iph = skb->nh.iph;
INET_ECN_is_not_ce(skb->nh.iph->tos))
IP_ECN_set_ce(iph); if (INET_ECN_is_ce(outer_iph->tos) &&
INET_ECN_is_not_ce(inner_iph->tos))
IP_ECN_set_ce(inner_iph);
} }
int ipip_rcv(struct sk_buff *skb) int ipip_rcv(struct sk_buff *skb)
...@@ -511,10 +514,8 @@ int ipip_rcv(struct sk_buff *skb) ...@@ -511,10 +514,8 @@ int ipip_rcv(struct sk_buff *skb)
} }
read_unlock(&ipip_lock); read_unlock(&ipip_lock);
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PROT_UNREACH, 0);
out: out:
kfree_skb(skb); return -1;
return 0;
} }
/* /*
...@@ -867,7 +868,7 @@ int __init ipip_fb_tunnel_init(struct net_device *dev) ...@@ -867,7 +868,7 @@ int __init ipip_fb_tunnel_init(struct net_device *dev)
return 0; return 0;
} }
static struct inet_protocol ipip_protocol = { static struct xfrm_tunnel ipip_handler = {
.handler = ipip_rcv, .handler = ipip_rcv,
.err_handler = ipip_err, .err_handler = ipip_err,
}; };
...@@ -879,8 +880,8 @@ int __init ipip_init(void) ...@@ -879,8 +880,8 @@ int __init ipip_init(void)
{ {
printk(banner); printk(banner);
if (inet_add_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) { if (xfrm4_tunnel_register(&ipip_handler) < 0) {
printk(KERN_INFO "ipip init: can't add protocol\n"); printk(KERN_INFO "ipip init: can't register tunnel\n");
return -EAGAIN; return -EAGAIN;
} }
...@@ -892,8 +893,8 @@ int __init ipip_init(void) ...@@ -892,8 +893,8 @@ int __init ipip_init(void)
static void __exit ipip_fini(void) static void __exit ipip_fini(void)
{ {
if (inet_del_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) if (xfrm4_tunnel_deregister(&ipip_handler) < 0)
printk(KERN_INFO "ipip close: can't remove protocol\n"); printk(KERN_INFO "ipip close: can't deregister tunnel\n");
unregister_netdev(&ipip_fb_tunnel_dev); unregister_netdev(&ipip_fb_tunnel_dev);
} }
......
/* xfrm4_tunnel.c: Generic IP tunnel transformer.
*
* Copyright (C) 2003 David S. Miller (davem@redhat.com)
*/
#include <linux/skbuff.h>
#include <net/xfrm.h>
#include <net/ip.h>
#include <net/icmp.h>
#include <net/inet_ecn.h>
static int ipip_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
struct iphdr *iph, *top_iph;
int tos;
iph = skb->nh.iph;
spin_lock_bh(&x->lock);
tos = iph->tos;
top_iph = (struct iphdr *) skb_push(skb, x->props.header_len);
top_iph->ihl = 5;
top_iph->version = 4;
top_iph->tos = INET_ECN_encapsulate(tos, iph->tos);
top_iph->tot_len = htons(skb->len);
top_iph->frag_off = iph->frag_off & ~htons(IP_MF|IP_OFFSET);
if (!(iph->frag_off & htons(IP_DF)))
__ip_select_ident(top_iph, dst, 0);
top_iph->ttl = iph->ttl;
top_iph->protocol = IPPROTO_IPIP;
top_iph->check = 0;
top_iph->saddr = x->props.saddr.a4;
top_iph->daddr = x->id.daddr.a4;
memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
ip_send_check(top_iph);
skb->nh.raw = skb->data;
x->curlft.bytes += skb->len;
x->curlft.packets++;
spin_unlock_bh(&x->lock);
if ((skb->dst = dst_pop(dst)) == NULL) {
kfree_skb(skb);
return -EHOSTUNREACH;
}
return NET_XMIT_BYPASS;
}
static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb)
{
struct iphdr *inner_iph = skb->nh.iph;
if (INET_ECN_is_ce(outer_iph->tos) &&
INET_ECN_is_not_ce(inner_iph->tos))
IP_ECN_set_ce(inner_iph);
}
static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
{
struct iphdr *outer_iph = skb->nh.iph;
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
return -EINVAL;
skb->mac.raw = skb->nh.raw;
skb->nh.raw = skb->data;
memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
dst_release(skb->dst);
skb->dst = NULL;
skb->protocol = htons(ETH_P_IP);
skb->pkt_type = PACKET_HOST;
ipip_ecn_decapsulate(outer_iph, skb);
netif_rx(skb);
return 0;
}
static struct xfrm_tunnel *ipip_handler;
static DECLARE_MUTEX(xfrm4_tunnel_sem);
int xfrm4_tunnel_register(struct xfrm_tunnel *handler)
{
int ret;
down(&xfrm4_tunnel_sem);
ret = 0;
if (ipip_handler != NULL)
ret = -EINVAL;
if (!ret)
ipip_handler = handler;
up(&xfrm4_tunnel_sem);
return ret;
}
int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
{
int ret;
down(&xfrm4_tunnel_sem);
ret = 0;
if (ipip_handler != handler)
ret = -EINVAL;
if (!ret)
ipip_handler = NULL;
up(&xfrm4_tunnel_sem);
synchronize_net();
return ret;
}
static int ipip_rcv(struct sk_buff *skb)
{
struct xfrm_tunnel *handler = ipip_handler;
struct xfrm_state *x = NULL;
int err;
/* Tunnel devices take precedence. */
if (handler) {
err = handler->handler(skb);
if (!err)
goto out;
}
x = xfrm_state_lookup((xfrm_address_t *)&skb->nh.iph->daddr,
skb->nh.iph->saddr,
IPPROTO_IPIP, AF_INET);
if (x) {
spin_lock(&x->lock);
if (unlikely(x->km.state != XFRM_STATE_VALID))
goto drop_unlock;
}
err = ipip_xfrm_rcv(x, NULL, skb);
if (err)
goto drop_unlock;
if (x) {
x->curlft.bytes += skb->len;
x->curlft.packets++;
spin_unlock(&x->lock);
xfrm_state_put(x);
}
return 0;
drop_unlock:
if (x) {
spin_unlock(&x->lock);
xfrm_state_put(x);
}
kfree_skb(skb);
out:
return 0;
}
void ipip_err(struct sk_buff *skb, u32 info)
{
struct xfrm_tunnel *handler = ipip_handler;
u32 arg = info;
if (handler)
handler->err_handler(skb, &arg);
}
static int ipip_init_state(struct xfrm_state *x, void *args)
{
x->props.header_len = sizeof(struct iphdr);
return 0;
}
static void ipip_destroy(struct xfrm_state *x)
{
}
static struct xfrm_type ipip_type = {
.description = "IPIP",
.proto = IPPROTO_IPIP,
.init_state = ipip_init_state,
.destructor = ipip_destroy,
.input = ipip_xfrm_rcv,
.output = ipip_output
};
static struct inet_protocol ipip_protocol = {
.handler = ipip_rcv,
.err_handler = ipip_err,
};
static int __init ipip_init(void)
{
SET_MODULE_OWNER(&ipip_type);
if (xfrm_register_type(&ipip_type, AF_INET) < 0) {
printk(KERN_INFO "ipip init: can't add xfrm type\n");
return -EAGAIN;
}
if (inet_add_protocol(&ipip_protocol, IPPROTO_IPIP) < 0) {
printk(KERN_INFO "ipip init: can't add protocol\n");
xfrm_unregister_type(&ipip_type, AF_INET);
return -EAGAIN;
}
return 0;
}
static void __exit ipip_fini(void)
{
if (inet_del_protocol(&ipip_protocol, IPPROTO_IPIP) < 0)
printk(KERN_INFO "ipip close: can't remove protocol\n");
if (xfrm_unregister_type(&ipip_type, AF_INET) < 0)
printk(KERN_INFO "ipip close: can't remove xfrm type\n");
}
module_init(ipip_init);
module_exit(ipip_fini);
MODULE_LICENSE("GPL");
...@@ -318,6 +318,8 @@ EXPORT_SYMBOL(__secpath_destroy); ...@@ -318,6 +318,8 @@ EXPORT_SYMBOL(__secpath_destroy);
EXPORT_SYMBOL(xfrm_get_acqseq); EXPORT_SYMBOL(xfrm_get_acqseq);
EXPORT_SYMBOL(xfrm_parse_spi); EXPORT_SYMBOL(xfrm_parse_spi);
EXPORT_SYMBOL(xfrm4_rcv); EXPORT_SYMBOL(xfrm4_rcv);
EXPORT_SYMBOL(xfrm4_tunnel_register);
EXPORT_SYMBOL(xfrm4_tunnel_deregister);
EXPORT_SYMBOL(xfrm_register_type); EXPORT_SYMBOL(xfrm_register_type);
EXPORT_SYMBOL(xfrm_unregister_type); EXPORT_SYMBOL(xfrm_unregister_type);
EXPORT_SYMBOL(xfrm_get_type); EXPORT_SYMBOL(xfrm_get_type);
......
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