int sysctl_icmp_ratelimit = 1 * HZ;
int sysctl_icmp_ratemask = 0x1818;
+int sysctl_icmp_errors_use_inbound_ifaddr;
/*
* ICMP control array. This specifies what to do with each ICMP.
*/
saddr = iph->daddr;
- if (!(rt->rt_flags & RTCF_LOCAL))
- saddr = 0;
+ if (!(rt->rt_flags & RTCF_LOCAL)) {
+ if (sysctl_icmp_errors_use_inbound_ifaddr)
+ saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK);
+ else
+ saddr = 0;
+ }
tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) |
IPTOS_PREC_INTERNETCONTROL) :
iph->tos;
- {
- struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->saddr,
- .saddr = saddr,
- .tos = RT_TOS(tos) } },
- .proto = IPPROTO_ICMP };
- if (ip_route_output_key(&rt, &fl))
- goto out_unlock;
- }
if (ip_options_echo(&icmp_param.replyopts, skb_in))
goto ende;
inet_sk(icmp_socket->sk)->tos = tos;
ipc.addr = iph->saddr;
ipc.opt = &icmp_param.replyopts;
- if (icmp_param.replyopts.srr) {
- struct flowi fl = { .nl_u = { .ip4_u =
- { .daddr = icmp_param.replyopts.faddr,
- .saddr = saddr,
- .tos = RT_TOS(tos) } },
- .proto = IPPROTO_ICMP };
- ip_rt_put(rt);
+
+ {
+ struct flowi fl = {
+ .nl_u = {
+ .ip4_u = {
+ .daddr = icmp_param.replyopts.srr ?
+ icmp_param.replyopts.faddr :
+ iph->saddr,
+ .saddr = saddr,
+ .tos = RT_TOS(tos)
+ }
+ },
+ .proto = IPPROTO_ICMP,
+ .uli_u = {
+ .icmpt = {
+ .type = type,
+ .code = code
+ }
+ }
+ };
if (ip_route_output_key(&rt, &fl))
goto out_unlock;
}
/* RFC says return as much as we can without exceeding 576 bytes. */
- room = dst_pmtu(&rt->u.dst);
+ room = dst_mtu(&rt->u.dst);
if (room > 576)
room = 576;
room -= sizeof(struct iphdr) + icmp_param.replyopts.optlen;