static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, int len) { struct iphdr *iph; unsigned long ip; if (len < sizeof(struct iphdr)) { icmp_statistics.IcmpInErrors++; return; } /* * Get the copied header of the packet that caused the redirect */ iph = (struct iphdr *) (icmph + 1); ip = iph->daddr; switch(icmph->code & 7) { case ICMP_REDIR_NET: case ICMP_REDIR_NETTOS: /* * As per RFC recommendations now handle it as * a host redirect. */ case ICMP_REDIR_HOST: case ICMP_REDIR_HOSTTOS: ip_rt_redirect(skb->nh.iph->saddr, ip, icmph->un.gateway, iph->saddr, iph->tos, skb->dev); break; default: break; } }
static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 source, __u32 daddr, int len) { struct iphdr *iph; unsigned long ip; /* * Get the copied header of the packet that caused the redirect */ if(len<=sizeof(struct iphdr)) goto flush_it; iph = (struct iphdr *) (icmph + 1); ip = iph->daddr; /* * If we are a router and we run a routing protocol, we MUST NOT follow redirects. * When using no routing protocol, we MAY follow redirects. (RFC 1812, 5.2.7.2) */ #if !defined(CONFIG_IP_DUMB_ROUTER) if (sysctl_ip_forward) { NETDEBUG(printk(KERN_INFO "icmp: ICMP redirect ignored. dest = %lX, " "orig gw = %lX, \"new\" gw = %lX, device = %s.\n", ntohl(ip), ntohl(source), ntohl(icmph->un.gateway), dev->name)); goto flush_it; } #endif switch(icmph->code & 7) { case ICMP_REDIR_NET: /* * This causes a problem with subnetted networks. What we should do * is use ICMP_ADDRESS to get the subnet mask of the problem route * and set both. But we don't.. [RFC1812 says routers MUST NOT * generate Network Redirects] */ #ifdef not_a_good_idea ip_rt_add((RTF_DYNAMIC | RTF_MODIFIED | RTF_GATEWAY), ip, 0, icmph->un.gateway, dev,0, 0, 0); #endif /* * As per RFC recommendations now handle it as * a host redirect. */ case ICMP_REDIR_HOST: /* * Add better route to host. * But first check that the redirect * comes from the old gateway.. * And make sure it's an ok host address * (not some confused thing sending our * address) */ NETDEBUG(printk(KERN_INFO "ICMP redirect from %s\n", in_ntoa(source))); ip_rt_redirect(source, ip, icmph->un.gateway, dev); break; case ICMP_REDIR_NETTOS: case ICMP_REDIR_HOSTTOS: NETDEBUG(printk(KERN_INFO "ICMP: cannot handle TOS redirects yet!\n")); break; default: break; } /* * Discard the original packet */ flush_it: kfree_skb(skb, FREE_READ); }