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

Comparing BasiliskII/src/Unix/ether_unix.cpp (file contents):
Revision 1.2 by cebix, 2001-07-12T19:48:27Z vs.
Revision 1.20 by gbeauche, 2005-05-15T17:22:12Z

# Line 1 | Line 1
1   /*
2   *  ether_unix.cpp - Ethernet device driver, Unix specific stuff (Linux and FreeBSD)
3   *
4 < *  Basilisk II (C) 1997-2001 Christian Bauer
4 > *  Basilisk II (C) 1997-2005 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
# Line 20 | Line 20
20  
21   #include "sysdeps.h"
22  
23 < #include <sys/ioctl.h>
23 > #ifdef HAVE_SYS_POLL_H
24   #include <sys/poll.h>
25 + #endif
26 + #include <sys/ioctl.h>
27 + #include <sys/socket.h>
28 + #include <sys/wait.h>
29 + #include <netinet/in.h>
30   #include <pthread.h>
31   #include <semaphore.h>
32   #include <errno.h>
33   #include <stdio.h>
34 + #include <map>
35  
36 < #include <netinet/in.h>
37 < #include <sys/socket.h>
36 > #if defined(__FreeBSD__) || defined(sgi) || (defined(__APPLE__) && defined(__MACH__))
37 > #include <net/if.h>
38 > #endif
39  
40 < #if defined(__FreeBSD__)
40 > #if defined(HAVE_LINUX_IF_H) && defined(HAVE_LINUX_IF_TUN_H)
41 > #include <linux/if.h>
42 > #include <linux/if_tun.h>
43 > #endif
44 >
45 > #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_IF_TUN_H)
46   #include <net/if.h>
47 + #include <net/if_tun.h>
48 + #endif
49 +
50 + #ifdef HAVE_SLIRP
51 + #include "libslirp.h"
52   #endif
53  
54   #include "cpu_emulation.h"
# Line 42 | Line 59
59   #include "ether.h"
60   #include "ether_defs.h"
61  
62 + #ifndef NO_STD_NAMESPACE
63 + using std::map;
64 + #endif
65 +
66   #define DEBUG 0
67   #include "debug.h"
68  
69   #define MONITOR 0
70  
71  
72 < // List of attached protocols
73 < struct NetProtocol {
74 <        NetProtocol *next;
75 <        uint16 type;
76 <        uint32 handler;
72 > // Ethernet device types
73 > enum {
74 >        NET_IF_SHEEPNET,
75 >        NET_IF_ETHERTAP,
76 >        NET_IF_TUNTAP,
77 >        NET_IF_SLIRP
78   };
79  
80 < static NetProtocol *prot_list = NULL;
81 <
80 > // Constants
81 > static const char ETHERCONFIG_FILE_NAME[] = DATADIR "/tunconfig";
82  
83   // Global variables
84   static int fd = -1;                                                     // fd of sheep_net device
# Line 64 | Line 86 | static pthread_t ether_thread;                         // Pac
86   static pthread_attr_t ether_thread_attr;        // Packet reception thread attributes
87   static bool thread_active = false;                      // Flag: Packet reception thread installed
88   static sem_t int_ack;                                           // Interrupt acknowledge semaphore
67 static bool is_ethertap;                                        // Flag: Ethernet device is ethertap
89   static bool udp_tunnel;                                         // Flag: UDP tunnelling active, fd is the socket descriptor
90 + static int net_if_type = -1;                            // Ethernet device type
91 + static char *net_if_name = NULL;                        // TUN/TAP device name
92 + static const char *net_if_script = NULL;        // Network config script
93 + static pthread_t slirp_thread;                          // Slirp reception thread
94 + static bool slirp_thread_active = false;        // Flag: Slirp reception threadinstalled
95 + static int slirp_output_fd = -1;                        // fd of slirp output pipe
96 +
97 + // Attached network protocols, maps protocol type to MacOS handler address
98 + static map<uint16, uint32> net_protocols;
99  
100   // Prototypes
101   static void *receive_func(void *arg);
102 <
103 <
74 < /*
75 < *  Find protocol in list
76 < */
77 <
78 < static NetProtocol *find_protocol(uint16 type)
79 < {
80 <        // All 802.2 types are the same
81 <        if (type <= 1500)
82 <                type = 0;
83 <
84 <        // Search list (we could use hashing here but there are usually only three
85 <        // handlers installed: 0x0000 for AppleTalk and 0x0800/0x0806 for TCP/IP)
86 <        NetProtocol *p = prot_list;
87 <        while (p) {
88 <                if (p->type == type)
89 <                        return p;
90 <                p = p->next;
91 <        }
92 <        return NULL;
93 < }
94 <
95 <
96 < /*
97 < *  Remove all protocols
98 < */
99 <
100 < static void remove_all_protocols(void)
101 < {
102 <        NetProtocol *p = prot_list;
103 <        while (p) {
104 <                NetProtocol *next = p->next;
105 <                delete p;
106 <                p = next;
107 <        }
108 <        prot_list = NULL;
109 < }
102 > static void *slirp_receive_func(void *arg);
103 > static int poll_fd(int fd);
104  
105  
106   /*
# Line 120 | Line 114 | static bool start_thread(void)
114                  return false;
115          }
116  
117 <        pthread_attr_init(&ether_thread_attr);
124 < #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
125 <        if (geteuid() == 0) {
126 <                pthread_attr_setinheritsched(&ether_thread_attr, PTHREAD_EXPLICIT_SCHED);
127 <                pthread_attr_setschedpolicy(&ether_thread_attr, SCHED_FIFO);
128 <                struct sched_param fifo_param;
129 <                fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2 + 1;
130 <                pthread_attr_setschedparam(&ether_thread_attr, &fifo_param);
131 <        }
132 < #endif
133 <
117 >        Set_pthread_attr(&ether_thread_attr, 1);
118          thread_active = (pthread_create(&ether_thread, &ether_thread_attr, receive_func, NULL) == 0);
119          if (!thread_active) {
120                  printf("WARNING: Cannot start Ethernet thread");
121                  return false;
122          }
123  
124 + #ifdef HAVE_SLIRP
125 +        if (net_if_type == NET_IF_SLIRP) {
126 +                slirp_thread_active = (pthread_create(&slirp_thread, NULL, slirp_receive_func, NULL) == 0);
127 +                if (!slirp_thread_active) {
128 +                        printf("WARNING: Cannot start slirp reception thread\n");
129 +                        return false;
130 +                }
131 +        }
132 + #endif
133 +
134          return true;
135   }
136  
# Line 147 | Line 141 | static bool start_thread(void)
141  
142   static void stop_thread(void)
143   {
144 + #ifdef HAVE_SLIRP
145 +        if (slirp_thread_active) {
146 + #ifdef HAVE_PTHREAD_CANCEL
147 +                pthread_cancel(slirp_thread);
148 + #endif
149 +                pthread_join(slirp_thread, NULL);
150 +                slirp_thread_active = false;
151 +        }
152 + #endif
153 +
154          if (thread_active) {
155 + #ifdef HAVE_PTHREAD_CANCEL
156                  pthread_cancel(ether_thread);
157 + #endif
158                  pthread_join(ether_thread, NULL);
159                  sem_destroy(&int_ack);
160                  thread_active = false;
# Line 157 | Line 163 | static void stop_thread(void)
163  
164  
165   /*
166 + *  Execute network script up|down
167 + */
168 +
169 + static bool execute_network_script(const char *action)
170 + {
171 +        if (net_if_script == NULL || net_if_name == NULL)
172 +                return false;
173 +
174 +        int pid = fork();
175 +        if (pid >= 0) {
176 +                if (pid == 0) {
177 +                        char *args[4];
178 +                        args[0] = (char *)net_if_script;
179 +                        args[1] = net_if_name;
180 +                        args[2] = (char *)action;
181 +                        args[3] = NULL;
182 +                        execv(net_if_script, args);
183 +                        exit(1);
184 +                }
185 +                int status;
186 +                while (waitpid(pid, &status, 0) != pid);
187 +                return WIFEXITED(status) && WEXITSTATUS(status) == 0;
188 +        }
189 +
190 +        return false;
191 + }
192 +
193 +
194 + /*
195   *  Initialization
196   */
197  
# Line 170 | Line 205 | bool ether_init(void)
205          if (name == NULL)
206                  return false;
207  
208 <        // Is it Ethertap?
209 <        is_ethertap = (strncmp(name, "tap", 3) == 0);
208 >        // Determine Ethernet device type
209 >        net_if_type = -1;
210 >        if (strncmp(name, "tap", 3) == 0)
211 >                net_if_type = NET_IF_ETHERTAP;
212 > #if ENABLE_TUNTAP
213 >        else if (strcmp(name, "tun") == 0)
214 >                net_if_type = NET_IF_TUNTAP;
215 > #endif
216 > #ifdef HAVE_SLIRP
217 >        else if (strcmp(name, "slirp") == 0)
218 >                net_if_type = NET_IF_SLIRP;
219 > #endif
220 >        else
221 >                net_if_type = NET_IF_SHEEPNET;
222 >
223 > #ifdef HAVE_SLIRP
224 >        // Initialize slirp library
225 >        if (net_if_type == NET_IF_SLIRP) {
226 >                slirp_init();
227 >
228 >                // Open slirp output pipe
229 >                int fds[2];
230 >                if (pipe(fds) < 0)
231 >                        return false;
232 >                fd = fds[0];
233 >                slirp_output_fd = fds[1];
234 >        }
235 > #endif
236  
237 <        // Open sheep_net or ethertap device
237 >        // Open sheep_net or ethertap or TUN/TAP device
238          char dev_name[16];
239 <        if (is_ethertap)
239 >        switch (net_if_type) {
240 >        case NET_IF_ETHERTAP:
241                  sprintf(dev_name, "/dev/%s", name);
242 <        else
242 >                break;
243 >        case NET_IF_TUNTAP:
244 >                strcpy(dev_name, "/dev/net/tun");
245 >                break;
246 >        case NET_IF_SHEEPNET:
247                  strcpy(dev_name, "/dev/sheep_net");
248 <        fd = open(dev_name, O_RDWR);
183 <        if (fd < 0) {
184 <                sprintf(str, GetString(STR_NO_SHEEP_NET_DRIVER_WARN), dev_name, strerror(errno));
185 <                WarningAlert(str);
186 <                goto open_error;
248 >                break;
249          }
250 +        if (net_if_type != NET_IF_SLIRP) {
251 +                fd = open(dev_name, O_RDWR);
252 +                if (fd < 0) {
253 +                        sprintf(str, GetString(STR_NO_SHEEP_NET_DRIVER_WARN), dev_name, strerror(errno));
254 +                        WarningAlert(str);
255 +                        goto open_error;
256 +                }
257 +        }
258 +
259 + #if ENABLE_TUNTAP
260 +        // Open TUN/TAP interface
261 +        if (net_if_type == NET_IF_TUNTAP) {
262 +                struct ifreq ifr;
263 +                memset(&ifr, 0, sizeof(ifr));
264 +                ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
265 +                strcpy(ifr.ifr_name, "tun%d");
266 +                if (ioctl(fd, TUNSETIFF, (void *) &ifr) != 0) {
267 +                        sprintf(str, GetString(STR_SHEEP_NET_ATTACH_WARN), strerror(errno));
268 +                        WarningAlert(str);
269 +                        goto open_error;
270 +                }
271 +
272 +                // Get network config script file path
273 +                net_if_script = PrefsFindString("etherconfig");
274 +                if (net_if_script == NULL)
275 +                        net_if_script = ETHERCONFIG_FILE_NAME;
276 +
277 +                // Start network script up
278 +                if (net_if_script == NULL) {
279 +                        sprintf(str, GetString(STR_TUN_TAP_CONFIG_WARN), "script not found");
280 +                        WarningAlert(str);
281 +                        goto open_error;
282 +                }
283 +                net_if_name = strdup(ifr.ifr_name);
284 +                if (!execute_network_script("up")) {
285 +                        sprintf(str, GetString(STR_TUN_TAP_CONFIG_WARN), "script execute error");
286 +                        WarningAlert(str);
287 +                        goto open_error;
288 +                }
289 +                D(bug("Connected to host network interface: %s\n", net_if_name));
290 +        }
291 + #endif
292  
293   #if defined(__linux__)
294          // Attach sheep_net to selected Ethernet card
295 <        if (!is_ethertap && ioctl(fd, SIOCSIFLINK, name) < 0) {
295 >        if (net_if_type == NET_IF_SHEEPNET && ioctl(fd, SIOCSIFLINK, name) < 0) {
296                  sprintf(str, GetString(STR_SHEEP_NET_ATTACH_WARN), strerror(errno));
297                  WarningAlert(str);
298                  goto open_error;
# Line 199 | Line 303 | bool ether_init(void)
303          ioctl(fd, FIONBIO, &nonblock);
304  
305          // Get Ethernet address
306 <        if (is_ethertap) {
306 >        if (net_if_type == NET_IF_ETHERTAP) {
307                  pid_t p = getpid();     // If configured for multicast, ethertap requires that the lower 32 bit of the Ethernet address are our PID
308                  ether_addr[0] = 0xfe;
309                  ether_addr[1] = 0xfd;
# Line 207 | Line 311 | bool ether_init(void)
311                  ether_addr[3] = p >> 16;
312                  ether_addr[4] = p >> 8;
313                  ether_addr[5] = p;
314 + #ifdef HAVE_SLIRP
315 +        } else if (net_if_type == NET_IF_SLIRP) {
316 +                ether_addr[0] = 0x52;
317 +                ether_addr[1] = 0x54;
318 +                ether_addr[2] = 0x00;
319 +                ether_addr[3] = 0x12;
320 +                ether_addr[4] = 0x34;
321 +                ether_addr[5] = 0x56;
322 + #endif
323          } else
324                  ioctl(fd, SIOCGIFADDR, ether_addr);
325          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]));
# Line 225 | Line 338 | open_error:
338                  close(fd);
339                  fd = -1;
340          }
341 +        if (slirp_output_fd >= 0) {
342 +                close(slirp_output_fd);
343 +                slirp_output_fd = -1;
344 +        }
345          return false;
346   }
347  
# Line 235 | Line 352 | open_error:
352  
353   void ether_exit(void)
354   {
355 <        // Stop reception thread
356 <        if (thread_active) {
357 <                pthread_cancel(ether_thread);
358 <                pthread_join(ether_thread, NULL);
359 <                sem_destroy(&int_ack);
360 <                thread_active = false;
361 <        }
355 >        // Stop reception threads
356 >        stop_thread();
357 >
358 >        // Shut down TUN/TAP interface
359 >        if (net_if_type == NET_IF_TUNTAP)
360 >                execute_network_script("down");
361 >
362 >        // Free TUN/TAP device name
363 >        if (net_if_name)
364 >                free(net_if_name);
365  
366          // Close sheep_net device
367          if (fd > 0)
368                  close(fd);
369  
370 <        // Remove all protocols
371 <        remove_all_protocols();
370 >        // Close slirp output buffer
371 >        if (slirp_output_fd > 0)
372 >                close(slirp_output_fd);
373   }
374  
375  
# Line 256 | Line 377 | void ether_exit(void)
377   *  Reset
378   */
379  
380 < void EtherReset(void)
380 > void ether_reset(void)
381   {
382 <        remove_all_protocols();
382 >        net_protocols.clear();
383   }
384  
385  
# Line 268 | Line 389 | void EtherReset(void)
389  
390   int16 ether_add_multicast(uint32 pb)
391   {
392 <        if (ioctl(fd, SIOCADDMULTI, Mac2HostAddr(pb + eMultiAddr)) < 0) {
393 <                D(bug("WARNING: Couldn't enable multicast address\n"));
394 <                if (is_ethertap)
395 <                        return noErr;
396 <                else
397 <                        return eMultiErr;
398 <        } else
392 >        switch (net_if_type) {
393 >        case NET_IF_ETHERTAP:
394 >        case NET_IF_SHEEPNET:
395 >                if (ioctl(fd, SIOCADDMULTI, Mac2HostAddr(pb + eMultiAddr)) < 0) {
396 >                        D(bug("WARNING: Couldn't enable multicast address\n"));
397 >                        if (net_if_type == NET_IF_ETHERTAP)
398 >                                return noErr;
399 >                        else
400 >                                return eMultiErr;
401 >                }
402 >        default:
403                  return noErr;
404 +        }
405   }
406  
407  
# Line 285 | Line 411 | int16 ether_add_multicast(uint32 pb)
411  
412   int16 ether_del_multicast(uint32 pb)
413   {
414 <        if (ioctl(fd, SIOCDELMULTI, Mac2HostAddr(pb + eMultiAddr)) < 0) {
415 <                D(bug("WARNING: Couldn't disable multicast address\n"));
416 <                return eMultiErr;
417 <        } else
414 >        switch (net_if_type) {
415 >        case NET_IF_ETHERTAP:
416 >        case NET_IF_SHEEPNET:
417 >                if (ioctl(fd, SIOCDELMULTI, Mac2HostAddr(pb + eMultiAddr)) < 0) {
418 >                        D(bug("WARNING: Couldn't disable multicast address\n"));
419 >                        return eMultiErr;
420 >                }
421 >        default:
422                  return noErr;
423 +        }
424   }
425  
426  
# Line 299 | Line 430 | int16 ether_del_multicast(uint32 pb)
430  
431   int16 ether_attach_ph(uint16 type, uint32 handler)
432   {
433 <        // Already attached?
303 <        NetProtocol *p = find_protocol(type);
304 <        if (p != NULL)
433 >        if (net_protocols.find(type) != net_protocols.end())
434                  return lapProtErr;
435 <        else {
436 <                // No, create and attach
308 <                p = new NetProtocol;
309 <                p->next = prot_list;
310 <                p->type = type;
311 <                p->handler = handler;
312 <                prot_list = p;
313 <                return noErr;
314 <        }
435 >        net_protocols[type] = handler;
436 >        return noErr;
437   }
438  
439  
# Line 321 | Line 443 | int16 ether_attach_ph(uint16 type, uint3
443  
444   int16 ether_detach_ph(uint16 type)
445   {
446 <        NetProtocol *p = find_protocol(type);
325 <        if (p != NULL) {
326 <                NetProtocol *q = prot_list;
327 <                if (p == q) {
328 <                        prot_list = p->next;
329 <                        delete p;
330 <                        return noErr;
331 <                }
332 <                while (q) {
333 <                        if (q->next == p) {
334 <                                q->next = p->next;
335 <                                delete p;
336 <                                return noErr;
337 <                        }
338 <                        q = q->next;
339 <                }
340 <                return lapProtErr;
341 <        } else
446 >        if (net_protocols.erase(type) == 0)
447                  return lapProtErr;
448 +        return noErr;
449   }
450  
451  
# Line 349 | Line 455 | int16 ether_detach_ph(uint16 type)
455  
456   int16 ether_write(uint32 wds)
457   {
352        // Set source address
353        uint32 hdr = ReadMacInt32(wds + 2);
354        Host2Mac_memcpy(hdr + 6, ether_addr, 6);
355
458          // Copy packet to buffer
459          uint8 packet[1516], *p = packet;
460          int len = 0;
461   #if defined(__linux__)
462 <        if (is_ethertap) {
462 >        if (net_if_type == NET_IF_ETHERTAP) {
463                  *p++ = 0;       // Linux ethertap discards the first 2 bytes
464                  *p++ = 0;
465                  len += 2;
# Line 374 | Line 476 | int16 ether_write(uint32 wds)
476   #endif
477  
478          // Transmit packet
479 + #ifdef HAVE_SLIRP
480 +        if (net_if_type == NET_IF_SLIRP) {
481 +                slirp_input(packet, len);
482 +                return noErr;
483 +        } else
484 + #endif
485          if (write(fd, packet, len) < 0) {
486                  D(bug("WARNING: Couldn't transmit packet\n"));
487                  return excessCollsns;
# Line 406 | Line 514 | void ether_stop_udp_thread(void)
514  
515  
516   /*
517 + *  SLIRP output buffer glue
518 + */
519 +
520 + #ifdef HAVE_SLIRP
521 + int slirp_can_output(void)
522 + {
523 +        return 1;
524 + }
525 +
526 + void slirp_output(const uint8 *packet, int len)
527 + {
528 +        write(slirp_output_fd, packet, len);
529 + }
530 +
531 + void *slirp_receive_func(void *arg)
532 + {
533 +        for (;;) {
534 +                // Wait for packets to arrive
535 +                fd_set rfds, wfds, xfds;
536 +                int nfds;
537 +                struct timeval tv;
538 +
539 +                nfds = -1;
540 +                FD_ZERO(&rfds);
541 +                FD_ZERO(&wfds);
542 +                FD_ZERO(&xfds);
543 +                slirp_select_fill(&nfds, &rfds, &wfds, &xfds);
544 +                tv.tv_sec = 0;
545 +                tv.tv_usec = 16667;
546 +                if (select(nfds + 1, &rfds, &wfds, &xfds, &tv) >= 0)
547 +                        slirp_select_poll(&rfds, &wfds, &xfds);
548 +
549 + #ifdef HAVE_PTHREAD_TESTCANCEL
550 +                // Explicit cancellation point if select() was not covered
551 +                // This seems to be the case on MacOS X 10.2
552 +                pthread_testcancel();
553 + #endif
554 +        }
555 +        return NULL;
556 + }
557 + #else
558 + int slirp_can_output(void)
559 + {
560 +        return 0;
561 + }
562 +
563 + void slirp_output(const uint8 *packet, int len)
564 + {
565 + }
566 + #endif
567 +
568 +
569 + /*
570   *  Packet reception thread
571   */
572  
# Line 414 | Line 575 | static void *receive_func(void *arg)
575          for (;;) {
576  
577                  // Wait for packets to arrive
578 + #if HAVE_POLL
579                  struct pollfd pf = {fd, POLLIN, 0};
580                  int res = poll(&pf, 1, -1);
581 + #else
582 +                fd_set rfds;
583 +                FD_ZERO(&rfds);
584 +                FD_SET(fd, &rfds);
585 +                // A NULL timeout could cause select() to block indefinitely,
586 +                // even if it is supposed to be a cancellation point [MacOS X]
587 +                struct timeval tv = { 0, 20000 };
588 +                int res = select(fd + 1, &rfds, NULL, NULL, &tv);
589 + #ifdef HAVE_PTHREAD_TESTCANCEL
590 +                pthread_testcancel();
591 + #endif
592 +                if (res == 0 || (res == -1 && errno == EINTR))
593 +                        continue;
594 + #endif
595                  if (res <= 0)
596                          break;
597  
# Line 440 | Line 616 | void EtherInterrupt(void)
616          D(bug("EtherIRQ\n"));
617  
618          // Call protocol handler for received packets
619 <        uint8 packet[1516];
619 >        EthernetPacket ether_packet;
620 >        uint32 packet = ether_packet.addr();
621          ssize_t length;
622          for (;;) {
623  
# Line 449 | Line 626 | void EtherInterrupt(void)
626                          // Read packet from socket
627                          struct sockaddr_in from;
628                          socklen_t from_len = sizeof(from);
629 <                        length = recvfrom(fd, packet, 1514, 0, (struct sockaddr *)&from, &from_len);
629 >                        length = recvfrom(fd, Mac2HostAddr(packet), 1514, 0, (struct sockaddr *)&from, &from_len);
630                          if (length < 14)
631                                  break;
632                          ether_udp_read(packet, length, &from);
# Line 458 | Line 635 | void EtherInterrupt(void)
635  
636                          // Read packet from sheep_net device
637   #if defined(__linux__)
638 <                        length = read(fd, packet, is_ethertap ? 1516 : 1514);
638 >                        length = read(fd, Mac2HostAddr(packet), net_if_type == NET_IF_ETHERTAP ? 1516 : 1514);
639   #else
640 <                        length = read(fd, packet, 1514);
640 >                        length = read(fd, Mac2HostAddr(packet), 1514);
641   #endif
642                          if (length < 14)
643                                  break;
# Line 468 | Line 645 | void EtherInterrupt(void)
645   #if MONITOR
646                          bug("Receiving Ethernet packet:\n");
647                          for (int i=0; i<length; i++) {
648 <                                bug("%02x ", packet[i]);
648 >                                bug("%02x ", ReadMacInt8(packet + i));
649                          }
650                          bug("\n");
651   #endif
652  
653                          // Pointer to packet data (Ethernet header)
654 <                        uint8 *p = packet;
654 >                        uint32 p = packet;
655   #if defined(__linux__)
656 <                        if (is_ethertap) {
656 >                        if (net_if_type == NET_IF_ETHERTAP) {
657                                  p += 2;                 // Linux ethertap has two random bytes before the packet
658                                  length -= 2;
659                          }
660   #endif
661  
662                          // Get packet type
663 <                        uint16 type = (p[12] << 8) | p[13];
663 >                        uint16 type = ReadMacInt16(p + 12);
664  
665                          // Look for protocol
666 <                        NetProtocol *prot = find_protocol(type);
667 <                        if (prot == NULL)
666 >                        uint16 search_type = (type <= 1500 ? 0 : type);
667 >                        if (net_protocols.find(search_type) == net_protocols.end())
668                                  continue;
669 +                        uint32 handler = net_protocols[search_type];
670  
671                          // No default handler
672 <                        if (prot->handler == 0)
672 >                        if (handler == 0)
673                                  continue;
674  
675                          // Copy header to RHA
676 <                        Host2Mac_memcpy(ether_data + ed_RHA, p, 14);
676 >                        Mac2Mac_memcpy(ether_data + ed_RHA, p, 14);
677                          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)));
678  
679                          // Call protocol handler
680                          M68kRegisters r;
681                          r.d[0] = type;                                                                  // Packet type
682                          r.d[1] = length - 14;                                                   // Remaining packet length (without header, for ReadPacket)
683 <                        r.a[0] = (uint32)p + 14;                                                // Pointer to packet (host address, for ReadPacket)
683 >                        r.a[0] = p + 14;                                                                // Pointer to packet (Mac address, for ReadPacket)
684                          r.a[3] = ether_data + ed_RHA + 14;                              // Pointer behind header in RHA
685                          r.a[4] = ether_data + ed_ReadPacket;                    // Pointer to ReadPacket/ReadRest routines
686 <                        D(bug(" calling protocol handler %08x, type %08x, length %08x, data %08x, rha %08x, read_packet %08x\n", prot->handler, r.d[0], r.d[1], r.a[0], r.a[3], r.a[4]));
687 <                        Execute68k(prot->handler, &r);
686 >                        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]));
687 >                        Execute68k(handler, &r);
688                  }
689          }
690  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines