1/* 2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22/* 23 * natd - Network Address Translation Daemon for FreeBSD. 24 * 25 * This software is provided free of charge, with no 26 * warranty of any kind, either expressed or implied. 27 * Use at your own risk. 28 * 29 * You may copy, modify and distribute this software (icmp.c) freely. 30 * 31 * Ari Suutari <suutari@iki.fi> 32 * 33 * Based upon: 34 * $FreeBSD: src/sbin/natd/icmp.c,v 1.6 1999/08/28 00:13:45 peter Exp $ 35 */ 36 37#include <stdlib.h> 38#include <stdio.h> 39#include <unistd.h> 40#include <string.h> 41#include <ctype.h> 42 43#include <sys/types.h> 44#include <sys/socket.h> 45#include <sys/time.h> 46#include <errno.h> 47#include <signal.h> 48 49#include <netdb.h> 50 51#include <netinet/in.h> 52#include <netinet/in_systm.h> 53#include <netinet/ip.h> 54#include <netinet/ip_icmp.h> 55 56#include <alias.h> 57 58#include "natd.h" 59 60int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu) 61{ 62 char icmpBuf[IP_MAXPACKET]; 63 struct ip* ip; 64 struct icmp* icmp; 65 int icmpLen; 66 int failBytes; 67 int failHdrLen; 68 struct sockaddr_in addr; 69 int wrote; 70 struct in_addr swap; 71/* 72 * Don't send error if packet is 73 * not the first fragment. 74 */ 75 if (ntohs (failedDgram->ip_off) & ~(IP_MF | IP_DF)) 76 return 0; 77/* 78 * Dont respond if failed datagram is ICMP. 79 */ 80 if (failedDgram->ip_p == IPPROTO_ICMP) 81 return 0; 82/* 83 * Start building the message. 84 */ 85 ip = (struct ip*) icmpBuf; 86 icmp = (struct icmp*) (icmpBuf + sizeof (struct ip)); 87/* 88 * Complete ICMP part. 89 */ 90 icmp->icmp_type = ICMP_UNREACH; 91 icmp->icmp_code = ICMP_UNREACH_NEEDFRAG; 92 icmp->icmp_cksum = 0; 93 icmp->icmp_void = 0; 94 icmp->icmp_nextmtu = htons (mtu); 95/* 96 * Copy header + 64 bits of original datagram. 97 */ 98 failHdrLen = (failedDgram->ip_hl << 2); 99 failBytes = failedDgram->ip_len - failHdrLen; 100 if (failBytes > 8) 101 failBytes = 8; 102 103 failBytes += failHdrLen; 104 icmpLen = ICMP_MINLEN + failBytes; 105 106 memcpy (&icmp->icmp_ip, failedDgram, failBytes); 107/* 108 * Calculate checksum. 109 */ 110 icmp->icmp_cksum = PacketAliasInternetChecksum ((u_short*) icmp, 111 icmpLen); 112/* 113 * Add IP header using old IP header as template. 114 */ 115 memcpy (ip, failedDgram, sizeof (struct ip)); 116 117 ip->ip_v = 4; 118 ip->ip_hl = 5; 119 ip->ip_len = htons (sizeof (struct ip) + icmpLen); 120 ip->ip_p = IPPROTO_ICMP; 121 ip->ip_tos = 0; 122 123 swap = ip->ip_dst; 124 ip->ip_dst = ip->ip_src; 125 ip->ip_src = swap; 126 127 PacketAliasIn ((char*) ip, IP_MAXPACKET); 128 129 addr.sin_family = AF_INET; 130 addr.sin_addr = ip->ip_dst; 131 addr.sin_port = 0; 132/* 133 * Put packet into processing queue. 134 */ 135 wrote = sendto (sock, 136 icmp, 137 icmpLen, 138 0, 139 (struct sockaddr*) &addr, 140 sizeof addr); 141 142 if (wrote != icmpLen) 143 Warn ("Cannot send ICMP message."); 144 145 return 1; 146} 147 148 149