1 |
|
/* |
2 |
|
* ether.cpp - Ethernet device driver |
3 |
|
* |
4 |
< |
* Basilisk II (C) 1997-2001 Christian Bauer |
4 |
> |
* Basilisk II (C) 1997-2002 Christian Bauer |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
25 |
|
* Inside AppleTalk, chapter 3 "Ethernet and TokenTalk Link Access Protocols" |
26 |
|
*/ |
27 |
|
|
28 |
– |
#include <string.h> |
29 |
– |
|
28 |
|
#include "sysdeps.h" |
29 |
< |
#include "cpu_emulation.h" |
30 |
< |
#include "main.h" |
31 |
< |
#include "macos_util.h" |
34 |
< |
#include "emul_op.h" |
35 |
< |
#include "prefs.h" |
36 |
< |
#include "ether.h" |
37 |
< |
#include "ether_defs.h" |
29 |
> |
|
30 |
> |
#include <string.h> |
31 |
> |
#include <map> |
32 |
|
|
33 |
|
#if SUPPORTS_UDP_TUNNEL |
34 |
|
#include <netinet/in.h> |
38 |
|
#include <errno.h> |
39 |
|
#endif |
40 |
|
|
41 |
< |
#include <map> |
41 |
> |
#include "cpu_emulation.h" |
42 |
> |
#include "main.h" |
43 |
> |
#include "macos_util.h" |
44 |
> |
#include "emul_op.h" |
45 |
> |
#include "prefs.h" |
46 |
> |
#include "ether.h" |
47 |
> |
#include "ether_defs.h" |
48 |
|
|
49 |
|
#ifndef NO_STD_NAMESPACE |
50 |
|
using std::map; |
56 |
|
#define MONITOR 0 |
57 |
|
|
58 |
|
|
59 |
+ |
#ifdef __BEOS__ |
60 |
+ |
#define CLOSESOCKET closesocket |
61 |
+ |
#else |
62 |
+ |
#define CLOSESOCKET close |
63 |
+ |
#endif |
64 |
+ |
|
65 |
+ |
|
66 |
|
// Global variables |
67 |
|
uint8 ether_addr[6]; // Ethernet address (set by ether_init()) |
68 |
|
static bool net_open = false; // Flag: initialization succeeded, network device open (set by EtherInit()) |
108 |
|
sa.sin_port = htons(udp_port); |
109 |
|
if (bind(udp_socket, (struct sockaddr *)&sa, sizeof(sa)) < 0) { |
110 |
|
perror("bind"); |
111 |
< |
close(udp_socket); |
111 |
> |
CLOSESOCKET(udp_socket); |
112 |
|
udp_socket = -1; |
113 |
|
return; |
114 |
|
} |
137 |
|
|
138 |
|
// Set socket options |
139 |
|
int on = 1; |
140 |
+ |
#ifdef __BEOS__ |
141 |
+ |
setsockopt(udp_socket, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(on)); |
142 |
+ |
#else |
143 |
|
setsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); |
144 |
|
ioctl(udp_socket, FIONBIO, &on); |
145 |
+ |
#endif |
146 |
|
|
147 |
|
// Start thread for packet reception |
148 |
|
if (!ether_start_udp_thread(udp_socket)) { |
149 |
< |
close(udp_socket); |
149 |
> |
CLOSESOCKET(udp_socket); |
150 |
|
udp_socket = -1; |
151 |
|
return; |
152 |
|
} |
170 |
|
if (udp_tunnel) { |
171 |
|
if (udp_socket >= 0) { |
172 |
|
ether_stop_udp_thread(); |
173 |
< |
close(udp_socket); |
173 |
> |
CLOSESOCKET(udp_socket); |
174 |
|
udp_socket = -1; |
175 |
|
} |
176 |
|
} else |
182 |
|
|
183 |
|
|
184 |
|
/* |
185 |
< |
* Check whether Ethernet address is AppleTalk broadcast address |
185 |
> |
* Reset |
186 |
> |
*/ |
187 |
> |
|
188 |
> |
void EtherReset(void) |
189 |
> |
{ |
190 |
> |
udp_protocols.clear(); |
191 |
> |
ether_reset(); |
192 |
> |
} |
193 |
> |
|
194 |
> |
|
195 |
> |
/* |
196 |
> |
* Check whether Ethernet address is AppleTalk or Ethernet broadcast address |
197 |
|
*/ |
198 |
|
|
199 |
|
static inline bool is_apple_talk_broadcast(uint8 *p) |
202 |
|
&& p[3] == 0xff && p[4] == 0xff && p[5] == 0xff; |
203 |
|
} |
204 |
|
|
205 |
+ |
static inline bool is_ethernet_broadcast(uint8 *p) |
206 |
+ |
{ |
207 |
+ |
return p[0] == 0xff && p[1] == 0xff && p[2] == 0xff |
208 |
+ |
&& p[3] == 0xff && p[4] == 0xff && p[5] == 0xff; |
209 |
+ |
} |
210 |
+ |
|
211 |
|
|
212 |
|
/* |
213 |
|
* Driver Open() routine |
307 |
|
|
308 |
|
case kENetWrite: { // Transmit raw Ethernet packet |
309 |
|
uint32 wds = ReadMacInt32(pb + ePointer); |
310 |
< |
D(bug(" EtherWrite\n")); |
310 |
> |
D(bug(" EtherWrite ")); |
311 |
|
if (ReadMacInt16(wds) < 14) |
312 |
|
return eLenErr; // Header incomplete |
313 |
+ |
|
314 |
+ |
// Set source address |
315 |
+ |
uint32 hdr = ReadMacInt32(wds + 2); |
316 |
+ |
Host2Mac_memcpy(hdr + 6, ether_addr, 6); |
317 |
+ |
D(bug("to %08x%04x, type %04x\n", ReadMacInt32(hdr), ReadMacInt16(hdr + 4), ReadMacInt16(hdr + 12))); |
318 |
+ |
|
319 |
|
if (net_open) { |
320 |
|
#if SUPPORTS_UDP_TUNNEL |
321 |
|
if (udp_tunnel) { |
324 |
|
uint8 packet[1514]; |
325 |
|
int len = ether_wds_to_buffer(wds, packet); |
326 |
|
|
327 |
< |
// Set source address and extract destination address |
294 |
< |
memcpy(packet + 6, ether_addr, 6); |
327 |
> |
// Extract destination address |
328 |
|
uint32 dest_ip; |
329 |
|
if (packet[0] == 'B' && packet[1] == '2') |
330 |
|
dest_ip = (packet[2] << 24) | (packet[3] << 16) | (packet[4] << 8) | packet[5]; |
331 |
< |
else if (is_apple_talk_broadcast(packet)) |
331 |
> |
else if (is_apple_talk_broadcast(packet) || is_ethernet_broadcast(packet)) |
332 |
|
dest_ip = INADDR_BROADCAST; |
333 |
|
else |
334 |
|
return eMultiErr; |