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.6 by cebix, 2001-07-13T15:39:21Z

# 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 < uint32 ether_data = 0;  // Mac address of driver data in MacOS RAM
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 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  
195   /*
# Line 61 | Line 207 | int16 EtherOpen(uint32 pb, uint32 dce)
207          if (r.a[0] == 0)
208                  return openErr;
209          ether_data = r.a[0];
210 <        D(bug(" data %08lx\n", ether_data));
210 >        D(bug(" data %08x\n", ether_data));
211  
212          WriteMacInt16(ether_data + ed_DeferredTask + qType, dtQType);
213          WriteMacInt32(ether_data + ed_DeferredTask + dtAddr, ether_data + ed_Code);
# Line 99 | Line 245 | int16 EtherControl(uint32 pb, uint32 dce
245          uint16 code = ReadMacInt16(pb + csCode);
246          D(bug("EtherControl %d\n", code));
247          switch (code) {
248 <                case 1:         // KillIO
248 >                case 1:                                 // KillIO
249                          return -1;
250  
251                  case kENetAddMulti:             // Add multicast address
252 <                        D(bug("AddMulti %08lx%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
253 <                        if (net_open)
252 >                        D(bug(" AddMulti %08x%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
253 >                        if (net_open && !udp_tunnel)
254                                  return ether_add_multicast(pb);
255 <                        else
110 <                                return noErr;
255 >                        return noErr;
256  
257                  case kENetDelMulti:             // Delete multicast address
258 <                        D(bug("DelMulti %08lx%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
259 <                        if (net_open)
258 >                        D(bug(" DelMulti %08x%04x\n", ReadMacInt32(pb + eMultiAddr), ReadMacInt16(pb + eMultiAddr + 4)));
259 >                        if (net_open && !udp_tunnel)
260                                  return ether_del_multicast(pb);
261 <                        else
262 <                                return noErr;
261 >                        return noErr;
262 >
263 >                case kENetAttachPH: {   // Attach protocol handler
264 >                        uint16 type = ReadMacInt16(pb + eProtType);
265 >                        uint32 handler = ReadMacInt32(pb + ePointer);
266 >                        D(bug(" AttachPH prot %04x, handler %08x\n", type, handler));
267 >                        if (net_open) {
268 >                                if (udp_tunnel) {
269 >                                        if (udp_protocols.find(type) != udp_protocols.end())
270 >                                                return lapProtErr;
271 >                                        udp_protocols[type] = handler;
272 >                                } else
273 >                                        return ether_attach_ph(type, handler);
274 >                        }
275 >                        return noErr;
276 >                }
277  
278 <                case kENetAttachPH:             // Attach protocol handler
279 <                        D(bug("AttachPH prot %04x, handler %08lx\n", ReadMacInt16(pb + eProtType), ReadMacInt32(pb + ePointer)));
280 <                        if (net_open)
281 <                                return ether_attach_ph(ReadMacInt16(pb + eProtType), ReadMacInt32(pb + ePointer));
282 <                        else
283 <                                return noErr;
284 <
285 <                case kENetDetachPH:             // Detach protocol handler
286 <                        D(bug("DetachPH prot %04x\n", ReadMacInt16(pb + eProtType)));
287 <                        if (net_open)
288 <                                return ether_detach_ph(ReadMacInt16(pb + eProtType));
289 <                        else
290 <                                return noErr;
291 <
292 <                case kENetWrite:                // Transmit raw Ethernet packet
293 <                        D(bug("EtherWrite\n"));
294 <                        if (ReadMacInt16(ReadMacInt32(pb + ePointer)) < 14)
278 >                case kENetDetachPH: {   // Detach protocol handler
279 >                        uint16 type = ReadMacInt16(pb + eProtType);
280 >                        D(bug(" DetachPH prot %04x\n", type));
281 >                        if (net_open) {
282 >                                if (udp_tunnel) {
283 >                                        if (udp_protocols.erase(type) == 0)
284 >                                                return lapProtErr;
285 >                                } else
286 >                                        return ether_detach_ph(type);
287 >                        }
288 >                        return noErr;
289 >                }
290 >
291 >                case kENetWrite: {              // Transmit raw Ethernet packet
292 >                        uint32 wds = ReadMacInt32(pb + ePointer);
293 >                        D(bug(" EtherWrite\n"));
294 >                        if (ReadMacInt16(wds) < 14)
295                                  return eLenErr; // Header incomplete
296 <                        if (net_open)
297 <                                return ether_write(ReadMacInt32(pb + ePointer));
298 <                        else
299 <                                return noErr;
296 >                        if (net_open) {
297 > #if SUPPORTS_UDP_TUNNEL
298 >                                if (udp_tunnel) {
299 >
300 >                                        // Copy packet to buffer
301 >                                        uint8 packet[1514];
302 >                                        int len = ether_wds_to_buffer(wds, packet);
303 >
304 >                                        // Set source address and extract destination address
305 >                                        memcpy(packet + 6, ether_addr, 6);
306 >                                        uint32 dest_ip;
307 >                                        if (packet[0] == 'B' && packet[1] == '2')
308 >                                                dest_ip = (packet[2] << 24) | (packet[3] << 16) | (packet[4] << 8) | packet[5];
309 >                                        else if (is_apple_talk_broadcast(packet))
310 >                                                dest_ip = INADDR_BROADCAST;
311 >                                        else
312 >                                                return eMultiErr;
313 >
314 > #if MONITOR
315 >                                        bug("Sending Ethernet packet:\n");
316 >                                        for (int i=0; i<len; i++) {
317 >                                                bug("%02x ", packet[i]);
318 >                                        }
319 >                                        bug("\n");
320 > #endif
321 >
322 >                                        // Send packet
323 >                                        struct sockaddr_in sa;
324 >                                        sa.sin_family = AF_INET;
325 >                                        sa.sin_addr.s_addr = htonl(dest_ip);
326 >                                        sa.sin_port = htons(udp_port);
327 >                                        if (sendto(udp_socket, packet, len, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
328 >                                                D(bug("WARNING: Couldn't transmit packet\n"));
329 >                                                return excessCollsns;
330 >                                        }
331 >                                } else
332 > #endif
333 >                                        return ether_write(wds);
334 >                        }
335 >                        return noErr;
336 >                }
337  
338                  case kENetGetInfo: {    // Get device information/statistics
339 <                        D(bug("GetInfo buf %08lx, size %d\n", ReadMacInt32(pb + ePointer), ReadMacInt16(pb + eBuffSize)));
339 >                        D(bug(" GetInfo buf %08x, size %d\n", ReadMacInt32(pb + ePointer), ReadMacInt16(pb + eBuffSize)));
340  
341                          // Collect info (only ethernet address)
342                          uint8 buf[18];
# Line 157 | Line 353 | int16 EtherControl(uint32 pb, uint32 dce
353                  }
354  
355                  case kENetSetGeneral:   // Set general mode (always in general mode)
356 <                        D(bug("SetGeneral\n"));
356 >                        D(bug(" SetGeneral\n"));
357                          return noErr;
358  
359                  default:
# Line 173 | Line 369 | int16 EtherControl(uint32 pb, uint32 dce
369  
370   void EtherReadPacket(uint8 **src, uint32 &dest, uint32 &len, uint32 &remaining)
371   {
372 <        D(bug("EtherReadPacket src %08lx, dest %08lx, len %08lx, remaining %08lx\n", *src, dest, len, remaining));
372 >        D(bug("EtherReadPacket src %p, dest %08x, len %08x, remaining %08x\n", *src, dest, len, remaining));
373          uint32 todo = len > remaining ? remaining : len;
374          Host2Mac_memcpy(dest, *src, todo);
375          *src += todo;
# Line 181 | Line 377 | void EtherReadPacket(uint8 **src, uint32
377          len -= todo;
378          remaining -= todo;
379   }
380 +
381 +
382 + #if SUPPORTS_UDP_TUNNEL
383 + /*
384 + *  Read packet from UDP socket
385 + */
386 +
387 + void ether_udp_read(uint8 *packet, int length, struct sockaddr_in *from)
388 + {
389 +        // Drop packets sent by us
390 +        if (memcmp(packet + 6, ether_addr, 6) == 0)
391 +                return;
392 +
393 + #if MONITOR
394 +        bug("Receiving Ethernet packet:\n");
395 +        for (int i=0; i<length; i++) {
396 +                bug("%02x ", packet[i]);
397 +        }
398 +        bug("\n");
399 + #endif
400 +
401 +        // Get packet type
402 +        uint16 type = (packet[12] << 8) | packet[13];
403 +
404 +        // Look for protocol
405 +        uint16 search_type = (type <= 1500 ? 0 : type);
406 +        if (udp_protocols.find(search_type) == udp_protocols.end())
407 +                return;
408 +        uint32 handler = udp_protocols[search_type];
409 +        if (handler == 0)
410 +                return;
411 +
412 +        // Copy header to RHA
413 +        Host2Mac_memcpy(ether_data + ed_RHA, packet, 14);
414 +        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)));
415 +
416 +        // Call protocol handler
417 +        M68kRegisters r;
418 +        r.d[0] = type;                                                                  // Packet type
419 +        r.d[1] = length - 14;                                                   // Remaining packet length (without header, for ReadPacket)
420 +        r.a[0] = (uint32)packet + 14;                                   // Pointer to packet (host address, for ReadPacket)
421 +        r.a[3] = ether_data + ed_RHA + 14;                              // Pointer behind header in RHA
422 +        r.a[4] = ether_data + ed_ReadPacket;                    // Pointer to ReadPacket/ReadRest routines
423 +        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]));
424 +        Execute68k(handler, &r);
425 + }
426 + #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines