ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/ether.cpp
(Generate patch)

Comparing BasiliskII/src/ether.cpp (file contents):
Revision 1.4 by cebix, 2001-02-02T20:52:57Z vs.
Revision 1.5 by cebix, 2001-07-12T19:48:25Z

# Line 32 | Line 32
32   #include "main.h"
33   #include "macos_util.h"
34   #include "emul_op.h"
35 + #include "prefs.h"
36   #include "ether.h"
37   #include "ether_defs.h"
38  
39 + #if SUPPORTS_UDP_TUNNEL
40 + #include <netinet/in.h>
41 + #include <sys/socket.h>
42 + #include <sys/ioctl.h>
43 + #include <netdb.h>
44 + #include <errno.h>
45 + #endif
46 +
47 + #include <map>
48 +
49 + #ifndef NO_STD_NAMESPACE
50 + using std::map;
51 + #endif
52 +
53   #define DEBUG 0
54   #include "debug.h"
55  
56 + #define MONITOR 0
57 +
58  
59   // Global variables
60 < uint8 ether_addr[6];    // Ethernet address (set by EtherInit())
61 < bool net_open = false;  // Flag: initialization succeeded, network device open (set by EtherInit())
60 > uint8 ether_addr[6];                    // Ethernet address (set by ether_init())
61 > static bool net_open = false;   // Flag: initialization succeeded, network device open (set by EtherInit())
62 >
63 > static bool udp_tunnel = false; // Flag: tunnelling AppleTalk over UDP using BSD socket API
64 > static uint16 udp_port;
65 > static int udp_socket = -1;
66 >
67 > // Mac address of driver data in MacOS RAM
68 > uint32 ether_data = 0;
69  
70 < uint32 ether_data = 0;  // Mac address of driver data in MacOS RAM
70 > // Attached network protocols for UDP tunneling, maps protocol type to MacOS handler address
71 > static map<uint16, uint32> udp_protocols;
72 >
73 >
74 > /*
75 > *  Initialization
76 > */
77 >
78 > void EtherInit(void)
79 > {
80 >        net_open = false;
81 >        udp_tunnel = false;
82 >
83 > #if SUPPORTS_UDP_TUNNEL
84 >        // UDP tunnelling requested?
85 >        if (PrefsFindBool("udptunnel")) {
86 >                udp_tunnel = true;
87 >                udp_port = PrefsFindInt32("udpport");
88 >
89 >                // Open UDP socket
90 >                udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
91 >                if (udp_socket < 0) {
92 >                        perror("socket");
93 >                        return;
94 >                }
95 >
96 >                // Bind to specified address and port
97 >                struct sockaddr_in sa;
98 >                memset(&sa, 0, sizeof(sa));
99 >                sa.sin_family = AF_INET;
100 >                sa.sin_addr.s_addr = INADDR_ANY;
101 >                sa.sin_port = htons(udp_port);
102 >                if (bind(udp_socket, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
103 >                        perror("bind");
104 >                        close(udp_socket);
105 >                        udp_socket = -1;
106 >                        return;
107 >                }
108 >
109 >                // Retrieve local IP address (or at least one of them)
110 >                socklen_t sa_len = sizeof(sa);
111 >                getsockname(udp_socket, (struct sockaddr *)&sa, &sa_len);
112 >                uint32 udp_ip = sa.sin_addr.s_addr;
113 >                if (udp_ip == INADDR_ANY || udp_ip == INADDR_LOOPBACK) {
114 >                        char name[256];
115 >                        gethostname(name, sizeof(name));
116 >                        struct hostent *local = gethostbyname(name);
117 >                        if (local)
118 >                                udp_ip = *(uint32 *)local->h_addr_list[0];
119 >                }
120 >                udp_ip = ntohl(udp_ip);
121 >
122 >                // Construct dummy Ethernet address from local IP address
123 >                ether_addr[0] = 'B';
124 >                ether_addr[1] = '2';
125 >                ether_addr[2] = udp_ip >> 24;
126 >                ether_addr[3] = udp_ip >> 16;
127 >                ether_addr[4] = udp_ip >> 8;
128 >                ether_addr[5] = udp_ip;
129 >                D(bug("Ethernet address %02x %02x %02x %02x %02x %02x\n", ether_addr[0], ether_addr[1], ether_addr[2], ether_addr[3], ether_addr[4], ether_addr[5]));
130 >
131 >                // Set socket options
132 >                int on = 1;
133 >                setsockopt(udp_socket, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
134 >                ioctl(udp_socket, FIONBIO, &on);
135 >
136 >                // Start thread for packet reception
137 >                if (!ether_start_udp_thread(udp_socket)) {
138 >                        close(udp_socket);
139 >                        udp_socket = -1;
140 >                        return;
141 >                }
142 >
143 >                net_open = true;
144 >        } else
145 > #endif
146 >                if (ether_init())
147 >                        net_open = true;
148 > }
149 >
150 >
151 > /*
152 > *  Deinitialization
153 > */
154 >
155 > void EtherExit(void)
156 > {
157 >        if (net_open) {
158 > #if SUPPORTS_UDP_TUNNEL
159 >                if (udp_tunnel) {
160 >                        if (udp_socket >= 0) {
161 >                                ether_stop_udp_thread();
162 >                                close(udp_socket);
163 >                                udp_socket = -1;
164 >                        }
165 >                } else
166 > #endif
167 >                        ether_exit();
168 >                net_open = false;
169 >        }
170 > }
171 >
172 >
173 > /*
174 > *  Check whether Ethernet address is AppleTalk broadcast address
175 > */
176 >
177 > static inline bool is_apple_talk_broadcast(uint8 *p)
178 > {
179 >        return p[0] == 0x09 && p[1] == 0x00 && p[2] == 0x07
180 >            && p[3] == 0xff && p[4] == 0xff && p[5] == 0xff;
181 > }
182  
183  
184   /*
# Line 61 | Line 196 | int16 EtherOpen(uint32 pb, uint32 dce)
196          if (r.a[0] == 0)
197                  return openErr;
198          ether_data = r.a[0];
199 <        D(bug(" data %08lx\n", ether_data));
199 >        D(bug(" data %08x\n", ether_data));
200  
201          WriteMacInt16(ether_data + ed_DeferredTask + qType, dtQType);
202          WriteMacInt32(ether_data + ed_DeferredTask + dtAddr, ether_data + ed_Code);
# Line 99 | Line 234 | int16 EtherControl(uint32 pb, uint32 dce
234          uint16 code = ReadMacInt16(pb + csCode);
235          D(bug("EtherControl %d\n", code));
236          switch (code) {
237 <                case 1:         // KillIO
237 >                case 1:                                 // KillIO
238                          return -1;
239  
240                  case kENetAddMulti:             // Add multicast address
241 <                        D(bug("AddMulti %08lx%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
242 <                        if (net_open)
241 >                        D(bug(" AddMulti %08x%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
242 >                        if (net_open && !udp_tunnel)
243                                  return ether_add_multicast(pb);
244 <                        else
110 <                                return noErr;
244 >                        return noErr;
245  
246                  case kENetDelMulti:             // Delete multicast address
247 <                        D(bug("DelMulti %08lx%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
248 <                        if (net_open)
247 >                        D(bug(" DelMulti %08x%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
248 >                        if (net_open && !udp_tunnel)
249                                  return ether_del_multicast(pb);
250 <                        else
251 <                                return noErr;
250 >                        return noErr;
251 >
252 >                case kENetAttachPH: {   // Attach protocol handler
253 >                        uint16 type = ReadMacInt16(pb + eProtType);
254 >                        uint32 handler = ReadMacInt32(pb + ePointer);
255 >                        D(bug(" AttachPH prot %04x, handler %08x\n", type, handler));
256 >                        if (net_open) {
257 >                                if (udp_tunnel) {
258 >                                        if (udp_protocols.find(type) != udp_protocols.end())
259 >                                                return lapProtErr;
260 >                                        udp_protocols[type] = handler;
261 >                                } else
262 >                                        return ether_attach_ph(type, handler);
263 >                        }
264 >                        return noErr;
265 >                }
266 >
267 >                case kENetDetachPH: {   // Detach protocol handler
268 >                        uint16 type = ReadMacInt16(pb + eProtType);
269 >                        D(bug(" DetachPH prot %04x\n", type));
270 >                        if (net_open) {
271 >                                if (udp_tunnel) {
272 >                                        if (udp_protocols.erase(type) == 0)
273 >                                                return lapProtErr;
274 >                                } else
275 >                                        return ether_detach_ph(type);
276 >                        }
277 >                        return noErr;
278 >                }
279  
280 <                case kENetAttachPH:             // Attach protocol handler
281 <                        D(bug("AttachPH prot %04x, handler %08lx\n", ReadMacInt16(pb + eProtType), ReadMacInt32(pb + ePointer)));
282 <                        if (net_open)
283 <                                return ether_attach_ph(ReadMacInt16(pb + eProtType), ReadMacInt32(pb + ePointer));
123 <                        else
124 <                                return noErr;
125 <
126 <                case kENetDetachPH:             // Detach protocol handler
127 <                        D(bug("DetachPH prot %04x\n", ReadMacInt16(pb + eProtType)));
128 <                        if (net_open)
129 <                                return ether_detach_ph(ReadMacInt16(pb + eProtType));
130 <                        else
131 <                                return noErr;
132 <
133 <                case kENetWrite:                // Transmit raw Ethernet packet
134 <                        D(bug("EtherWrite\n"));
135 <                        if (ReadMacInt16(ReadMacInt32(pb + ePointer)) < 14)
280 >                case kENetWrite: {              // Transmit raw Ethernet packet
281 >                        uint32 wds = ReadMacInt32(pb + ePointer);
282 >                        D(bug(" EtherWrite\n"));
283 >                        if (ReadMacInt16(wds) < 14)
284                                  return eLenErr; // Header incomplete
285 <                        if (net_open)
286 <                                return ether_write(ReadMacInt32(pb + ePointer));
287 <                        else
288 <                                return noErr;
285 >                        if (net_open) {
286 > #if SUPPORTS_UDP_TUNNEL
287 >                                if (udp_tunnel) {
288 >
289 >                                        // Copy packet to buffer
290 >                                        uint8 packet[1514];
291 >                                        int len = ether_wds_to_buffer(wds, packet);
292 >
293 >                                        // Set source address and extract destination address
294 >                                        memcpy(packet + 6, ether_addr, 6);
295 >                                        uint32 dest_ip;
296 >                                        if (packet[0] == 'B' && packet[1] == '2')
297 >                                                dest_ip = (packet[2] << 24) | (packet[3] << 16) | (packet[4] << 8) | packet[5];
298 >                                        else if (is_apple_talk_broadcast(packet))
299 >                                                dest_ip = INADDR_BROADCAST;
300 >                                        else
301 >                                                return eMultiErr;
302 >
303 > #if MONITOR
304 >                                        bug("Sending Ethernet packet:\n");
305 >                                        for (int i=0; i<len; i++) {
306 >                                                bug("%02x ", packet[i]);
307 >                                        }
308 >                                        bug("\n");
309 > #endif
310 >
311 >                                        // Send packet
312 >                                        struct sockaddr_in sa;
313 >                                        sa.sin_family = AF_INET;
314 >                                        sa.sin_addr.s_addr = htonl(dest_ip);
315 >                                        sa.sin_port = htons(udp_port);
316 >                                        if (sendto(udp_socket, packet, len, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
317 >                                                D(bug("WARNING: Couldn't transmit packet\n"));
318 >                                                return excessCollsns;
319 >                                        }
320 >                                } else
321 > #endif
322 >                                        return ether_write(wds);
323 >                        }
324 >                        return noErr;
325 >                }
326  
327                  case kENetGetInfo: {    // Get device information/statistics
328 <                        D(bug("GetInfo buf %08lx, size %d\n", ReadMacInt32(pb + ePointer), ReadMacInt16(pb + eBuffSize)));
328 >                        D(bug(" GetInfo buf %08x, size %d\n", ReadMacInt32(pb + ePointer), ReadMacInt16(pb + eBuffSize)));
329  
330                          // Collect info (only ethernet address)
331                          uint8 buf[18];
# Line 157 | Line 342 | int16 EtherControl(uint32 pb, uint32 dce
342                  }
343  
344                  case kENetSetGeneral:   // Set general mode (always in general mode)
345 <                        D(bug("SetGeneral\n"));
345 >                        D(bug(" SetGeneral\n"));
346                          return noErr;
347  
348                  default:
# Line 173 | Line 358 | int16 EtherControl(uint32 pb, uint32 dce
358  
359   void EtherReadPacket(uint8 **src, uint32 &dest, uint32 &len, uint32 &remaining)
360   {
361 <        D(bug("EtherReadPacket src %08lx, dest %08lx, len %08lx, remaining %08lx\n", *src, dest, len, remaining));
361 >        D(bug("EtherReadPacket src %p, dest %08x, len %08x, remaining %08x\n", *src, dest, len, remaining));
362          uint32 todo = len > remaining ? remaining : len;
363          Host2Mac_memcpy(dest, *src, todo);
364          *src += todo;
# Line 181 | Line 366 | void EtherReadPacket(uint8 **src, uint32
366          len -= todo;
367          remaining -= todo;
368   }
369 +
370 +
371 + #if SUPPORTS_UDP_TUNNEL
372 + /*
373 + *  Read packet from UDP socket
374 + */
375 +
376 + void ether_udp_read(uint8 *packet, int length, struct sockaddr_in *from)
377 + {
378 +        // Drop packets sent by us
379 +        if (memcmp(packet + 6, ether_addr, 6) == 0)
380 +                return;
381 +
382 + #if MONITOR
383 +        bug("Receiving Ethernet packet:\n");
384 +        for (int i=0; i<length; i++) {
385 +                bug("%02x ", packet[i]);
386 +        }
387 +        bug("\n");
388 + #endif
389 +
390 +        // Get packet type
391 +        uint16 type = (packet[12] << 8) | packet[13];
392 +
393 +        // Look for protocol
394 +        uint16 search_type = (type <= 1500 ? 0 : type);
395 +        if (udp_protocols.find(search_type) == udp_protocols.end())
396 +                return;
397 +        uint32 handler = udp_protocols[search_type];
398 +        if (handler == 0)
399 +                return;
400 +
401 +        // Copy header to RHA
402 +        Host2Mac_memcpy(ether_data + ed_RHA, packet, 14);
403 +        D(bug(" header %08x%04x %08x%04x %04x\n", ReadMacInt32(ether_data + ed_RHA), ReadMacInt16(ether_data + ed_RHA + 4), ReadMacInt32(ether_data + ed_RHA + 6), ReadMacInt16(ether_data + ed_RHA + 10), ReadMacInt16(ether_data + ed_RHA + 12)));
404 +
405 +        // Call protocol handler
406 +        M68kRegisters r;
407 +        r.d[0] = type;                                                                  // Packet type
408 +        r.d[1] = length - 14;                                                   // Remaining packet length (without header, for ReadPacket)
409 +        r.a[0] = (uint32)packet + 14;                                   // Pointer to packet (host address, for ReadPacket)
410 +        r.a[3] = ether_data + ed_RHA + 14;                              // Pointer behind header in RHA
411 +        r.a[4] = ether_data + ed_ReadPacket;                    // Pointer to ReadPacket/ReadRest routines
412 +        D(bug(" calling protocol handler %08x, type %08x, length %08x, data %08x, rha %08x, read_packet %08x\n", handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4]));
413 +        Execute68k(handler, &r);
414 + }
415 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines