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