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.2 by cebix, 2004-01-12T15:55:51Z vs.
Revision 1.3 by gbeauche, 2004-05-09T17:44:18Z

# 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 >                sprintf(dev_name, "/dev/net/tun", name);
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++;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines