git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
coredump: factor out the not-ispipe file checks
[safe/jmp/linux-2.6]
/
net
/
ipv6
/
icmp.c
diff --git
a/net/ipv6/icmp.c
b/net/ipv6/icmp.c
index
1950861
..
ce79929
100644
(file)
--- a/
net/ipv6/icmp.c
+++ b/
net/ipv6/icmp.c
@@
-5,8
+5,6
@@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: icmp.c,v 1.38 2002/02/08 03:57:19 davem Exp $
- *
* Based on net/ipv4/icmp.c
*
* RFC 1885
* Based on net/ipv4/icmp.c
*
* RFC 1885
@@
-42,6
+40,7
@@
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/netfilter.h>
#include <linux/skbuff.h>
#include <linux/init.h>
#include <linux/netfilter.h>
+#include <linux/slab.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
@@
-69,11
+68,6
@@
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/system.h>
-DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics) __read_mostly;
-EXPORT_SYMBOL(icmpv6_statistics);
-DEFINE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics) __read_mostly;
-EXPORT_SYMBOL(icmpv6msg_statistics);
-
/*
* The ICMP socket(s). This is the most convenient way to flow control
* our ICMP output as well as maintain a clean interface throughout
/*
* The ICMP socket(s). This is the most convenient way to flow control
* our ICMP output as well as maintain a clean interface throughout
@@
-88,24
+82,27
@@
static inline struct sock *icmpv6_sk(struct net *net)
static int icmpv6_rcv(struct sk_buff *skb);
static int icmpv6_rcv(struct sk_buff *skb);
-static struct inet6_protocol icmpv6_protocol = {
+static
const
struct inet6_protocol icmpv6_protocol = {
.handler = icmpv6_rcv,
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};
.handler = icmpv6_rcv,
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};
-static __inline__
int icmpv6_xmit_lock(struct sock *sk
)
+static __inline__
struct sock *icmpv6_xmit_lock(struct net *net
)
{
{
+ struct sock *sk;
+
local_bh_disable();
local_bh_disable();
+ sk = icmpv6_sk(net);
if (unlikely(!spin_trylock(&sk->sk_lock.slock))) {
/* This can happen if the output path (f.e. SIT or
* ip6ip6 tunnel) signals dst_link_failure() for an
* outgoing ICMP6 packet.
*/
local_bh_enable();
if (unlikely(!spin_trylock(&sk->sk_lock.slock))) {
/* This can happen if the output path (f.e. SIT or
* ip6ip6 tunnel) signals dst_link_failure() for an
* outgoing ICMP6 packet.
*/
local_bh_enable();
- return
1
;
+ return
NULL
;
}
}
- return
0
;
+ return
sk
;
}
static __inline__ void icmpv6_xmit_unlock(struct sock *sk)
}
static __inline__ void icmpv6_xmit_unlock(struct sock *sk)
@@
-116,9
+113,9
@@
static __inline__ void icmpv6_xmit_unlock(struct sock *sk)
/*
* Slightly more convenient version of icmpv6_send.
*/
/*
* Slightly more convenient version of icmpv6_send.
*/
-void icmpv6_param_prob(struct sk_buff *skb,
int
code, int pos)
+void icmpv6_param_prob(struct sk_buff *skb,
u8
code, int pos)
{
{
- icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos
, skb->dev
);
+ icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos);
kfree_skb(skb);
}
kfree_skb(skb);
}
@@
-160,7
+157,7
@@
static int is_ineligible(struct sk_buff *skb)
/*
* Check the ICMP output rate limit
*/
/*
* Check the ICMP output rate limit
*/
-static inline int icmpv6_xrlim_allow(struct sock *sk,
int
type,
+static inline int icmpv6_xrlim_allow(struct sock *sk,
u8
type,
struct flowi *fl)
{
struct dst_entry *dst;
struct flowi *fl)
{
struct dst_entry *dst;
@@
-182,7
+179,7
@@
static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
*/
dst = ip6_route_output(net, sk, fl);
if (dst->error) {
*/
dst = ip6_route_output(net, sk, fl);
if (dst->error) {
- IP6_INC_STATS(ip6_dst_idev(dst),
+ IP6_INC_STATS(
net,
ip6_dst_idev(dst),
IPSTATS_MIB_OUTNOROUTES);
} else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
res = 1;
IPSTATS_MIB_OUTNOROUTES);
} else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
res = 1;
@@
-232,7
+229,7
@@
static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct
icmp6h->icmp6_cksum = 0;
if (skb_queue_len(&sk->sk_write_queue) == 1) {
icmp6h->icmp6_cksum = 0;
if (skb_queue_len(&sk->sk_write_queue) == 1) {
- skb->csum = csum_partial(
(char *)
icmp6h,
+ skb->csum = csum_partial(icmp6h,
sizeof(struct icmp6hdr), skb->csum);
icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src,
&fl->fl6_dst,
sizeof(struct icmp6hdr), skb->csum);
icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src,
&fl->fl6_dst,
@@
-245,7
+242,7
@@
static int icmpv6_push_pending_frames(struct sock *sk, struct flowi *fl, struct
tmp_csum = csum_add(tmp_csum, skb->csum);
}
tmp_csum = csum_add(tmp_csum, skb->csum);
}
- tmp_csum = csum_partial(
(char *)
icmp6h,
+ tmp_csum = csum_partial(icmp6h,
sizeof(struct icmp6hdr), tmp_csum);
icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src,
&fl->fl6_dst,
sizeof(struct icmp6hdr), tmp_csum);
icmp6h->icmp6_cksum = csum_ipv6_magic(&fl->fl6_src,
&fl->fl6_dst,
@@
-304,8
+301,7
@@
static inline void mip6_addr_swap(struct sk_buff *skb) {}
/*
* Send an ICMP message in response to a packet in error
*/
/*
* Send an ICMP message in response to a packet in error
*/
-void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
- struct net_device *dev)
+void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
{
struct net *net = dev_net(skb->dev);
struct inet6_dev *idev = NULL;
{
struct net *net = dev_net(skb->dev);
struct inet6_dev *idev = NULL;
@@
-322,7
+318,7
@@
void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
int iif = 0;
int addr_type = 0;
int len;
int iif = 0;
int addr_type = 0;
int len;
- int hlimit
, tclass
;
+ int hlimit;
int err = 0;
if ((u8 *)hdr < skb->head ||
int err = 0;
if ((u8 *)hdr < skb->head ||
@@
-394,11
+390,10
@@
void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
fl.fl_icmp_code = code;
security_skb_classify_flow(skb, &fl);
fl.fl_icmp_code = code;
security_skb_classify_flow(skb, &fl);
- sk = icmpv6_sk(net);
- np = inet6_sk(sk);
-
- if (icmpv6_xmit_lock(sk))
+ sk = icmpv6_xmit_lock(net);
+ if (sk == NULL)
return;
return;
+ np = inet6_sk(sk);
if (!icmpv6_xrlim_allow(sk, type, &fl))
goto out;
if (!icmpv6_xrlim_allow(sk, type, &fl))
goto out;
@@
-427,7
+422,7
@@
void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
/* No need to clone since we're just using its address. */
dst2 = dst;
/* No need to clone since we're just using its address. */
dst2 = dst;
- err = xfrm_lookup(&dst, &fl, sk, 0);
+ err = xfrm_lookup(
net,
&dst, &fl, sk, 0);
switch (err) {
case 0:
if (dst != dst2)
switch (err) {
case 0:
if (dst != dst2)
@@
-441,24
+436,26
@@
void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
}
if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6))
}
if (xfrm_decode_session_reverse(skb, &fl2, AF_INET6))
- goto
out_dst_release
;
+ goto
relookup_failed
;
- if (ip6_dst_lookup(sk, &dst2, &fl))
- goto
out_dst_release
;
+ if (ip6_dst_lookup(sk, &dst2, &fl
2
))
+ goto
relookup_failed
;
- err = xfrm_lookup(&dst2, &fl, sk, XFRM_LOOKUP_ICMP);
- if (err == -ENOENT) {
+ err = xfrm_lookup(net, &dst2, &fl2, sk, XFRM_LOOKUP_ICMP);
+ switch (err) {
+ case 0:
+ dst_release(dst);
+ dst = dst2;
+ break;
+ case -EPERM:
+ goto out_dst_release;
+ default:
+relookup_failed:
if (!dst)
goto out;
if (!dst)
goto out;
-
goto route_done
;
+
break
;
}
}
- dst_release(dst);
- dst = dst2;
-
- if (err)
- goto out;
-
route_done:
if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops;
route_done:
if (ipv6_addr_is_multicast(&fl.fl6_dst))
hlimit = np->mcast_hops;
@@
-467,10
+464,6
@@
route_done:
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
- tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
-
msg.skb = skb;
msg.offset = skb_network_offset(skb);
msg.type = type;
msg.skb = skb;
msg.offset = skb_network_offset(skb);
msg.type = type;
@@
-486,10
+479,11
@@
route_done:
err = ip6_append_data(sk, icmpv6_getfrag, &msg,
len + sizeof(struct icmp6hdr),
err = ip6_append_data(sk, icmpv6_getfrag, &msg,
len + sizeof(struct icmp6hdr),
- sizeof(struct icmp6hdr),
-
hlimit,
tclass, NULL, &fl, (struct rt6_info*)dst,
- MSG_DONTWAIT);
+ sizeof(struct icmp6hdr),
hlimit,
+
np->
tclass, NULL, &fl, (struct rt6_info*)dst,
+ MSG_DONTWAIT
, np->dontfrag
);
if (err) {
if (err) {
+ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
ip6_flush_pending_frames(sk);
goto out_put;
}
ip6_flush_pending_frames(sk);
goto out_put;
}
@@
-520,7
+514,6
@@
static void icmpv6_echo_reply(struct sk_buff *skb)
struct dst_entry *dst;
int err = 0;
int hlimit;
struct dst_entry *dst;
int err = 0;
int hlimit;
- int tclass;
saddr = &ipv6_hdr(skb)->daddr;
saddr = &ipv6_hdr(skb)->daddr;
@@
-539,11
+532,10
@@
static void icmpv6_echo_reply(struct sk_buff *skb)
fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
security_skb_classify_flow(skb, &fl);
fl.fl_icmp_type = ICMPV6_ECHO_REPLY;
security_skb_classify_flow(skb, &fl);
- sk = icmpv6_sk(net);
- np = inet6_sk(sk);
-
- if (icmpv6_xmit_lock(sk))
+ sk = icmpv6_xmit_lock(net);
+ if (sk == NULL)
return;
return;
+ np = inet6_sk(sk);
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
@@
-551,7
+543,7
@@
static void icmpv6_echo_reply(struct sk_buff *skb)
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
goto out;
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
goto out;
- if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0)
+ if ((err = xfrm_lookup(
net,
&dst, &fl, sk, 0)) < 0)
goto out;
if (ipv6_addr_is_multicast(&fl.fl6_dst))
goto out;
if (ipv6_addr_is_multicast(&fl.fl6_dst))
@@
-561,10
+553,6
@@
static void icmpv6_echo_reply(struct sk_buff *skb)
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
if (hlimit < 0)
hlimit = ip6_dst_hoplimit(dst);
- tclass = np->tclass;
- if (tclass < 0)
- tclass = 0;
-
idev = in6_dev_get(skb->dev);
msg.skb = skb;
idev = in6_dev_get(skb->dev);
msg.skb = skb;
@@
-572,10
+560,12
@@
static void icmpv6_echo_reply(struct sk_buff *skb)
msg.type = ICMPV6_ECHO_REPLY;
err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
msg.type = ICMPV6_ECHO_REPLY;
err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr),
- sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl,
- (struct rt6_info*)dst, MSG_DONTWAIT);
+ sizeof(struct icmp6hdr), hlimit, np->tclass, NULL, &fl,
+ (struct rt6_info*)dst, MSG_DONTWAIT,
+ np->dontfrag);
if (err) {
if (err) {
+ ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS);
ip6_flush_pending_frames(sk);
goto out_put;
}
ip6_flush_pending_frames(sk);
goto out_put;
}
@@
-589,9
+579,9
@@
out:
icmpv6_xmit_unlock(sk);
}
icmpv6_xmit_unlock(sk);
}
-static void icmpv6_notify(struct sk_buff *skb,
int type, int
code, __be32 info)
+static void icmpv6_notify(struct sk_buff *skb,
u8 type, u8
code, __be32 info)
{
{
- struct inet6_protocol *ipprot;
+
const
struct inet6_protocol *ipprot;
int inner_offset;
int hash;
u8 nexthdr;
int inner_offset;
int hash;
u8 nexthdr;
@@
-642,12
+632,13
@@
static int icmpv6_rcv(struct sk_buff *skb)
struct in6_addr *saddr, *daddr;
struct ipv6hdr *orig_hdr;
struct icmp6hdr *hdr;
struct in6_addr *saddr, *daddr;
struct ipv6hdr *orig_hdr;
struct icmp6hdr *hdr;
-
int
type;
+
u8
type;
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+ struct sec_path *sp = skb_sec_path(skb);
int nh;
int nh;
- if (!(s
kb->sp && skb->sp->xvec[skb->
sp->len - 1]->props.flags &
+ if (!(s
p && sp->xvec[
sp->len - 1]->props.flags &
XFRM_STATE_ICMP))
goto drop_no_count;
XFRM_STATE_ICMP))
goto drop_no_count;
@@
-663,7
+654,7
@@
static int icmpv6_rcv(struct sk_buff *skb)
skb_set_network_header(skb, nh);
}
skb_set_network_header(skb, nh);
}
- ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS);
+ ICMP6_INC_STATS_BH(
dev_net(dev),
idev, ICMP6_MIB_INMSGS);
saddr = &ipv6_hdr(skb)->saddr;
daddr = &ipv6_hdr(skb)->daddr;
saddr = &ipv6_hdr(skb)->saddr;
daddr = &ipv6_hdr(skb)->daddr;
@@
-679,8
+670,8
@@
static int icmpv6_rcv(struct sk_buff *skb)
skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len,
IPPROTO_ICMPV6, 0));
if (__skb_checksum_complete(skb)) {
skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len,
IPPROTO_ICMPV6, 0));
if (__skb_checksum_complete(skb)) {
- LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [
" NIP6_FMT " > " NIP6_FMT "
]\n",
-
NIP6(*saddr), NIP6(*daddr)
);
+ LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [
%pI6 > %pI6
]\n",
+
saddr, daddr
);
goto discard_it;
}
}
goto discard_it;
}
}
@@
-692,7
+683,7
@@
static int icmpv6_rcv(struct sk_buff *skb)
type = hdr->icmp6_type;
type = hdr->icmp6_type;
- ICMP6MSGIN_INC_STATS_BH(idev, type);
+ ICMP6MSGIN_INC_STATS_BH(
dev_net(dev),
idev, type);
switch (type) {
case ICMPV6_ECHO_REQUEST:
switch (type) {
case ICMPV6_ECHO_REQUEST:
@@
-771,7
+762,7
@@
static int icmpv6_rcv(struct sk_buff *skb)
return 0;
discard_it:
return 0;
discard_it:
- ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INERRORS);
+ ICMP6_INC_STATS_BH(
dev_net(dev),
idev, ICMP6_MIB_INERRORS);
drop_no_count:
kfree_skb(skb);
return 0;
drop_no_count:
kfree_skb(skb);
return 0;
@@
-912,7
+903,7
@@
static const struct icmp6_err {
},
};
},
};
-int icmpv6_err_convert(
int type, int
code, int *err)
+int icmpv6_err_convert(
u8 type, u8
code, int *err)
{
int fatal = 0;
{
int fatal = 0;
@@
-949,17
+940,16
@@
EXPORT_SYMBOL(icmpv6_err_convert);
#ifdef CONFIG_SYSCTL
ctl_table ipv6_icmp_table_template[] = {
{
#ifdef CONFIG_SYSCTL
ctl_table ipv6_icmp_table_template[] = {
{
- .ctl_name = NET_IPV6_ICMP_RATELIMIT,
.procname = "ratelimit",
.data = &init_net.ipv6.sysctl.icmpv6_time,
.maxlen = sizeof(int),
.mode = 0644,
.procname = "ratelimit",
.data = &init_net.ipv6.sysctl.icmpv6_time,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler =
&proc_dointvec
+ .proc_handler =
proc_dointvec_ms_jiffies,
},
},
- {
.ctl_name = 0
},
+ { },
};
};
-struct ctl_table *ipv6_icmp_sysctl_init(struct net *net)
+struct ctl_table *
__net_init
ipv6_icmp_sysctl_init(struct net *net)
{
struct ctl_table *table;
{
struct ctl_table *table;