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