#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/icmp.h>
#include <net/icmp.h>
#include <net/ip.h>
#include <net/tcp.h>
static void send_unreach(struct sk_buff *skb_in, int code)
{
struct iphdr *iph;
+ struct udphdr *udph;
struct icmphdr *icmph;
struct sk_buff *nskb;
u32 saddr;
if (iph->frag_off&htons(IP_OFFSET))
return;
+ /* if UDP checksum is set, verify it's correct */
+ if (iph->protocol == IPPROTO_UDP
+ && skb_in->tail-(u8*)iph >= sizeof(struct udphdr)) {
+ int datalen = skb_in->len - (iph->ihl<<2);
+ udph = (struct udphdr *)((char *)iph + (iph->ihl<<2));
+ if (udph->check
+ && csum_tcpudp_magic(iph->saddr, iph->daddr,
+ datalen, IPPROTO_UDP,
+ csum_partial((char *)udph, datalen,
+ 0)) != 0)
+ return;
+ }
+
/* If we send an ICMP error to an ICMP error a mess would result.. */
if (iph->protocol == IPPROTO_ICMP
&& skb_in->tail-(u8*)iph >= sizeof(struct icmphdr)) {