ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/router/udp.cpp
Revision: 1.2
Committed: 2008-01-01T09:40:34Z (16 years, 10 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 * udp.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 "prefs.h"
26 #include "ether_windows.h"
27 #include "ether.h"
28 #include "router.h"
29 #include "router_types.h"
30 #include "dynsockets.h"
31 #include "ipsocket.h"
32 #include "iphelp.h"
33 #include "udp.h"
34 #include "dump.h"
35
36
37 #if DEBUG
38 #pragma optimize("",off)
39 #endif
40
41 #include "debug.h"
42
43
44 void CALLBACK udp_read_completion(
45 DWORD error,
46 DWORD bytes_read,
47 LPWSAOVERLAPPED lpOverlapped,
48 DWORD flags
49 )
50 {
51 D(bug("udp_read_completion(error=0x%x, bytes_read=%d, flags=0x%x)\r\n", error, bytes_read, flags));
52
53 socket_t *cmpl = (socket_t *)lpOverlapped->hEvent;
54
55 // It's not easy to know whether empty upd datagrams should be passed along. doh.
56 if(error == 0 && bytes_read > 0) {
57
58 if(bytes_read > 1460) {
59 D(bug("discarding oversized udp packet, size = \r\n", bytes_read));
60 } else {
61 struct sockaddr_in name;
62 int namelen = sizeof(name);
63 memset( &name, 0, sizeof(name) );
64 if( _getsockname( cmpl->s, (struct sockaddr *)&name, &namelen ) == SOCKET_ERROR ) {
65 D(bug("_getsockname() failed, error=%d\r\n", _WSAGetLastError() ));
66 } else {
67 D(bug("_getsockname(): port=%d\r\n", ntohs(name.sin_port) ));
68 }
69
70 int udp_size = sizeof(udp_t) + bytes_read;
71 udp_t *udp = (udp_t *)malloc( udp_size );
72 if(udp) {
73 mac_t *mac = (mac_t *)udp;
74 ip_t *ip = (ip_t *)udp;
75
76 // Build MAC
77 // memcpy( udp->ip.mac.dest, cmpl->mac_src, 6 );
78 memcpy( mac->dest, ether_addr, 6 );
79 memcpy( mac->src, router_mac_addr, 6 );
80 mac->type = htons(mac_type_ip4);
81
82 // Build IP
83 ip->version = 4;
84 ip->header_len = 5;
85 ip->tos = 0;
86 ip->total_len = htons(sizeof(udp_t) - sizeof(mac_t) + bytes_read); // no options
87 ip->ident = htons(next_ip_ident_number++); // htons() might be a macro... but does not really matter here.
88 ip->flags_n_frag_offset = 0;
89 ip->ttl = 128; // one hop actually!
90 ip->proto = ip_proto_udp;
91 ip->src = htonl(cmpl->ip_dest);
92 ip->dest = htonl(cmpl->ip_src);
93 make_ip4_checksum( (ip_t *)udp );
94
95 // Copy payload (used by UDP checksum)
96 memcpy( (char *)udp + sizeof(udp_t), cmpl->buffers[0].buf, bytes_read );
97
98 // Build UDP
99 udp->src_port = htons(cmpl->dest_port);
100 udp->dest_port = htons(cmpl->src_port);
101 udp->msg_len = htons(sizeof(udp_t) - sizeof(ip_t) + bytes_read); // no options
102 make_udp_checksum( udp );
103
104 dump_bytes( (uint8 *)udp, udp_size );
105
106 enqueue_packet( (uint8 *)udp, udp_size );
107 free(udp);
108 }
109 }
110 }
111
112 if(!is_router_shutting_down && cmpl->s != INVALID_SOCKET && cmpl->b_recfrom()) {
113 cmpl->socket_ttl = GetTickCount() + 60000L;
114 } else {
115 delete_socket( cmpl );
116 }
117 }
118
119 void write_udp( udp_t *udp, int len )
120 {
121 if( len < sizeof(udp_t) ) {
122 D(bug("Too small udp packet(%d), dropped\r\n", len));
123 return;
124 }
125
126 uint16 src_port = ntohs(udp->src_port);
127 uint16 dest_port = ntohs(udp->dest_port);
128
129 BOOL ok = true;
130
131 socket_t *cmpl = find_socket( src_port, dest_port, IPPROTO_UDP );
132
133 BOOL old_socket_found = cmpl != 0;
134
135 if(!cmpl) {
136 cmpl = new socket_t(IPPROTO_UDP);
137 if(cmpl) {
138 cmpl->s = _socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
139 if(cmpl->s == INVALID_SOCKET) {
140 delete cmpl;
141 cmpl = 0;
142 ok = false;
143 } else {
144 cmpl->src_port = src_port;
145 cmpl->dest_port = dest_port;
146 add_socket( cmpl );
147 }
148 } else {
149 ok = false;
150 }
151 }
152
153 if(ok) {
154 cmpl->src_port = src_port;
155 cmpl->dest_port = dest_port;
156 cmpl->ip_src = ntohl(udp->ip.src);
157 cmpl->ip_dest = ntohl(udp->ip.dest);
158
159 struct sockaddr_in to;
160 memset( &to, 0, sizeof(to) );
161 to.sin_family = AF_INET;
162 to.sin_port = udp->dest_port;
163 to.sin_addr.s_addr = udp->ip.dest;
164
165 char *data = (char *)udp + sizeof(udp_t);
166 int dlen = len - sizeof(udp_t);
167
168 // ttl changed, update checksum
169 make_udp_checksum( udp );
170
171 cmpl->set_ttl( udp->ip.ttl );
172
173 bool please_close = true;
174 /*
175 Note that broadcast messages fill fail, no setsockopt(SO_BROADCAST).
176 That's exactly what I want.
177 */
178 if(SOCKET_ERROR != _sendto( cmpl->s, data, dlen, 0, (struct sockaddr *)&to, sizeof(to) )) {
179 if(old_socket_found) {
180 // This socket is not overlapped.
181 please_close = false;
182 } else {
183 if(cmpl->b_recfrom()) please_close = false;
184 }
185 cmpl->socket_ttl = GetTickCount() + 60000L;
186 } else {
187 int socket_error = _WSAGetLastError();
188 D(bug("_sendto() completed with error %d\r\n", socket_error));
189 // TODO: check this out: error_winsock_2_icmp() uses router_ip_address
190 // as source ip; but it's probably allright
191 error_winsock_2_icmp( socket_error, (ip_t *)udp, len );
192 }
193 if(please_close) {
194 delete_socket(cmpl);
195 }
196 }
197 }
198
199 void init_udp()
200 {
201 }
202
203 void final_udp()
204 {
205 }