]> git.saurik.com Git - apple/network_cmds.git/blob - natd.tproj/icmp.c
network_cmds-115.tar.gz
[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 * 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
60 int 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