ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/router/iphelp.cpp
Revision: 1.2
Committed: 2008-01-01T09:40:34Z (16 years, 11 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# Content
1 /*
2 * iphelp.cpp - ip router
3 *
4 * Basilisk II (C) 1997-2008 Christian Bauer
5 *
6 * Windows platform specific code copyright (C) Lauri Pesonen
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #include "sysdeps.h"
24 #include "cpu_emulation.h"
25 #include "ether_windows.h"
26 #include "ether.h"
27 #include "router.h"
28 #include "router_types.h"
29 #include "tcp.h"
30 #include "icmp.h"
31 #include "udp.h"
32 #include "iphelp.h"
33 #include "dump.h"
34
35
36 #if DEBUG
37 #pragma optimize("",off)
38 #endif
39
40 #include "debug.h"
41
42
43 void make_icmp_checksum( icmp_t *icmp, int len )
44 {
45 icmp->checksum = 0;
46
47 uint16 sz = (len-sizeof(ip_t))/2;
48 uint16 *p = (uint16 *)( (uint8 *)icmp + sizeof(ip_t) );
49
50 uint32 sum32 = 0;
51 for( int i=0; i<sz; i++ ) {
52 sum32 += ntohs(p[i]);
53 }
54
55 while( HIWORD(sum32) ) {
56 sum32 = HIWORD(sum32) + LOWORD(sum32);
57 }
58 sum32 = ~sum32;
59 icmp->checksum = htons((uint16)sum32);
60 }
61
62 void make_tcp_checksum( tcp_t *tcp, int len )
63 {
64 tcp->checksum = 0;
65
66 int tcp_len = len - sizeof(ip_t);
67 uint16 sz = tcp_len/2;
68 uint16 *p = (uint16 *)( (uint8 *)tcp + sizeof(ip_t) );
69
70 uint32 sum32 = 0;
71 for( int i=0; i<sz; i++ ) {
72 sum32 += ntohs(p[i]);
73 }
74
75 if(len & 1) {
76 uint8 *p8 = (uint8 *)p;
77 sum32 += p8[tcp_len-1] << 8;
78 }
79
80 pseudo_ip_t pseudo;
81 pseudo.src_lo = LOWORD(ntohl(tcp->ip.src));
82 pseudo.src_hi = HIWORD(ntohl(tcp->ip.src));
83 pseudo.dest_lo = LOWORD(ntohl(tcp->ip.dest));
84 pseudo.dest_hi = HIWORD(ntohl(tcp->ip.dest));
85 pseudo.proto = (uint16)tcp->ip.proto;
86 pseudo.msg_len = tcp->header_len >> 2;
87
88 int datalen = len - sizeof(tcp_t);
89 pseudo.msg_len += datalen;
90
91 p = (uint16 *)&pseudo;
92
93 for( int i=0; i<sizeof(pseudo_ip_t)/2; i++ ) {
94 sum32 += p[i];
95 }
96
97 while( HIWORD(sum32) ) {
98 sum32 = HIWORD(sum32) + LOWORD(sum32);
99 }
100 sum32 = ~sum32;
101 tcp->checksum = htons((uint16)sum32);
102 }
103
104 void make_ip4_checksum( ip_t *ip )
105 {
106 ip->checksum = 0;
107 uint16 sz = ip->header_len * 2;
108 uint16 *p = (uint16 *)( (uint8 *)ip + sizeof(mac_t) );
109
110 uint32 sum32 = 0;
111 for( int i=0; i<sz; i++ ) {
112 sum32 += ntohs(p[i]);
113 }
114
115 while( HIWORD(sum32) ) {
116 sum32 = HIWORD(sum32) + LOWORD(sum32);
117 }
118
119 sum32 = ~sum32;
120 ip->checksum = htons((uint16)sum32);
121 }
122
123 void make_udp_checksum( udp_t *udp )
124 {
125 udp->checksum = 0;
126 return;
127
128 // UDP checksums are optional.
129
130 /*
131 uint16 sz = ntohs(udp->msg_len) / 2;
132 uint16 *p = (uint16 *)( (uint8 *)udp + sizeof(ip_t) );
133
134 uint32 sum32 = 0;
135 for( int i=0; i<sz; i++ ) {
136 sum32 += ntohs(p[i]);
137 }
138
139 // last byte??
140
141 pseudo_ip_t pseudo;
142 pseudo.src_lo = LOWORD(ntohl(udp->ip.src));
143 pseudo.src_hi = HIWORD(ntohl(udp->ip.src));
144 pseudo.dest_lo = LOWORD(ntohl(udp->ip.dest));
145 pseudo.dest_hi = HIWORD(ntohl(udp->ip.dest));
146 pseudo.proto = (uint16)udp->ip.proto;
147 pseudo.msg_len = ntohs(udp->msg_len); // ???
148
149 p = (uint16 *)&pseudo;
150
151 for( i=0; i<sizeof(pseudo_ip_t)/2; i++ ) {
152 sum32 += p[i];
153 }
154
155 while( HIWORD(sum32) ) {
156 sum32 = HIWORD(sum32) + LOWORD(sum32);
157 }
158 sum32 = ~sum32;
159 udp->checksum = htons((uint16)sum32);
160 */
161 }
162
163 void error_winsock_2_icmp( int err, ip_t *ip_err, int dlen_err )
164 {
165 int type = -1, code = -1, msg_size = 0;
166
167 switch( err ) {
168 case WSAEHOSTUNREACH:
169 case WSAETIMEDOUT:
170 type = icmp_Destination_unreachable;
171 code = 1; // Host unreachable
172 msg_size = (ip_err->header_len << 2) + 4 + 8; // ip header + unused + 64 msg bits
173 break;
174 case WSAENETDOWN:
175 case WSAENETUNREACH:
176 type = icmp_Destination_unreachable;
177 code = 0; // Network unreachable
178 msg_size = (ip_err->header_len << 2) + 4 + 8; // ip header + unused + 64 msg bits
179 break;
180 case WSAETTLEXCEEDED:
181 type = icmp_Time_exceeded;
182 code = 0; // Transit TTL exceeded
183 msg_size = (ip_err->header_len << 2) + 4 + 8; // ip header + unused + 64 msg bits
184 break;
185 }
186
187 if(type >= 0 && macos_ip_address != 0) {
188 D(bug("sending icmp error reply. type=%d, code=%d, msg_size=%d\r\n", type, code, msg_size));
189
190 int icmp_size = sizeof(icmp_t) + msg_size;
191
192 icmp_t *icmp = (icmp_t *)malloc( icmp_size );
193 if(icmp) {
194 mac_t *mac = (mac_t *)icmp;
195 ip_t *ip = (ip_t *)icmp;
196
197 memcpy( mac->dest, ether_addr, 6 );
198 memcpy( mac->src, router_mac_addr, 6 );
199 mac->type = htons(mac_type_ip4);
200
201 ip->version = 4;
202 ip->header_len = 5;
203 ip->tos = 0;
204 ip->total_len = htons(sizeof(icmp_t) - sizeof(mac_t) + msg_size);
205
206 ip->ident = htons(next_ip_ident_number++);
207 ip->flags_n_frag_offset = 0;
208 ip->ttl = 128;
209 ip->proto = ip_proto_icmp;
210 ip->src = htonl(router_ip_address);
211 ip->dest = htonl(macos_ip_address);
212 make_ip4_checksum( ip );
213
214 icmp->type = type;
215 icmp->code = code;
216
217 // zero out the unused field
218 memset( (char *)icmp + sizeof(icmp_t), 0, sizeof(uint32) );
219
220 // copy 64 bits of original message
221 memcpy(
222 (char *)icmp + sizeof(icmp_t) + sizeof(uint32),
223 (char *)ip_err + sizeof(mac_t),
224 msg_size
225 );
226
227 make_icmp_checksum( icmp, icmp_size );
228
229 dump_bytes( (uint8 *)icmp, icmp_size );
230
231 enqueue_packet( (uint8 *)icmp, icmp_size );
232 free(icmp);
233 }
234 }
235 }