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.7 by cebix, 2001-07-13T18:49:22Z

# Line 25 | Line 25
25   *    Inside AppleTalk, chapter 3 "Ethernet and TokenTalk Link Access Protocols"
26   */
27  
28 + #include "sysdeps.h"
29 +
30   #include <string.h>
31 + #include <map>
32 +
33 + #if SUPPORTS_UDP_TUNNEL
34 + #include <netinet/in.h>
35 + #include <sys/socket.h>
36 + #include <sys/ioctl.h>
37 + #include <netdb.h>
38 + #include <errno.h>
39 + #endif
40  
30 #include "sysdeps.h"
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;
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 > // 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 > *  Reset
175 > */
176 >
177 > void EtherReset(void)
178 > {
179 >        udp_protocols.clear();
180 >        ether_reset();
181 > }
182 >
183 >
184 > /*
185 > *  Check whether Ethernet address is AppleTalk or Ethernet broadcast address
186 > */
187 >
188 > static inline bool is_apple_talk_broadcast(uint8 *p)
189 > {
190 >        return p[0] == 0x09 && p[1] == 0x00 && p[2] == 0x07
191 >            && p[3] == 0xff && p[4] == 0xff && p[5] == 0xff;
192 > }
193  
194 < uint32 ether_data = 0;  // Mac address of driver data in MacOS RAM
194 > static inline bool is_ethernet_broadcast(uint8 *p)
195 > {
196 >        return p[0] == 0xff && p[1] == 0xff && p[2] == 0xff
197 >            && p[3] == 0xff && p[4] == 0xff && p[5] == 0xff;
198 > }
199  
200  
201   /*
# Line 61 | Line 213 | int16 EtherOpen(uint32 pb, uint32 dce)
213          if (r.a[0] == 0)
214                  return openErr;
215          ether_data = r.a[0];
216 <        D(bug(" data %08lx\n", ether_data));
216 >        D(bug(" data %08x\n", ether_data));
217  
218          WriteMacInt16(ether_data + ed_DeferredTask + qType, dtQType);
219          WriteMacInt32(ether_data + ed_DeferredTask + dtAddr, ether_data + ed_Code);
# Line 99 | Line 251 | int16 EtherControl(uint32 pb, uint32 dce
251          uint16 code = ReadMacInt16(pb + csCode);
252          D(bug("EtherControl %d\n", code));
253          switch (code) {
254 <                case 1:         // KillIO
254 >                case 1:                                 // KillIO
255                          return -1;
256  
257                  case kENetAddMulti:             // Add multicast address
258 <                        D(bug("AddMulti %08lx%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
259 <                        if (net_open)
258 >                        D(bug(" AddMulti %08x%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
259 >                        if (net_open && !udp_tunnel)
260                                  return ether_add_multicast(pb);
261 <                        else
110 <                                return noErr;
261 >                        return noErr;
262  
263                  case kENetDelMulti:             // Delete multicast address
264 <                        D(bug("DelMulti %08lx%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
265 <                        if (net_open)
264 >                        D(bug(" DelMulti %08x%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
265 >                        if (net_open && !udp_tunnel)
266                                  return ether_del_multicast(pb);
267 <                        else
268 <                                return noErr;
267 >                        return noErr;
268 >
269 >                case kENetAttachPH: {   // Attach protocol handler
270 >                        uint16 type = ReadMacInt16(pb + eProtType);
271 >                        uint32 handler = ReadMacInt32(pb + ePointer);
272 >                        D(bug(" AttachPH prot %04x, handler %08x\n", type, handler));
273 >                        if (net_open) {
274 >                                if (udp_tunnel) {
275 >                                        if (udp_protocols.find(type) != udp_protocols.end())
276 >                                                return lapProtErr;
277 >                                        udp_protocols[type] = handler;
278 >                                } else
279 >                                        return ether_attach_ph(type, handler);
280 >                        }
281 >                        return noErr;
282 >                }
283  
284 <                case kENetAttachPH:             // Attach protocol handler
285 <                        D(bug("AttachPH prot %04x, handler %08lx\n", ReadMacInt16(pb + eProtType), ReadMacInt32(pb + ePointer)));
286 <                        if (net_open)
287 <                                return ether_attach_ph(ReadMacInt16(pb + eProtType), ReadMacInt32(pb + ePointer));
288 <                        else
289 <                                return noErr;
290 <
291 <                case kENetDetachPH:             // Detach protocol handler
292 <                        D(bug("DetachPH prot %04x\n", ReadMacInt16(pb + eProtType)));
293 <                        if (net_open)
294 <                                return ether_detach_ph(ReadMacInt16(pb + eProtType));
295 <                        else
296 <                                return noErr;
297 <
298 <                case kENetWrite:                // Transmit raw Ethernet packet
299 <                        D(bug("EtherWrite\n"));
300 <                        if (ReadMacInt16(ReadMacInt32(pb + ePointer)) < 14)
284 >                case kENetDetachPH: {   // Detach protocol handler
285 >                        uint16 type = ReadMacInt16(pb + eProtType);
286 >                        D(bug(" DetachPH prot %04x\n", type));
287 >                        if (net_open) {
288 >                                if (udp_tunnel) {
289 >                                        if (udp_protocols.erase(type) == 0)
290 >                                                return lapProtErr;
291 >                                } else
292 >                                        return ether_detach_ph(type);
293 >                        }
294 >                        return noErr;
295 >                }
296 >
297 >                case kENetWrite: {              // Transmit raw Ethernet packet
298 >                        uint32 wds = ReadMacInt32(pb + ePointer);
299 >                        D(bug(" EtherWrite "));
300 >                        if (ReadMacInt16(wds) < 14)
301                                  return eLenErr; // Header incomplete
302 <                        if (net_open)
303 <                                return ether_write(ReadMacInt32(pb + ePointer));
304 <                        else
305 <                                return noErr;
302 >
303 >                        // Set source address
304 >                        uint32 hdr = ReadMacInt32(wds + 2);
305 >                        Host2Mac_memcpy(hdr + 6, ether_addr, 6);
306 >                        D(bug("to %08x%04x, type %04x\n", ReadMacInt32(hdr), ReadMacInt16(hdr + 4), ReadMacInt16(hdr + 12)));
307 >
308 >                        if (net_open) {
309 > #if SUPPORTS_UDP_TUNNEL
310 >                                if (udp_tunnel) {
311 >
312 >                                        // Copy packet to buffer
313 >                                        uint8 packet[1514];
314 >                                        int len = ether_wds_to_buffer(wds, packet);
315 >
316 >                                        // Extract destination address
317 >                                        uint32 dest_ip;
318 >                                        if (packet[0] == 'B' && packet[1] == '2')
319 >                                                dest_ip = (packet[2] << 24) | (packet[3] << 16) | (packet[4] << 8) | packet[5];
320 >                                        else if (is_apple_talk_broadcast(packet) || is_ethernet_broadcast(packet))
321 >                                                dest_ip = INADDR_BROADCAST;
322 >                                        else
323 >                                                return eMultiErr;
324 >
325 > #if MONITOR
326 >                                        bug("Sending Ethernet packet:\n");
327 >                                        for (int i=0; i<len; i++) {
328 >                                                bug("%02x ", packet[i]);
329 >                                        }
330 >                                        bug("\n");
331 > #endif
332 >
333 >                                        // Send packet
334 >                                        struct sockaddr_in sa;
335 >                                        sa.sin_family = AF_INET;
336 >                                        sa.sin_addr.s_addr = htonl(dest_ip);
337 >                                        sa.sin_port = htons(udp_port);
338 >                                        if (sendto(udp_socket, packet, len, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
339 >                                                D(bug("WARNING: Couldn't transmit packet\n"));
340 >                                                return excessCollsns;
341 >                                        }
342 >                                } else
343 > #endif
344 >                                        return ether_write(wds);
345 >                        }
346 >                        return noErr;
347 >                }
348  
349                  case kENetGetInfo: {    // Get device information/statistics
350 <                        D(bug("GetInfo buf %08lx, size %d\n", ReadMacInt32(pb + ePointer), ReadMacInt16(pb + eBuffSize)));
350 >                        D(bug(" GetInfo buf %08x, size %d\n", ReadMacInt32(pb + ePointer), ReadMacInt16(pb + eBuffSize)));
351  
352                          // Collect info (only ethernet address)
353                          uint8 buf[18];
# Line 157 | Line 364 | int16 EtherControl(uint32 pb, uint32 dce
364                  }
365  
366                  case kENetSetGeneral:   // Set general mode (always in general mode)
367 <                        D(bug("SetGeneral\n"));
367 >                        D(bug(" SetGeneral\n"));
368                          return noErr;
369  
370                  default:
# Line 173 | Line 380 | int16 EtherControl(uint32 pb, uint32 dce
380  
381   void EtherReadPacket(uint8 **src, uint32 &dest, uint32 &len, uint32 &remaining)
382   {
383 <        D(bug("EtherReadPacket src %08lx, dest %08lx, len %08lx, remaining %08lx\n", *src, dest, len, remaining));
383 >        D(bug("EtherReadPacket src %p, dest %08x, len %08x, remaining %08x\n", *src, dest, len, remaining));
384          uint32 todo = len > remaining ? remaining : len;
385          Host2Mac_memcpy(dest, *src, todo);
386          *src += todo;
# Line 181 | Line 388 | void EtherReadPacket(uint8 **src, uint32
388          len -= todo;
389          remaining -= todo;
390   }
391 +
392 +
393 + #if SUPPORTS_UDP_TUNNEL
394 + /*
395 + *  Read packet from UDP socket
396 + */
397 +
398 + void ether_udp_read(uint8 *packet, int length, struct sockaddr_in *from)
399 + {
400 +        // Drop packets sent by us
401 +        if (memcmp(packet + 6, ether_addr, 6) == 0)
402 +                return;
403 +
404 + #if MONITOR
405 +        bug("Receiving Ethernet packet:\n");
406 +        for (int i=0; i<length; i++) {
407 +                bug("%02x ", packet[i]);
408 +        }
409 +        bug("\n");
410 + #endif
411 +
412 +        // Get packet type
413 +        uint16 type = (packet[12] << 8) | packet[13];
414 +
415 +        // Look for protocol
416 +        uint16 search_type = (type <= 1500 ? 0 : type);
417 +        if (udp_protocols.find(search_type) == udp_protocols.end())
418 +                return;
419 +        uint32 handler = udp_protocols[search_type];
420 +        if (handler == 0)
421 +                return;
422 +
423 +        // Copy header to RHA
424 +        Host2Mac_memcpy(ether_data + ed_RHA, packet, 14);
425 +        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)));
426 +
427 +        // Call protocol handler
428 +        M68kRegisters r;
429 +        r.d[0] = type;                                                                  // Packet type
430 +        r.d[1] = length - 14;                                                   // Remaining packet length (without header, for ReadPacket)
431 +        r.a[0] = (uint32)packet + 14;                                   // Pointer to packet (host address, for ReadPacket)
432 +        r.a[3] = ether_data + ed_RHA + 14;                              // Pointer behind header in RHA
433 +        r.a[4] = ether_data + ed_ReadPacket;                    // Pointer to ReadPacket/ReadRest routines
434 +        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]));
435 +        Execute68k(handler, &r);
436 + }
437 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines