#include <asm/uaccess.h>
#include <net/checksum.h>
#include <net/xfrm.h>
+#include <net/inet_common.h>
/*
* Build xmit assembly blocks
},
};
-/* Control parameters for ECHO replies. */
-int sysctl_icmp_echo_ignore_all __read_mostly;
-int sysctl_icmp_echo_ignore_broadcasts __read_mostly = 1;
-
-/* Control parameter - ignore bogus broadcast responses? */
-int sysctl_icmp_ignore_bogus_error_responses __read_mostly = 1;
-
-/*
- * Configurable global rate limit.
- *
- * ratelimit defines tokens/packet consumed for dst->rate_token bucket
- * ratemask defines which icmp types are ratelimited by setting
- * it's bit position.
- *
- * default:
- * dest unreachable (3), source quench (4),
- * time exceeded (11), parameter problem (12)
- */
-
-int sysctl_icmp_ratelimit __read_mostly = 1 * HZ;
-int sysctl_icmp_ratemask __read_mostly = 0x1818;
-int sysctl_icmp_errors_use_inbound_ifaddr __read_mostly;
-
/*
* ICMP control array. This specifies what to do with each ICMP.
*/
return rc;
}
-static inline int icmpv4_xrlim_allow(struct rtable *rt, int type, int code)
+static inline int icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
+ int type, int code)
{
struct dst_entry *dst = &rt->u.dst;
int rc = 1;
goto out;
/* Limit if icmp type is enabled in ratemask. */
- if ((1 << type) & sysctl_icmp_ratemask)
- rc = xrlim_allow(dst, sysctl_icmp_ratelimit);
+ if ((1 << type) & net->ipv4.sysctl_icmp_ratemask)
+ rc = xrlim_allow(dst, net->ipv4.sysctl_icmp_ratelimit);
out:
return rc;
}
struct sock *sk;
struct sk_buff *skb;
- sk = icmp_sk(rt->u.dst.dev->nd_net);
+ sk = icmp_sk(dev_net(rt->u.dst.dev));
if (ip_append_data(sk, icmp_glue_bits, icmp_param,
icmp_param->data_len+icmp_param->head_len,
icmp_param->head_len,
static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
{
struct ipcm_cookie ipc;
- struct rtable *rt = (struct rtable *)skb->dst;
- struct net *net = rt->u.dst.dev->nd_net;
+ struct rtable *rt = skb->rtable;
+ struct net *net = dev_net(rt->u.dst.dev);
struct sock *sk = icmp_sk(net);
struct inet_sock *inet = inet_sk(sk);
__be32 daddr;
if (ip_route_output_key(net, &rt, &fl))
goto out_unlock;
}
- if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type,
+ if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type,
icmp_param->data.icmph.code))
icmp_push_reply(icmp_param, &ipc, rt);
ip_rt_put(rt);
struct iphdr *iph;
int room;
struct icmp_bxm icmp_param;
- struct rtable *rt = (struct rtable *)skb_in->dst;
+ struct rtable *rt = skb_in->rtable;
struct ipcm_cookie ipc;
__be32 saddr;
u8 tos;
if (!rt)
goto out;
- net = rt->u.dst.dev->nd_net;
+ net = dev_net(rt->u.dst.dev);
sk = icmp_sk(net);
/*
if (!(rt->rt_flags & RTCF_LOCAL)) {
struct net_device *dev = NULL;
- if (rt->fl.iif && sysctl_icmp_errors_use_inbound_ifaddr)
+ if (rt->fl.iif &&
+ net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr)
dev = dev_get_by_index(net, rt->fl.iif);
if (dev) {
}
if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET))
- goto out_unlock;
+ goto relookup_failed;
if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL)
err = __ip_route_output_key(net, &rt2, &fl);
fl2.fl4_dst = fl.fl4_src;
if (ip_route_output_key(net, &rt2, &fl2))
- goto out_unlock;
+ goto relookup_failed;
/* Ugh! */
odst = skb_in->dst;
RT_TOS(tos), rt2->u.dst.dev);
dst_release(&rt2->u.dst);
- rt2 = (struct rtable *)skb_in->dst;
+ rt2 = skb_in->rtable;
skb_in->dst = odst;
}
if (err)
- goto out_unlock;
+ goto relookup_failed;
err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL,
XFRM_LOOKUP_ICMP);
- if (err == -ENOENT) {
+ switch (err) {
+ case 0:
+ dst_release(&rt->u.dst);
+ rt = rt2;
+ break;
+ case -EPERM:
+ goto ende;
+ default:
+relookup_failed:
if (!rt)
goto out_unlock;
- goto route_done;
+ break;
}
-
- dst_release(&rt->u.dst);
- rt = rt2;
-
- if (err)
- goto out_unlock;
}
route_done:
- if (!icmpv4_xrlim_allow(rt, type, code))
+ if (!icmpv4_xrlim_allow(net, rt, type, code))
goto ende;
/* RFC says return as much as we can without exceeding 576 bytes. */
u32 info = 0;
struct net *net;
- net = skb->dst->dev->nd_net;
+ net = dev_net(skb->dst->dev);
/*
* Incomplete header ?
break;
case ICMP_FRAG_NEEDED:
if (ipv4_config.no_pmtu_disc) {
- LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: "
+ LIMIT_NETDEBUG(KERN_INFO "ICMP: " NIPQUAD_FMT ": "
"fragmentation needed "
"and DF set.\n",
NIPQUAD(iph->daddr));
} else {
info = ip_rt_frag_needed(net, iph,
- ntohs(icmph->un.frag.mtu));
+ ntohs(icmph->un.frag.mtu),
+ skb->dev);
if (!info)
goto out;
}
break;
case ICMP_SR_FAILED:
- LIMIT_NETDEBUG(KERN_INFO "ICMP: %u.%u.%u.%u: Source "
+ LIMIT_NETDEBUG(KERN_INFO "ICMP: " NIPQUAD_FMT ": Source "
"Route Failed.\n",
NIPQUAD(iph->daddr));
break;
* get the other vendor to fix their kit.
*/
- if (!sysctl_icmp_ignore_bogus_error_responses &&
+ if (!net->ipv4.sysctl_icmp_ignore_bogus_error_responses &&
inet_addr_type(net, iph->daddr) == RTN_BROADCAST) {
if (net_ratelimit())
- printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP "
+ printk(KERN_WARNING NIPQUAD_FMT " sent an invalid ICMP "
"type %u, code %u "
- "error to a broadcast: %u.%u.%u.%u on %s\n",
+ "error to a broadcast: " NIPQUAD_FMT " on %s\n",
NIPQUAD(ip_hdr(skb)->saddr),
icmph->type, icmph->code,
NIPQUAD(iph->daddr),
static void icmp_echo(struct sk_buff *skb)
{
- if (!sysctl_icmp_echo_ignore_all) {
+ struct net *net;
+
+ net = dev_net(skb->dst->dev);
+ if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
struct icmp_bxm icmp_param;
icmp_param.data.icmph = *icmp_hdr(skb);
*/
static void icmp_timestamp(struct sk_buff *skb)
{
- struct timeval tv;
+ struct timespec tv;
struct icmp_bxm icmp_param;
/*
* Too short.
/*
* Fill in the current time as ms since midnight UT:
*/
- do_gettimeofday(&tv);
- icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * 1000 +
- tv.tv_usec / 1000);
+ getnstimeofday(&tv);
+ icmp_param.data.times[1] = htonl((tv.tv_sec % 86400) * MSEC_PER_SEC +
+ tv.tv_nsec / NSEC_PER_MSEC);
icmp_param.data.times[2] = icmp_param.data.times[1];
if (skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4))
BUG();
static void icmp_address_reply(struct sk_buff *skb)
{
- struct rtable *rt = (struct rtable *)skb->dst;
+ struct rtable *rt = skb->rtable;
struct net_device *dev = skb->dev;
struct in_device *in_dev;
struct in_ifaddr *ifa;
break;
}
if (!ifa && net_ratelimit()) {
- printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from "
- "%s/%u.%u.%u.%u\n",
+ printk(KERN_INFO "Wrong address mask " NIPQUAD_FMT " from "
+ "%s/" NIPQUAD_FMT "\n",
NIPQUAD(*mp), dev->name, NIPQUAD(rt->rt_src));
}
}
int icmp_rcv(struct sk_buff *skb)
{
struct icmphdr *icmph;
- struct rtable *rt = (struct rtable *)skb->dst;
+ struct rtable *rt = skb->rtable;
if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
int nh;
*/
if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
+ struct net *net;
+
+ net = dev_net(rt->u.dst.dev);
/*
* RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be
* silently ignored (we let user decide with a sysctl).
*/
if ((icmph->type == ICMP_ECHO ||
icmph->type == ICMP_TIMESTAMP) &&
- sysctl_icmp_echo_ignore_broadcasts) {
+ net->ipv4.sysctl_icmp_echo_ignore_broadcasts) {
goto error;
}
if (icmph->type != ICMP_ECHO &&
int i;
for_each_possible_cpu(i)
- sk_release_kernel(net->ipv4.icmp_sk[i]);
+ inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);
kfree(net->ipv4.icmp_sk);
net->ipv4.icmp_sk = NULL;
}
-int __net_init icmp_sk_init(struct net *net)
+static int __net_init icmp_sk_init(struct net *net)
{
int i, err;
for_each_possible_cpu(i) {
struct sock *sk;
- struct socket *sock;
- struct inet_sock *inet;
- err = sock_create_kern(PF_INET, SOCK_RAW, IPPROTO_ICMP, &sock);
+ err = inet_ctl_sock_create(&sk, PF_INET,
+ SOCK_RAW, IPPROTO_ICMP, net);
if (err < 0)
goto fail;
- net->ipv4.icmp_sk[i] = sk = sock->sk;
- sk_change_net(sk, net);
-
- sk->sk_allocation = GFP_ATOMIC;
+ net->ipv4.icmp_sk[i] = sk;
/* Enough space for 2 64K ICMP packets, including
* sk_buff struct overhead.
sk->sk_sndbuf =
(2 * ((64 * 1024) + sizeof(struct sk_buff)));
- inet = inet_sk(sk);
- inet->uc_ttl = -1;
- inet->pmtudisc = IP_PMTUDISC_DONT;
-
- /* Unhash it so that IP input processing does not even
- * see it, we do not wish this socket to see incoming
- * packets.
- */
- sk->sk_prot->unhash(sk);
+ inet_sk(sk)->pmtudisc = IP_PMTUDISC_DONT;
}
+
+ /* Control parameters for ECHO replies. */
+ net->ipv4.sysctl_icmp_echo_ignore_all = 0;
+ net->ipv4.sysctl_icmp_echo_ignore_broadcasts = 1;
+
+ /* Control parameter - ignore bogus broadcast responses? */
+ net->ipv4.sysctl_icmp_ignore_bogus_error_responses = 1;
+
+ /*
+ * Configurable global rate limit.
+ *
+ * ratelimit defines tokens/packet consumed for dst->rate_token
+ * bucket ratemask defines which icmp types are ratelimited by
+ * setting it's bit position.
+ *
+ * default:
+ * dest unreachable (3), source quench (4),
+ * time exceeded (11), parameter problem (12)
+ */
+
+ net->ipv4.sysctl_icmp_ratelimit = 1 * HZ;
+ net->ipv4.sysctl_icmp_ratemask = 0x1818;
+ net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr = 0;
+
return 0;
fail:
for_each_possible_cpu(i)
- sk_release_kernel(net->ipv4.icmp_sk[i]);
+ inet_ctl_sock_destroy(net->ipv4.icmp_sk[i]);
kfree(net->ipv4.icmp_sk);
return err;
}