#include <sys/param.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <alias.h>
#include "natd.h"
int
SendNeedFragIcmp(int sock, struct ip *failedDgram, int mtu)
{
char icmpBuf[IP_MAXPACKET];
struct ip* ip;
struct icmp* icmp;
int icmpLen;
int failBytes;
int failHdrLen;
struct sockaddr_in addr;
int wrote;
struct in_addr swap;
if (ntohs(failedDgram->ip_off) & ~(IP_MF | IP_DF))
return 0;
if (failedDgram->ip_p == IPPROTO_ICMP)
return 0;
ip = (struct ip *)icmpBuf;
icmp = (struct icmp *)(icmpBuf + sizeof(struct ip));
icmp->icmp_type = ICMP_UNREACH;
icmp->icmp_code = ICMP_UNREACH_NEEDFRAG;
icmp->icmp_cksum = 0;
icmp->icmp_void = 0;
icmp->icmp_nextmtu = htons(mtu);
failHdrLen = (failedDgram->ip_hl << 2);
failBytes = failedDgram->ip_len - failHdrLen;
if (failBytes > 8)
failBytes = 8;
failBytes += failHdrLen;
icmpLen = ICMP_MINLEN + failBytes;
memcpy(&icmp->icmp_ip, failedDgram, failBytes);
icmp->icmp_cksum = PacketAliasInternetChecksum((u_short *)icmp,
icmpLen);
memcpy(ip, failedDgram, sizeof(struct ip));
ip->ip_v = 4;
ip->ip_hl = 5;
ip->ip_len = htons(sizeof(struct ip) + icmpLen);
ip->ip_p = IPPROTO_ICMP;
ip->ip_tos = 0;
swap = ip->ip_dst;
ip->ip_dst = ip->ip_src;
ip->ip_src = swap;
PacketAliasIn((char *)ip, IP_MAXPACKET);
addr.sin_family = AF_INET;
addr.sin_addr = ip->ip_dst;
addr.sin_port = 0;
wrote = sendto(sock,
icmp,
icmpLen,
0,
(struct sockaddr *)&addr,
sizeof addr);
if (wrote != icmpLen)
Warn("Cannot send ICMP message.");
return 1;
}