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

Comparing SheepShaver/src/Unix/Linux/ether_linux.cpp (file contents):
Revision 1.1.1.1 by cebix, 2002-02-04T16:58:13Z vs.
Revision 1.8 by gbeauche, 2005-07-03T13:05:36Z

# Line 1 | Line 1
1   /*
2   *  ether_linux.cpp - SheepShaver Ethernet Device Driver (DLPI), Linux specific stuff
3   *
4 < *  SheepShaver (C) 1997-2002 Marc Hellwig and Christian Bauer
4 > *  SheepShaver (C) 1997-2005 Marc Hellwig and 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 18 | Line 18
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   */
20  
21 + #include "sysdeps.h"
22 +
23   #include <pthread.h>
24   #include <semaphore.h>
25   #include <unistd.h>
# Line 25 | Line 27
27   #include <errno.h>
28   #include <sys/ioctl.h>
29   #include <sys/poll.h>
30 + #include <sys/wait.h>
31   #include <stdio.h>
32   #include <string.h>
33  
34 < #include "sysdeps.h"
34 > #if defined(HAVE_LINUX_IF_H) && defined(HAVE_LINUX_IF_TUN_H)
35 > #include <linux/if.h>
36 > #include <linux/if_tun.h>
37 > #endif
38 >
39 > #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_IF_TUN_H)
40 > #include <net/if.h>
41 > #include <net/if_tun.h>
42 > #endif
43 >
44   #include "main.h"
45   #include "macos_util.h"
46   #include "prefs.h"
# Line 43 | Line 55
55   #define MONITOR 0
56  
57  
58 + // Ethernet device types
59 + enum {
60 +        NET_IF_SHEEPNET,
61 +        NET_IF_ETHERTAP,
62 +        NET_IF_TUNTAP,
63 + };
64 +
65 + // Constants
66 + static const char ETHERCONFIG_FILE_NAME[] = DATADIR "/tunconfig";
67 +
68   // Global variables
69   static int fd = -1;                                     // fd of sheep_net device
70  
# Line 53 | Line 75 | static sem_t int_ack;                          // Interrupt ac
75   static uint8 ether_addr[6];                     // Our Ethernet address
76  
77   static bool net_open = false;           // Flag: initialization succeeded, network device open
78 < static bool is_ethertap = false;        // Flag: Ethernet device is ethertap
78 > static int net_if_type = -1;            // Ethernet device type
79 > static char *net_if_name;                       // TUN/TAP device name
80 > static const char *net_if_script;       // Network config script
81  
82  
83   // Prototypes
# Line 61 | Line 85 | static void *receive_func(void *arg);
85  
86  
87   /*
88 + *  Execute network script up|down
89 + */
90 +
91 + static bool execute_network_script(const char *action)
92 + {
93 +        if (net_if_script == NULL || net_if_name == NULL)
94 +                return false;
95 +
96 +        int pid = fork();
97 +        if (pid >= 0) {
98 +                if (pid == 0) {
99 +                        char *args[4];
100 +                        args[0] = (char *)net_if_script;
101 +                        args[1] = net_if_name;
102 +                        args[2] = (char *)action;
103 +                        args[3] = NULL;
104 +                        execv(net_if_script, args);
105 +                        exit(1);
106 +                }
107 +                int status;
108 +                while (waitpid(pid, &status, 0) != pid);
109 +                return WIFEXITED(status) && WEXITSTATUS(status) == 0;
110 +        }
111 +
112 +        return false;
113 + }
114 +
115 +
116 + /*
117   *  Initialize ethernet
118   */
119  
# Line 78 | Line 131 | void EtherInit(void)
131          if (name == NULL)
132                  return;
133  
134 <        // Is it Ethertap?
135 <        is_ethertap = (strncmp(name, "tap", 3) == 0);
134 >        // Determine Ether device type
135 >        net_if_type = -1;
136 >        if (strncmp(name, "tap", 3) == 0)
137 >                net_if_type = NET_IF_ETHERTAP;
138 > #if ENABLE_TUNTAP
139 >        else if (strcmp(name, "tun") == 0)
140 >                net_if_type = NET_IF_TUNTAP;
141 > #endif
142 >        else
143 >                net_if_type = NET_IF_SHEEPNET;
144  
145          // Open sheep_net or ethertap device
146          char dev_name[16];
147 <        if (is_ethertap)
147 >        switch (net_if_type) {
148 >        case NET_IF_ETHERTAP:
149                  sprintf(dev_name, "/dev/%s", name);
150 <        else
150 >                break;
151 >        case NET_IF_TUNTAP:    
152 >                strcpy(dev_name, "/dev/net/tun");
153 >                break;
154 >        case NET_IF_SHEEPNET:
155                  strcpy(dev_name, "/dev/sheep_net");
156 +                break;
157 +        }
158          fd = open(dev_name, O_RDWR);
159          if (fd < 0) {
160                  sprintf(str, GetString(STR_NO_SHEEP_NET_DRIVER_WARN), dev_name, strerror(errno));
# Line 94 | Line 162 | void EtherInit(void)
162                  goto open_error;
163          }
164  
165 + #if ENABLE_TUNTAP
166 +        // Open TUN/TAP interface
167 +        if (net_if_type == NET_IF_TUNTAP) {
168 +                struct ifreq ifr;
169 +                memset(&ifr, 0, sizeof(ifr));
170 +                ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
171 +                strcpy(ifr.ifr_name, "tun%d");
172 +                if (ioctl(fd, TUNSETIFF, (void *) &ifr) != 0) {
173 +                        sprintf(str, GetString(STR_SHEEP_NET_ATTACH_WARN), strerror(errno));
174 +                        WarningAlert(str);
175 +                        goto open_error;
176 +                }
177 +
178 +                // Get network config script file path
179 +                net_if_script = PrefsFindString("etherconfig");
180 +                if (net_if_script == NULL)
181 +                        net_if_script = ETHERCONFIG_FILE_NAME;
182 +
183 +                // Start network script up
184 +                if (net_if_script == NULL) {
185 +                        sprintf(str, GetString(STR_TUN_TAP_CONFIG_WARN), "script not found");
186 +                        WarningAlert(str);
187 +                        goto open_error;
188 +                }
189 +                net_if_name = strdup(ifr.ifr_name);
190 +                if (!execute_network_script("up")) {
191 +                        sprintf(str, GetString(STR_TUN_TAP_CONFIG_WARN), "script execute error");
192 +                        WarningAlert(str);
193 +                        goto open_error;
194 +                }
195 +                D(bug("Connected to host network interface: %s\n", net_if_name));
196 +        }
197 + #endif
198 +
199          // Attach to selected Ethernet card
200 <        if (!is_ethertap && ioctl(fd, SIOCSIFLINK, name) < 0) {
200 >        if (net_if_type == NET_IF_SHEEPNET && ioctl(fd, SIOCSIFLINK, name) < 0) {
201                  sprintf(str, GetString(STR_SHEEP_NET_ATTACH_WARN), strerror(errno));
202                  WarningAlert(str);
203                  goto open_error;
# Line 105 | Line 207 | void EtherInit(void)
207          ioctl(fd, FIONBIO, &nonblock);
208  
209          // Get Ethernet address
210 <        if (is_ethertap) {
210 >        if (net_if_type == NET_IF_ETHERTAP) {
211                  pid_t p = getpid();     // If configured for multicast, ethertap requires that the lower 32 bit of the Ethernet address are our PID
212                  ether_addr[0] = 0xfe;
213                  ether_addr[1] = 0xfd;
# Line 160 | Line 262 | void EtherExit(void)
262                  thread_active = false;
263          }
264  
265 +        // Shut down TUN/TAP interface
266 +        if (net_if_type == NET_IF_TUNTAP)
267 +                execute_network_script("down");
268 +
269 +        // Free TUN/TAP device name
270 +        if (net_if_name)
271 +                free(net_if_name);
272 +
273          // Close sheep_net device
274          if (fd > 0)
275                  close(fd);
# Line 209 | Line 319 | void AO_enable_multicast(uint8 *addr)
319   {
320          D(bug("AO_enable_multicast\n"));
321          if (net_open) {
322 <                if (ioctl(fd, SIOCADDMULTI, addr) < 0) {
322 >                if (net_if_type != NET_IF_TUNTAP && ioctl(fd, SIOCADDMULTI, addr) < 0) {
323                          D(bug("WARNING: couldn't enable multicast address\n"));
324                  }
325          }
# Line 224 | Line 334 | void AO_disable_multicast(uint8 *addr)
334   {
335          D(bug("AO_disable_multicast\n"));
336          if (net_open) {
337 <                if (ioctl(fd, SIOCDELMULTI, addr) < 0) {
337 >                if (net_if_type != NET_IF_TUNTAP && ioctl(fd, SIOCDELMULTI, addr) < 0) {
338                          D(bug("WARNING: couldn't disable multicast address\n"));
339                  }
340          }
# Line 243 | Line 353 | void AO_transmit_packet(mblk_t *mp)
353                  // Copy packet to buffer
354                  uint8 packet[1516], *p = packet;
355                  int len = 0;
356 <                if (is_ethertap) {
356 >                if (net_if_type == NET_IF_ETHERTAP) {
357                          *p++ = 0;       // Ethertap discards the first 2 bytes
358                          *p++ = 0;
359                          len += 2;
# Line 317 | Line 427 | void EtherIRQ(void)
427          uint8 packet[1516];
428          for (;;) {
429  
430 <                if (is_ethertap) {
430 >                if (net_if_type != NET_IF_SHEEPNET) {
431  
432                          // Read packet from ethertap device
433 <                        ssize_t size = read(fd, packet, 1516);
433 >                        ssize_t size = read(fd, packet, net_if_type == NET_IF_ETHERTAP ? 1516 : 1514);
434                          if (size < 14)
435                                  break;
436  
# Line 333 | Line 443 | void EtherIRQ(void)
443   #endif
444  
445                          // Pointer to packet data (Ethernet header)
446 <                        uint8 *p = packet + 2;  // Ethertap has two random bytes before the packet
447 <                        size -= 2;
446 >                        uint8 *p = packet;
447 >                        if (net_if_type == NET_IF_ETHERTAP) {
448 >                                p += 2; // Ethertap has two random bytes before the packet
449 >                                size -= 2;
450 >                        }
451  
452                          // Wrap packet in message block
453                          num_rx_packets++;
454                          mblk_t *mp;
455                          if ((mp = allocb(size, 0)) != NULL) {
456 <                                D(bug(" packet data at %p\n", mp->b_rptr));
456 >                                D(bug(" packet data at %p\n", (void *)mp->b_rptr));
457                                  memcpy(mp->b_rptr, p, size);
458                                  mp->b_wptr += size;
459                                  ether_packet_received(mp);
# Line 371 | Line 484 | void EtherIRQ(void)
484                          num_rx_packets++;
485                          mblk_t *mp;
486                          if ((mp = allocb(size, 0)) != NULL) {
487 <                                D(bug(" packet data at %p\n", mp->b_rptr));
488 <                                read(fd, mp->b_rptr, 1514);
487 >                                D(bug(" packet data at %p\n", (void *)mp->b_rptr));
488 >                                read(fd, mp->b_rptr, size);
489   #if MONITOR
490                                  bug("Receiving Ethernet packet:\n");
491                                  for (int i=0; i<size; i++) {
# Line 384 | Line 497 | void EtherIRQ(void)
497                                  ether_packet_received(mp);
498                          } else {
499                                  D(bug("WARNING: Cannot allocate mblk for received packet\n"));
500 +                                read(fd, packet, size); // consume this packet
501                                  num_rx_no_mem++;
502                          }
503                  }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines