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, 6 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * iphelp.cpp - ip router
3     *
4 gbeauche 1.2 * Basilisk II (C) 1997-2008 Christian Bauer
5 gbeauche 1.1 *
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     }