]>
Commit | Line | Data |
---|---|---|
7ba0088d A |
1 | /* |
2 | * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
a2c93a76 A |
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. | |
7ba0088d | 11 | * |
a2c93a76 A |
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 | |
7ba0088d A |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
a2c93a76 A |
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. | |
7ba0088d A |
19 | * |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
b7080c8e A |
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 | * | |
7ba0088d A |
33 | * Based upon: |
34 | * $FreeBSD: src/sbin/natd/icmp.c,v 1.6 1999/08/28 00:13:45 peter Exp $ | |
b7080c8e A |
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 |