Commit 0eb8fea5 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 a0b2fc70 b53f295e
...@@ -379,6 +379,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr) ...@@ -379,6 +379,7 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
tun->owner = -1; tun->owner = -1;
tun->dev.init = tun_net_init; tun->dev.init = tun_net_init;
tun->dev.priv = tun; tun->dev.priv = tun;
tun->dev.owner = THIS_MODULE;
err = -EINVAL; err = -EINVAL;
...@@ -402,8 +403,6 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr) ...@@ -402,8 +403,6 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
if ((err = register_netdevice(&tun->dev))) if ((err = register_netdevice(&tun->dev)))
goto failed; goto failed;
MOD_INC_USE_COUNT;
tun->name = tun->dev.name; tun->name = tun->dev.name;
} }
...@@ -553,7 +552,6 @@ static int tun_chr_close(struct inode *inode, struct file *file) ...@@ -553,7 +552,6 @@ static int tun_chr_close(struct inode *inode, struct file *file)
dev_close(&tun->dev); dev_close(&tun->dev);
unregister_netdevice(&tun->dev); unregister_netdevice(&tun->dev);
kfree(tun); kfree(tun);
MOD_DEC_USE_COUNT;
} }
rtnl_unlock(); rtnl_unlock();
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#include <linux/jiffies.h>
#include <net/neighbour.h> #include <net/neighbour.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -208,7 +209,7 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout) ...@@ -208,7 +209,7 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
if (expires == 0) if (expires == 0)
expires = 1; expires = 1;
if (dst->expires == 0 || (long)(dst->expires - expires) > 0) if (dst->expires == 0 || time_before(expires, dst->expires))
dst->expires = expires; dst->expires = expires;
} }
......
...@@ -44,15 +44,17 @@ struct inet_protocol ...@@ -44,15 +44,17 @@ struct inet_protocol
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
struct inet6_protocol struct inet6_protocol
{ {
int (*handler)(struct sk_buff **skbp); int (*handler)(struct sk_buff **skb, unsigned int *nhoffp);
void (*err_handler)(struct sk_buff *skb, void (*err_handler)(struct sk_buff *skb,
struct inet6_skb_parm *opt, struct inet6_skb_parm *opt,
int type, int code, int offset, int type, int code, int offset,
__u32 info); __u32 info);
int no_policy; unsigned int flags; /* INET6_PROTO_xxx */
}; };
#define INET6_PROTO_NOPOLICY 0x1
#define INET6_PROTO_FINAL 0x2
#endif #endif
/* This is used to register socket interfaces for IP protocols. */ /* This is used to register socket interfaces for IP protocols. */
......
...@@ -453,7 +453,7 @@ extern void sock_def_destruct(struct sock *); ...@@ -453,7 +453,7 @@ extern void sock_def_destruct(struct sock *);
extern void sock_init_data(struct socket *sock, struct sock *sk); extern void sock_init_data(struct socket *sock, struct sock *sk);
/** /**
* __sk_filter - run a packet through a socket filter * sk_filter - run a packet through a socket filter
* @sk: sock associated with &sk_buff * @sk: sock associated with &sk_buff
* @skb: buffer to filter * @skb: buffer to filter
* @needlock: set to 1 if the sock is not locked by caller. * @needlock: set to 1 if the sock is not locked by caller.
...@@ -464,14 +464,16 @@ extern void sock_init_data(struct socket *sock, struct sock *sk); ...@@ -464,14 +464,16 @@ extern void sock_init_data(struct socket *sock, struct sock *sk);
* wrapper to sk_run_filter. It returns 0 if the packet should * wrapper to sk_run_filter. It returns 0 if the packet should
* be accepted or -EPERM if the packet should be tossed. * be accepted or -EPERM if the packet should be tossed.
* *
* This function should not be called directly, use sk_filter instead
* to ensure that the LSM security check is also performed.
*/ */
static inline int __sk_filter(struct sock *sk, struct sk_buff *skb, int needlock) static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
{ {
int err = 0; int err;
err = security_sock_rcv_skb(sk, skb);
if (err)
return err;
if (sk->filter) { if (sk->filter) {
struct sk_filter *filter; struct sk_filter *filter;
...@@ -518,17 +520,6 @@ static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp) ...@@ -518,17 +520,6 @@ static inline void sk_filter_charge(struct sock *sk, struct sk_filter *fp)
atomic_add(sk_filter_len(fp), &sk->omem_alloc); atomic_add(sk_filter_len(fp), &sk->omem_alloc);
} }
static inline int sk_filter(struct sock *sk, struct sk_buff *skb, int needlock)
{
int err;
err = security_sock_rcv_skb(sk, skb);
if (err)
return err;
return __sk_filter(sk, skb, needlock);
}
/* /*
* Socket reference counting postulates. * Socket reference counting postulates.
* *
......
...@@ -760,7 +760,7 @@ extern int xfrm4_rcv(struct sk_buff *skb); ...@@ -760,7 +760,7 @@ 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_register(struct xfrm_tunnel *handler);
extern int xfrm4_tunnel_deregister(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, unsigned int *nhoffp);
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);
......
...@@ -805,7 +805,6 @@ static int __init inet6_init(void) ...@@ -805,7 +805,6 @@ static int __init inet6_init(void)
sit_init(); sit_init();
/* Init v6 extension headers. */ /* Init v6 extension headers. */
ipv6_hopopts_init();
ipv6_rthdr_init(); ipv6_rthdr_init();
ipv6_frag_init(); ipv6_frag_init();
ipv6_nodata_init(); ipv6_nodata_init();
......
...@@ -330,7 +330,7 @@ static struct xfrm_type ah6_type = ...@@ -330,7 +330,7 @@ static struct xfrm_type ah6_type =
static struct inet6_protocol ah6_protocol = { static struct inet6_protocol ah6_protocol = {
.handler = xfrm6_rcv, .handler = xfrm6_rcv,
.err_handler = ah6_err, .err_handler = ah6_err,
.no_policy = 1, .flags = INET6_PROTO_NOPOLICY,
}; };
int __init ah6_init(void) int __init ah6_init(void)
......
...@@ -501,7 +501,7 @@ static struct xfrm_type esp6_type = ...@@ -501,7 +501,7 @@ static struct xfrm_type esp6_type =
static struct inet6_protocol esp6_protocol = { static struct inet6_protocol esp6_protocol = {
.handler = xfrm6_rcv, .handler = xfrm6_rcv,
.err_handler = esp6_err, .err_handler = esp6_err,
.no_policy = 1, .flags = INET6_PROTO_NOPOLICY,
}; };
int __init esp6_init(void) int __init esp6_init(void)
......
...@@ -18,9 +18,9 @@ ...@@ -18,9 +18,9 @@
/* Changes: /* Changes:
* yoshfuji : ensure not to overrun while parsing * yoshfuji : ensure not to overrun while parsing
* tlv options. * tlv options.
* Mitsuru KANDA @USAGI : Remove ipv6_parse_exthdrs(). * Mitsuru KANDA @USAGI and: Remove ipv6_parse_exthdrs().
* : Register inbound extention header * YOSHIFUJI Hideaki @USAGI Register inbound extention header
* : handlers as inet6_protocol{}. * handlers as inet6_protocol{}.
*/ */
#include <linux/errno.h> #include <linux/errno.h>
...@@ -153,38 +153,37 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = { ...@@ -153,38 +153,37 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = {
{-1, NULL} {-1, NULL}
}; };
static int ipv6_destopt_rcv(struct sk_buff **skbp) static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
{ {
struct sk_buff *skb = *skbp; struct sk_buff *skb = *skbp;
struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
u8 nexthdr = 0;
if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
kfree_skb(skb); kfree_skb(skb);
return 0; return -1;
} }
nexthdr = ((struct ipv6_destopt_hdr *)skb->h.raw)->nexthdr;
opt->dst1 = skb->h.raw - skb->nh.raw; opt->dst1 = skb->h.raw - skb->nh.raw;
if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
skb->h.raw += ((skb->h.raw[1]+1)<<3); skb->h.raw += ((skb->h.raw[1]+1)<<3);
return -nexthdr; *nhoffp = opt->dst1;
return 1;
} }
return 0; return -1;
} }
static struct inet6_protocol destopt_protocol = static struct inet6_protocol destopt_protocol =
{ {
.handler = ipv6_destopt_rcv, .handler = ipv6_destopt_rcv,
.flags = INET6_PROTO_NOPOLICY,
}; };
void __init ipv6_destopt_init(void) void __init ipv6_destopt_init(void)
{ {
if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0) if (inet6_add_protocol(&destopt_protocol, IPPROTO_DSTOPTS) < 0)
printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n"); printk(KERN_ERR "ipv6_destopt_init: Could not register protocol\n");
} }
...@@ -192,7 +191,7 @@ void __init ipv6_destopt_init(void) ...@@ -192,7 +191,7 @@ void __init ipv6_destopt_init(void)
NONE header. No data in packet. NONE header. No data in packet.
********************************/ ********************************/
static int ipv6_nodata_rcv(struct sk_buff **skbp) static int ipv6_nodata_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
{ {
struct sk_buff *skb = *skbp; struct sk_buff *skb = *skbp;
...@@ -203,6 +202,7 @@ static int ipv6_nodata_rcv(struct sk_buff **skbp) ...@@ -203,6 +202,7 @@ static int ipv6_nodata_rcv(struct sk_buff **skbp)
static struct inet6_protocol nodata_protocol = static struct inet6_protocol nodata_protocol =
{ {
.handler = ipv6_nodata_rcv, .handler = ipv6_nodata_rcv,
.flags = INET6_PROTO_NOPOLICY,
}; };
void __init ipv6_nodata_init(void) void __init ipv6_nodata_init(void)
...@@ -215,7 +215,7 @@ void __init ipv6_nodata_init(void) ...@@ -215,7 +215,7 @@ void __init ipv6_nodata_init(void)
Routing header. Routing header.
********************************/ ********************************/
static int ipv6_rthdr_rcv(struct sk_buff **skbp) static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
{ {
struct sk_buff *skb = *skbp; struct sk_buff *skb = *skbp;
struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb;
...@@ -223,7 +223,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -223,7 +223,6 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
struct in6_addr daddr; struct in6_addr daddr;
int addr_type; int addr_type;
int n, i; int n, i;
u8 nexthdr = 0;
struct ipv6_rt_hdr *hdr; struct ipv6_rt_hdr *hdr;
struct rt0_hdr *rthdr; struct rt0_hdr *rthdr;
...@@ -232,16 +231,15 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -232,16 +231,15 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
IP6_INC_STATS_BH(Ip6InHdrErrors); IP6_INC_STATS_BH(Ip6InHdrErrors);
kfree_skb(skb); kfree_skb(skb);
return 0; return -1;
} }
hdr = (struct ipv6_rt_hdr *) skb->h.raw; hdr = (struct ipv6_rt_hdr *) skb->h.raw;
nexthdr = hdr->nexthdr;
if ((ipv6_addr_type(&skb->nh.ipv6h->daddr)&IPV6_ADDR_MULTICAST) || if ((ipv6_addr_type(&skb->nh.ipv6h->daddr)&IPV6_ADDR_MULTICAST) ||
skb->pkt_type != PACKET_HOST) { skb->pkt_type != PACKET_HOST) {
kfree_skb(skb); kfree_skb(skb);
return 0; return -1;
} }
looped_back: looped_back:
...@@ -250,12 +248,13 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -250,12 +248,13 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
skb->h.raw += (hdr->hdrlen + 1) << 3; skb->h.raw += (hdr->hdrlen + 1) << 3;
opt->dst0 = opt->dst1; opt->dst0 = opt->dst1;
opt->dst1 = 0; opt->dst1 = 0;
return -nexthdr; *nhoffp = (&hdr->nexthdr) - skb->nh.raw;
return 1;
} }
if (hdr->type != IPV6_SRCRT_TYPE_0 || (hdr->hdrlen & 0x01)) { if (hdr->type != IPV6_SRCRT_TYPE_0 || (hdr->hdrlen & 0x01)) {
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, hdr->type != IPV6_SRCRT_TYPE_0 ? 2 : 1); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, hdr->type != IPV6_SRCRT_TYPE_0 ? 2 : 1);
return 0; return -1;
} }
/* /*
...@@ -267,7 +266,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -267,7 +266,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
if (hdr->segments_left > n) { if (hdr->segments_left > n) {
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->segments_left) - skb->nh.raw);
return 0; return -1;
} }
/* We are about to mangle packet header. Be careful! /* We are about to mangle packet header. Be careful!
...@@ -277,7 +276,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -277,7 +276,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC); struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
kfree_skb(skb); kfree_skb(skb);
if (skb2 == NULL) if (skb2 == NULL)
return 0; return -1;
*skbp = skb = skb2; *skbp = skb = skb2;
opt = (struct inet6_skb_parm *)skb2->cb; opt = (struct inet6_skb_parm *)skb2->cb;
hdr = (struct ipv6_rt_hdr *) skb2->h.raw; hdr = (struct ipv6_rt_hdr *) skb2->h.raw;
...@@ -296,7 +295,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -296,7 +295,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
if (addr_type&IPV6_ADDR_MULTICAST) { if (addr_type&IPV6_ADDR_MULTICAST) {
kfree_skb(skb); kfree_skb(skb);
return 0; return -1;
} }
ipv6_addr_copy(&daddr, addr); ipv6_addr_copy(&daddr, addr);
...@@ -307,26 +306,27 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp) ...@@ -307,26 +306,27 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp)
ip6_route_input(skb); ip6_route_input(skb);
if (skb->dst->error) { if (skb->dst->error) {
dst_input(skb); dst_input(skb);
return 0; return -1;
} }
if (skb->dst->dev->flags&IFF_LOOPBACK) { if (skb->dst->dev->flags&IFF_LOOPBACK) {
if (skb->nh.ipv6h->hop_limit <= 1) { if (skb->nh.ipv6h->hop_limit <= 1) {
icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT, icmpv6_send(skb, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
0, skb->dev); 0, skb->dev);
kfree_skb(skb); kfree_skb(skb);
return 0; return -1;
} }
skb->nh.ipv6h->hop_limit--; skb->nh.ipv6h->hop_limit--;
goto looped_back; goto looped_back;
} }
dst_input(skb); dst_input(skb);
return 0; return -1;
} }
static struct inet6_protocol rthdr_protocol = static struct inet6_protocol rthdr_protocol =
{ {
.handler = ipv6_rthdr_rcv, .handler = ipv6_rthdr_rcv,
.flags = INET6_PROTO_NOPOLICY,
}; };
void __init ipv6_rthdr_init(void) void __init ipv6_rthdr_init(void)
...@@ -470,34 +470,6 @@ int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff) ...@@ -470,34 +470,6 @@ int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
return -1; return -1;
} }
/* This is fake. We have already parsed hopopts in ipv6_rcv(). -mk */
static int ipv6_hopopts_rcv(struct sk_buff **skbp)
{
struct sk_buff *skb = *skbp;
u8 nexthdr = 0;
if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) ||
!pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) {
kfree_skb(skb);
return 0;
}
nexthdr = ((struct ipv6_hopopt_hdr *)skb->h.raw)->nexthdr;
skb->h.raw += (skb->h.raw[1]+1)<<3;
return -nexthdr;
}
static struct inet6_protocol hopopts_protocol =
{
.handler = ipv6_hopopts_rcv,
};
void __init ipv6_hopopts_init(void)
{
if (inet6_add_protocol(&hopopts_protocol, IPPROTO_HOPOPTS) < 0)
printk(KERN_ERR "ipv6_hopopts_init: Could not register protocol\n");
}
/* /*
* Creating outbound headers. * Creating outbound headers.
* *
......
...@@ -74,10 +74,11 @@ DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); ...@@ -74,10 +74,11 @@ DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
static struct socket *__icmpv6_socket[NR_CPUS]; static struct socket *__icmpv6_socket[NR_CPUS];
#define icmpv6_socket __icmpv6_socket[smp_processor_id()] #define icmpv6_socket __icmpv6_socket[smp_processor_id()]
static int icmpv6_rcv(struct sk_buff **pskb); static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp);
static struct inet6_protocol icmpv6_protocol = { static struct inet6_protocol icmpv6_protocol = {
.handler = icmpv6_rcv, .handler = icmpv6_rcv,
.flags = INET6_PROTO_FINAL,
}; };
struct icmpv6_msg { struct icmpv6_msg {
...@@ -459,7 +460,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info) ...@@ -459,7 +460,7 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
* Handle icmp messages * Handle icmp messages
*/ */
static int icmpv6_rcv(struct sk_buff **pskb) static int icmpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
{ {
struct sk_buff *skb = *pskb; struct sk_buff *skb = *pskb;
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
......
...@@ -17,7 +17,8 @@ ...@@ -17,7 +17,8 @@
*/ */
/* Changes /* Changes
* *
* Mitsuru KANDA @USAGI : Remove ipv6_parse_exthdrs(). * Mitsuru KANDA @USAGI and
* YOSHIFUJI Hideaki @USAGI: Remove ipv6_parse_exthdrs().
*/ */
#include <linux/errno.h> #include <linux/errno.h>
...@@ -128,22 +129,34 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ...@@ -128,22 +129,34 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
static inline int ip6_input_finish(struct sk_buff *skb) static inline int ip6_input_finish(struct sk_buff *skb)
{ {
struct ipv6hdr *hdr = skb->nh.ipv6h;
struct inet6_protocol *ipprot; struct inet6_protocol *ipprot;
struct sock *raw_sk; struct sock *raw_sk;
int nexthdr = hdr->nexthdr; unsigned int nhoff;
int nexthdr;
u8 hash; u8 hash;
int cksum_sub = 0;
skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr); skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
if (!pskb_pull(skb, skb->h.raw - skb->data)) /*
goto discard; * Parse extension headers
*/
if (skb->ip_summed == CHECKSUM_HW) nexthdr = skb->nh.ipv6h->nexthdr;
skb->csum = csum_sub(skb->csum, nhoff = offsetof(struct ipv6hdr, nexthdr);
csum_partial(skb->nh.raw, skb->h.raw-skb->nh.raw, 0));
/* Skip hop-by-hop options, they are already parsed. */
if (nexthdr == NEXTHDR_HOP) {
nhoff = sizeof(struct ipv6hdr);
nexthdr = skb->h.raw[0];
skb->h.raw += (skb->h.raw[1]+1)<<3;
}
resubmit: resubmit:
if (!pskb_pull(skb, skb->h.raw - skb->data))
goto discard;
nexthdr = skb->nh.raw[nhoff];
raw_sk = raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)]; raw_sk = raw_v6_htable[nexthdr & (MAX_INET_PROTOS - 1)];
if (raw_sk) if (raw_sk)
ipv6_raw_deliver(skb, nexthdr); ipv6_raw_deliver(skb, nexthdr);
...@@ -152,23 +165,29 @@ static inline int ip6_input_finish(struct sk_buff *skb) ...@@ -152,23 +165,29 @@ static inline int ip6_input_finish(struct sk_buff *skb)
if ((ipprot = inet6_protos[hash]) != NULL) { if ((ipprot = inet6_protos[hash]) != NULL) {
int ret; int ret;
if (!ipprot->no_policy && if (ipprot->flags & INET6_PROTO_FINAL) {
if (!cksum_sub && skb->ip_summed == CHECKSUM_HW) {
skb->csum = csum_sub(skb->csum,
csum_partial(skb->nh.raw, skb->h.raw-skb->nh.raw, 0));
cksum_sub++;
}
}
if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
} }
ret = ipprot->handler(&skb);
if (ret < 0) { ret = ipprot->handler(&skb, &nhoff);
nexthdr = -ret; if (ret > 0)
goto resubmit; goto resubmit;
} else if (ret == 0)
IP6_INC_STATS_BH(Ip6InDelivers); IP6_INC_STATS_BH(Ip6InDelivers);
} else { } else {
if (!raw_sk) { if (!raw_sk) {
if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) { if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
IP6_INC_STATS_BH(Ip6InUnknownProtos); IP6_INC_STATS_BH(Ip6InUnknownProtos);
icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, nhoff);
offsetof(struct ipv6hdr, nexthdr));
} }
} else { } else {
IP6_INC_STATS_BH(Ip6InDelivers); IP6_INC_STATS_BH(Ip6InDelivers);
......
...@@ -154,6 +154,7 @@ int ip6_route_me_harder(struct sk_buff *skb) ...@@ -154,6 +154,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
if (dst->error) { if (dst->error) {
if (net_ratelimit()) if (net_ratelimit())
printk(KERN_DEBUG "ip6_route_me_harder: No more route.\n"); printk(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
dst_release(dst);
return -EINVAL; return -EINVAL;
} }
......
...@@ -520,13 +520,13 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, ...@@ -520,13 +520,13 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
* the last and the first frames arrived and all the bits are here. * the last and the first frames arrived and all the bits are here.
*/ */
static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
unsigned int *nhoffp,
struct net_device *dev) struct net_device *dev)
{ {
struct sk_buff *fp, *head = fq->fragments; struct sk_buff *fp, *head = fq->fragments;
int remove_fraghdr = 0; int remove_fraghdr = 0;
int payload_len; int payload_len;
int nhoff; unsigned int nhoff;
u8 nexthdr = 0;
fq_kill(fq); fq_kill(fq);
...@@ -537,8 +537,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, ...@@ -537,8 +537,6 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len; payload_len = (head->data - head->nh.raw) - sizeof(struct ipv6hdr) + fq->len;
nhoff = head->h.raw - head->nh.raw; nhoff = head->h.raw - head->nh.raw;
nexthdr = ((struct frag_hdr*)head->h.raw)->nexthdr;
if (payload_len > 65535) { if (payload_len > 65535) {
payload_len -= 8; payload_len -= 8;
if (payload_len > 65535) if (payload_len > 65535)
...@@ -613,12 +611,10 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, ...@@ -613,12 +611,10 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
if (head->ip_summed == CHECKSUM_HW) if (head->ip_summed == CHECKSUM_HW)
head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum); head->csum = csum_partial(head->nh.raw, head->h.raw-head->nh.raw, head->csum);
if (!pskb_pull(head, head->h.raw - head->data))
goto out_fail;
IP6_INC_STATS_BH(Ip6ReasmOKs); IP6_INC_STATS_BH(Ip6ReasmOKs);
fq->fragments = NULL; fq->fragments = NULL;
return nexthdr; *nhoffp = nhoff;
return 1;
out_oversize: out_oversize:
if (net_ratelimit()) if (net_ratelimit())
...@@ -629,18 +625,16 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in, ...@@ -629,18 +625,16 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n"); printk(KERN_DEBUG "ip6_frag_reasm: no memory for reassembly\n");
out_fail: out_fail:
IP6_INC_STATS_BH(Ip6ReasmFails); IP6_INC_STATS_BH(Ip6ReasmFails);
return 0; return -1;
} }
static int ipv6_frag_rcv(struct sk_buff **skbp) static int ipv6_frag_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
{ {
struct sk_buff *skb = *skbp; struct sk_buff *skb = *skbp;
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
struct frag_hdr *fhdr; struct frag_hdr *fhdr;
struct frag_queue *fq; struct frag_queue *fq;
struct ipv6hdr *hdr; struct ipv6hdr *hdr;
int nhoff = skb->h.raw - skb->nh.raw;
u8 nexthdr = 0;
hdr = skb->nh.ipv6h; hdr = skb->nh.ipv6h;
...@@ -649,23 +643,23 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) ...@@ -649,23 +643,23 @@ static int ipv6_frag_rcv(struct sk_buff **skbp)
/* Jumbo payload inhibits frag. header */ /* Jumbo payload inhibits frag. header */
if (hdr->payload_len==0) { if (hdr->payload_len==0) {
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw);
goto discard; return -1;
} }
if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) { if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+sizeof(struct frag_hdr))) {
icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw); icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw-skb->nh.raw);
goto discard; return -1;
} }
hdr = skb->nh.ipv6h; hdr = skb->nh.ipv6h;
fhdr = (struct frag_hdr *)skb->h.raw; fhdr = (struct frag_hdr *)skb->h.raw;
nexthdr = fhdr->nexthdr;
if (!(fhdr->frag_off & htons(0xFFF9))) { if (!(fhdr->frag_off & htons(0xFFF9))) {
/* It is not a fragmented frame */ /* It is not a fragmented frame */
skb->h.raw += sizeof(struct frag_hdr); skb->h.raw += sizeof(struct frag_hdr);
IP6_INC_STATS_BH(Ip6ReasmOKs); IP6_INC_STATS_BH(Ip6ReasmOKs);
return (u8*)fhdr - skb->nh.raw; *nhoffp = (u8*)fhdr - skb->nh.raw;
return 1;
} }
if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh) if (atomic_read(&ip6_frag_mem) > sysctl_ip6frag_high_thresh)
...@@ -676,26 +670,26 @@ static int ipv6_frag_rcv(struct sk_buff **skbp) ...@@ -676,26 +670,26 @@ static int ipv6_frag_rcv(struct sk_buff **skbp)
spin_lock(&fq->lock); spin_lock(&fq->lock);
ip6_frag_queue(fq, skb, fhdr, nhoff); ip6_frag_queue(fq, skb, fhdr, *nhoffp);
if (fq->last_in == (FIRST_IN|LAST_IN) && if (fq->last_in == (FIRST_IN|LAST_IN) &&
fq->meat == fq->len) fq->meat == fq->len)
ret = ip6_frag_reasm(fq, skbp, dev); ret = ip6_frag_reasm(fq, skbp, nhoffp, dev);
spin_unlock(&fq->lock); spin_unlock(&fq->lock);
fq_put(fq); fq_put(fq);
return -ret; return ret;
} }
discard:
IP6_INC_STATS_BH(Ip6ReasmFails); IP6_INC_STATS_BH(Ip6ReasmFails);
kfree_skb(skb); kfree_skb(skb);
return 0; return -1;
} }
static struct inet6_protocol frag_protocol = static struct inet6_protocol frag_protocol =
{ {
.handler = ipv6_frag_rcv, .handler = ipv6_frag_rcv,
.flags = INET6_PROTO_NOPOLICY,
}; };
void __init ipv6_frag_init(void) void __init ipv6_frag_init(void)
......
...@@ -1591,7 +1591,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) ...@@ -1591,7 +1591,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
return 0; return 0;
} }
static int tcp_v6_rcv(struct sk_buff **pskb) static int tcp_v6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
{ {
struct sk_buff *skb = *pskb; struct sk_buff *skb = *pskb;
struct tcphdr *th; struct tcphdr *th;
...@@ -1657,7 +1657,7 @@ static int tcp_v6_rcv(struct sk_buff **pskb) ...@@ -1657,7 +1657,7 @@ static int tcp_v6_rcv(struct sk_buff **pskb)
bh_unlock_sock(sk); bh_unlock_sock(sk);
sock_put(sk); sock_put(sk);
return ret; return ret ? -1 : 0;
no_tcp_socket: no_tcp_socket:
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
...@@ -2193,7 +2193,7 @@ struct proto tcpv6_prot = { ...@@ -2193,7 +2193,7 @@ struct proto tcpv6_prot = {
static struct inet6_protocol tcpv6_protocol = { static struct inet6_protocol tcpv6_protocol = {
.handler = tcp_v6_rcv, .handler = tcp_v6_rcv,
.err_handler = tcp_v6_err, .err_handler = tcp_v6_err,
.no_policy = 1, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
}; };
extern struct proto_ops inet6_stream_ops; extern struct proto_ops inet6_stream_ops;
......
...@@ -640,7 +640,7 @@ static void udpv6_mcast_deliver(struct udphdr *uh, ...@@ -640,7 +640,7 @@ static void udpv6_mcast_deliver(struct udphdr *uh,
read_unlock(&udp_hash_lock); read_unlock(&udp_hash_lock);
} }
static int udpv6_rcv(struct sk_buff **pskb) static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
{ {
struct sk_buff *skb = *pskb; struct sk_buff *skb = *pskb;
struct sock *sk; struct sock *sk;
...@@ -954,7 +954,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg ...@@ -954,7 +954,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
static struct inet6_protocol udpv6_protocol = { static struct inet6_protocol udpv6_protocol = {
.handler = udpv6_rcv, .handler = udpv6_rcv,
.err_handler = udpv6_err, .err_handler = udpv6_err,
.no_policy = 1, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
}; };
#define LINE_LEN 190 #define LINE_LEN 190
......
...@@ -123,7 +123,7 @@ int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir) ...@@ -123,7 +123,7 @@ int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir)
return nexthdr; return nexthdr;
} }
int xfrm6_rcv(struct sk_buff **pskb) int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
{ {
struct sk_buff *skb = *pskb; struct sk_buff *skb = *pskb;
int err; int err;
...@@ -233,6 +233,7 @@ int xfrm6_rcv(struct sk_buff **pskb) ...@@ -233,6 +233,7 @@ int xfrm6_rcv(struct sk_buff **pskb)
memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state)); memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
skb->sp->len += xfrm_nr; skb->sp->len += xfrm_nr;
skb->ip_summed = CHECKSUM_NONE;
if (decaps) { if (decaps) {
if (!(skb->dev->flags&IFF_LOOPBACK)) { if (!(skb->dev->flags&IFF_LOOPBACK)) {
...@@ -240,9 +241,10 @@ int xfrm6_rcv(struct sk_buff **pskb) ...@@ -240,9 +241,10 @@ int xfrm6_rcv(struct sk_buff **pskb)
skb->dst = NULL; skb->dst = NULL;
} }
netif_rx(skb); netif_rx(skb);
return 0; return -1;
} else { } else {
return -nexthdr; *nhoffp = nh_offset;
return 1;
} }
drop_unlock: drop_unlock:
...@@ -253,7 +255,7 @@ int xfrm6_rcv(struct sk_buff **pskb) ...@@ -253,7 +255,7 @@ int xfrm6_rcv(struct sk_buff **pskb)
while (--xfrm_nr >= 0) while (--xfrm_nr >= 0)
xfrm_state_put(xfrm_vec[xfrm_nr].xvec); xfrm_state_put(xfrm_vec[xfrm_nr].xvec);
kfree_skb(skb); kfree_skb(skb);
return 0; return -1;
} }
void __init xfrm6_input_init(void) void __init xfrm6_input_init(void)
......
...@@ -149,11 +149,6 @@ static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp, ...@@ -149,11 +149,6 @@ static int rsvp_classify(struct sk_buff *skb, struct tcf_proto *tp,
struct iphdr *nhptr = skb->nh.iph; struct iphdr *nhptr = skb->nh.iph;
#endif #endif
#if !defined( __i386__) && !defined(__mc68000__)
if ((unsigned long)nhptr & 3)
return -1;
#endif
restart: restart:
#if RSVP_DST_LEN == 4 #if RSVP_DST_LEN == 4
......
...@@ -112,11 +112,6 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re ...@@ -112,11 +112,6 @@ static int u32_classify(struct sk_buff *skb, struct tcf_proto *tp, struct tcf_re
int sel = 0; int sel = 0;
int i; int i;
#if !defined(__i386__) && !defined(__mc68000__)
if ((unsigned long)ptr & 3)
return -1;
#endif
next_ht: next_ht:
n = ht->ht[sel]; n = ht->ht[sel];
......
...@@ -776,18 +776,18 @@ static struct inet_protosw sctpv6_stream_protosw = { ...@@ -776,18 +776,18 @@ static struct inet_protosw sctpv6_stream_protosw = {
.ops = &inet6_seqpacket_ops, .ops = &inet6_seqpacket_ops,
.capability = -1, .capability = -1,
.no_check = 0, .no_check = 0,
.flags = SCTP_PROTOSW_FLAG .flags = SCTP_PROTOSW_FLAG,
}; };
static int sctp6_rcv(struct sk_buff **pskb) static int sctp6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
{ {
return sctp_rcv(*pskb); return sctp_rcv(*pskb) ? -1 : 0;
} }
static struct inet6_protocol sctpv6_protocol = { static struct inet6_protocol sctpv6_protocol = {
.handler = sctp6_rcv, .handler = sctp6_rcv,
.err_handler = sctp_v6_err, .err_handler = sctp_v6_err,
.no_policy = 1, .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
}; };
static struct sctp_af sctp_ipv6_specific = { static struct sctp_af sctp_ipv6_specific = {
......
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