2 * natd - Network Address Translation Daemon for FreeBSD.
4 * This software is provided free of charge, with no
5 * warranty of any kind, either expressed or implied.
6 * Use at your own risk.
8 * You may copy, modify and distribute this software (icmp.c) freely.
10 * Ari Suutari <suutari@iki.fi>
12 * $FreeBSD: src/sbin/natd/icmp.c,v 1.6 1999/08/28 00:13:45 peter Exp $
13 * $DragonFly: src/sbin/natd/icmp.c,v 1.5 2005/06/07 20:21:23 swildner Exp $
16 #include <sys/param.h>
17 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <netinet/in_systm.h>
33 #include <netinet/ip.h>
34 #include <netinet/ip_icmp.h>
41 SendNeedFragIcmp(int sock
, struct ip
*failedDgram
, int mtu
)
43 char icmpBuf
[IP_MAXPACKET
];
49 struct sockaddr_in addr
;
53 * Don't send error if packet is
54 * not the first fragment.
56 if (ntohs(failedDgram
->ip_off
) & ~(IP_MF
| IP_DF
))
59 * Dont respond if failed datagram is ICMP.
61 if (failedDgram
->ip_p
== IPPROTO_ICMP
)
64 * Start building the message.
66 ip
= (struct ip
*)icmpBuf
;
67 icmp
= (struct icmp
*)(icmpBuf
+ sizeof(struct ip
));
71 icmp
->icmp_type
= ICMP_UNREACH
;
72 icmp
->icmp_code
= ICMP_UNREACH_NEEDFRAG
;
75 icmp
->icmp_nextmtu
= htons(mtu
);
77 * Copy header + 64 bits of original datagram.
79 failHdrLen
= (failedDgram
->ip_hl
<< 2);
80 failBytes
= failedDgram
->ip_len
- failHdrLen
;
84 failBytes
+= failHdrLen
;
85 icmpLen
= ICMP_MINLEN
+ failBytes
;
87 memcpy(&icmp
->icmp_ip
, failedDgram
, failBytes
);
91 icmp
->icmp_cksum
= PacketAliasInternetChecksum((u_short
*)icmp
,
94 * Add IP header using old IP header as template.
96 memcpy(ip
, failedDgram
, sizeof(struct ip
));
100 ip
->ip_len
= htons(sizeof(struct ip
) + icmpLen
);
101 ip
->ip_p
= IPPROTO_ICMP
;
105 ip
->ip_dst
= ip
->ip_src
;
108 PacketAliasIn((char *)ip
, IP_MAXPACKET
);
110 addr
.sin_family
= AF_INET
;
111 addr
.sin_addr
= ip
->ip_dst
;
114 * Put packet into processing queue.
120 (struct sockaddr
*)&addr
,
123 if (wrote
!= icmpLen
)
124 Warn("Cannot send ICMP message.");