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

Comparing BasiliskII/src/Windows/ether_windows.cpp (file contents):
Revision 1.6 by gbeauche, 2006-04-29T10:57:56Z vs.
Revision 1.7 by gbeauche, 2006-05-01T10:23:47Z

# Line 20 | Line 20
20   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21   */
22  
23 + #include "sysdeps.h"
24 +
25   #include <process.h>
26   #include <windowsx.h>
27 + #include <winioctl.h>
28   #include <ctype.h>
29  
27 #include "sysdeps.h"
30   #include "cpu_emulation.h"
31   #include "main.h"
32   #include "macos_util.h"
# Line 58 | Line 60 | enum {
60          NET_IF_B2ETHER,
61          NET_IF_ROUTER,
62          NET_IF_SLIRP,
63 +        NET_IF_TAP,
64          NET_IF_FAKE,
65   };
66  
67 + // TAP-Win32 constants
68 + #define TAP_VERSION_MIN_MAJOR 7
69 + #define TAP_VERSION_MIN_MINOR 1
70 +
71 + #define TAP_CONTROL_CODE(request, method) \
72 +                CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS)
73 +
74 + #define TAP_IOCTL_GET_MAC                               TAP_CONTROL_CODE (1, METHOD_BUFFERED)
75 + #define TAP_IOCTL_GET_VERSION                   TAP_CONTROL_CODE (2, METHOD_BUFFERED)
76 + #define TAP_IOCTL_GET_MTU                               TAP_CONTROL_CODE (3, METHOD_BUFFERED)
77 + #define TAP_IOCTL_GET_INFO                              TAP_CONTROL_CODE (4, METHOD_BUFFERED)
78 + #define TAP_IOCTL_CONFIG_POINT_TO_POINT TAP_CONTROL_CODE (5, METHOD_BUFFERED)
79 + #define TAP_IOCTL_SET_MEDIA_STATUS              TAP_CONTROL_CODE (6, METHOD_BUFFERED)
80 + #define TAP_IOCTL_CONFIG_DHCP_MASQ              TAP_CONTROL_CODE (7, METHOD_BUFFERED)
81 + #define TAP_IOCTL_GET_LOG_LINE                  TAP_CONTROL_CODE (8, METHOD_BUFFERED)
82 + #define TAP_IOCTL_CONFIG_DHCP_SET_OPT   TAP_CONTROL_CODE (9, METHOD_BUFFERED)
83 +
84 + #define OLD_TAP_CONTROL_CODE(request, method) \
85 +                CTL_CODE (FILE_DEVICE_PHYSICAL_NETCARD | 8000, request, method, FILE_ANY_ACCESS)
86 +
87 + #define OLD_TAP_IOCTL_GET_VERSION               OLD_TAP_CONTROL_CODE (3, METHOD_BUFFERED)
88 +
89   // Options
90   bool ether_use_permanent = true;
91   static int16 ether_multi_mode = ETHER_MULTICAST_MAC;
# Line 70 | Line 95 | HANDLE ether_th;
95   unsigned int ether_tid;
96   HANDLE ether_th1;
97   HANDLE ether_th2;
98 < static int net_if_type = -1;                            // Ethernet device type
98 > static int net_if_type = -1;    // Ethernet device type
99   #ifdef SHEEPSHAVER
100 < static bool net_open = false;                           // Flag: initialization succeeded, network device open
101 < uint8 ether_addr[6];                                            // Our Ethernet address
100 > static bool net_open = false;   // Flag: initialization succeeded, network device open
101 > uint8 ether_addr[6];                    // Our Ethernet address
102   #endif
103  
104   // These are protected by queue_csection
# Line 143 | Line 168 | static HANDLE int_sig2 = 0;
168   static HANDLE int_send_now = 0;
169  
170   // Prototypes
171 + static LPADAPTER tap_open_adapter(const char *dev_name);
172 + static void tap_close_adapter(LPADAPTER fd);
173 + static bool tap_check_version(LPADAPTER fd);
174 + static bool tap_set_status(LPADAPTER fd, ULONG status);
175 + static bool tap_get_mac(LPADAPTER fd, LPBYTE addr);
176 + static bool tap_receive_packet(LPADAPTER fd, LPPACKET lpPacket, BOOLEAN Sync);
177 + static bool tap_send_packet(LPADAPTER fd, LPPACKET lpPacket, BOOLEAN Sync, BOOLEAN recycle);
178   static WINAPI unsigned int slirp_receive_func(void *arg);
179   static WINAPI unsigned int ether_thread_feed_int(void *arg);
180   static WINAPI unsigned int ether_thread_get_packets_nt(void *arg);
# Line 202 | Line 234 | bool ether_init(void)
234                  net_if_type = NET_IF_ROUTER;
235          else if (strcmp(name, "slirp") == 0)
236                  net_if_type = NET_IF_SLIRP;
237 +        else if (strcmp(name, "tap") == 0)
238 +                net_if_type = NET_IF_TAP;
239          else
240                  net_if_type = NET_IF_B2ETHER;
241  
# Line 226 | Line 260 | bool ether_init(void)
260          case NET_IF_B2ETHER:
261                  dev_name = PrefsFindString("etherguid");
262                  break;
263 +        case NET_IF_TAP:
264 +                dev_name = PrefsFindString("etherguid");
265 +                break;
266          }
267          if (net_if_type == NET_IF_B2ETHER) {
268                  if (dev_name == NULL) {
# Line 261 | Line 298 | bool ether_init(void)
298                          D(bug("Fake 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]));
299                  }
300          }
301 +        else if (net_if_type == NET_IF_TAP) {
302 +                if (dev_name == NULL) {
303 +                        WarningAlert("No ethernet device GUID specified. Ethernet is not available.");
304 +                        goto open_error;
305 +                }
306 +
307 +                fd = tap_open_adapter(dev_name);
308 +                if (!fd) {
309 +                        sprintf(str, "Could not open ethernet adapter %s.", dev_name);
310 +                        WarningAlert(str);
311 +                        goto open_error;
312 +                }
313 +
314 +                if (!tap_check_version(fd)) {
315 +                        sprintf(str, "Minimal TAP-Win32 version supported is %d.%d.", TAP_VERSION_MIN_MAJOR, TAP_VERSION_MIN_MINOR);
316 +                        WarningAlert(str);
317 +                        goto open_error;
318 +                }
319 +
320 +                if (!tap_set_status(fd, true)) {
321 +                        sprintf(str, "Could not set media status to connected.");
322 +                        WarningAlert(str);
323 +                        goto open_error;
324 +                }
325 +
326 +                if (!tap_get_mac(fd, ether_addr)) {
327 +                        sprintf(str, "Could not get hardware address of device %s. Ethernet is not available.", dev_name);
328 +                        WarningAlert(str);
329 +                        goto open_error;
330 +                }
331 +                D(bug("Real 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]));
332 +
333 +                const char *ether_fake_address;
334 +                ether_fake_address = PrefsFindString("etherfakeaddress");
335 +                if (ether_fake_address && strlen(ether_fake_address) == 12) {
336 +                        char sm[10];
337 +                        strcpy( sm, "0x00" );
338 +                        for( int i=0; i<6; i++ ) {
339 +                                sm[2] = ether_fake_address[i*2];
340 +                                sm[3] = ether_fake_address[i*2+1];
341 +                                ether_addr[i] = (uint8)strtoul(sm,0,0);
342 +                        }
343 +                }
344 + #if 1
345 +                /*
346 +                  If we bridge the underlying ethernet connection and the TAP
347 +                  device altogether, we have to use a fake address.
348 +                 */
349 +                else {
350 +                        ether_addr[0] = 0x52;
351 +                        ether_addr[1] = 0x54;
352 +                        ether_addr[2] = 0x00;
353 +                }
354 + #endif
355 +                D(bug("Fake 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]));
356 +        }
357          else if (net_if_type == NET_IF_SLIRP) {
358                  ether_addr[0] = 0x52;
359                  ether_addr[1] = 0x54;
# Line 337 | Line 430 | bool ether_init(void)
430          thread_active = true;
431  
432          unsigned int dummy;
433 <        ether_th2 = (HANDLE)_beginthreadex( 0, 0,
434 <                net_if_type == NET_IF_SLIRP ? slirp_receive_func : ether_thread_get_packets_nt,
435 <                0, 0, &dummy );
433 >        unsigned int (WINAPI *receive_func)(void *);
434 >        switch (net_if_type) {
435 >        case NET_IF_SLIRP:
436 >          receive_func = slirp_receive_func;
437 >          break;
438 >        default:
439 >          receive_func = ether_thread_get_packets_nt;
440 >          break;
441 >        }
442 >        ether_th2 = (HANDLE)_beginthreadex( 0, 0, receive_func, 0, 0, &dummy );
443          ether_th1 = (HANDLE)_beginthreadex( 0, 0, ether_thread_write_packets, 0, 0, &dummy );
444  
445          // Everything OK
# Line 363 | Line 463 | bool ether_init(void)
463                  int_send_now = 0;
464                  thread_active = false;
465          }
466 <        if(net_if_type == NET_IF_B2ETHER) {
467 <                PacketCloseAdapter(fd);
466 >        if (fd) {
467 >                switch (net_if_type) {
468 >                case NET_IF_B2ETHER:
469 >                        PacketCloseAdapter(fd);
470 >                        break;
471 >                case NET_IF_TAP:
472 >                        tap_close_adapter(fd);
473 >                        break;
474 >                }
475 >                fd = 0;
476          }
369        fd = 0;
477          return false;
478   }
479  
# Line 437 | Line 544 | void ether_exit(void)
544          }
545  
546          // Close ethernet device
547 <        if(fd) {
548 <                PacketCloseAdapter(fd);
547 >        if (fd) {
548 >                switch (net_if_type) {
549 >                case NET_IF_B2ETHER:
550 >                        PacketCloseAdapter(fd);
551 >                        break;
552 >                case NET_IF_TAP:
553 >                        tap_close_adapter(fd);
554 >                        break;
555 >                }
556                  fd = 0;
557          }
558  
# Line 904 | Line 1018 | static unsigned int ether_thread_write_p
1018                                          // already recycled if async
1019                                  }
1020                                  break;
1021 +                        case NET_IF_TAP:
1022 +                                if (!tap_send_packet(fd, Packet, FALSE, TRUE)) {
1023 +                                        // already recycled if async
1024 +                                }
1025 +                                break;
1026                          case NET_IF_SLIRP:
1027                                  slirp_input((uint8 *)Packet->Buffer, Packet->Length);
1028                                  Packet->bIoComplete = TRUE;
# Line 1060 | Line 1179 | static bool set_wait_request(void)
1179  
1180  
1181   /*
1182 + *  TAP-Win32 glue
1183 + */
1184 +
1185 + static LPADAPTER tap_open_adapter(const char *dev_name)
1186 + {
1187 +        fd = (LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(*fd));
1188 +        if (fd == NULL)
1189 +                return NULL;
1190 +
1191 +        char dev_path[MAX_PATH];
1192 +        snprintf(dev_path, sizeof(dev_path),
1193 +                         "\\\\.\\Global\\%s.tap", dev_name);
1194 +
1195 +        HANDLE handle = CreateFile(
1196 +                dev_path,
1197 +                GENERIC_READ | GENERIC_WRITE,
1198 +                0,
1199 +                NULL,
1200 +                OPEN_EXISTING,
1201 +                FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED,
1202 +                NULL);
1203 +        if (handle == NULL || handle == INVALID_HANDLE_VALUE)
1204 +                return NULL;
1205 +
1206 +        fd->hFile = handle;
1207 +        return fd;
1208 + }
1209 +
1210 + static void tap_close_adapter(LPADAPTER fd)
1211 + {
1212 +        if (fd) {
1213 +                if (fd->hFile) {
1214 +                        tap_set_status(fd, false);
1215 +                        CloseHandle(fd->hFile);
1216 +                }
1217 +                GlobalFreePtr(fd);
1218 +        }
1219 + }
1220 +
1221 + static bool tap_check_version(LPADAPTER fd)
1222 + {
1223 +        ULONG len;
1224 +        ULONG info[3] = { 0, };
1225 +
1226 +        if (!DeviceIoControl(fd->hFile, TAP_IOCTL_GET_VERSION,
1227 +                                                 &info, sizeof(info),
1228 +                                                 &info, sizeof(info), &len, NULL)
1229 +                && !DeviceIoControl(fd->hFile, OLD_TAP_IOCTL_GET_VERSION,
1230 +                                                        &info, sizeof(info),
1231 +                                                        &info, sizeof(info), &len, NULL))
1232 +                return false;
1233 +
1234 +        if (info[0] > TAP_VERSION_MIN_MAJOR)
1235 +                return true;
1236 +        if (info[0] == TAP_VERSION_MIN_MAJOR && info[1] >= TAP_VERSION_MIN_MINOR)
1237 +                return true;
1238 +
1239 +        return false;
1240 + }
1241 +
1242 + static bool tap_set_status(LPADAPTER fd, ULONG status)
1243 + {
1244 +        DWORD len = 0;
1245 +        return DeviceIoControl(fd->hFile, TAP_IOCTL_SET_MEDIA_STATUS,
1246 +                                                   &status, sizeof (status),
1247 +                                                   &status, sizeof (status), &len, NULL);
1248 + }
1249 +
1250 + static bool tap_get_mac(LPADAPTER fd, LPBYTE addr)
1251 + {
1252 +        DWORD len = 0;
1253 +        return DeviceIoControl(fd->hFile, TAP_IOCTL_GET_MAC,
1254 +                                                   addr, 6,
1255 +                                                   addr, 6, &len, NULL);
1256 +                                                  
1257 + }
1258 +
1259 + static VOID CALLBACK tap_write_completion(
1260 +        DWORD dwErrorCode,
1261 +        DWORD dwNumberOfBytesTransfered,
1262 +        LPOVERLAPPED lpOverLapped
1263 +        )
1264 + {
1265 +        LPPACKET lpPacket = CONTAINING_RECORD(lpOverLapped, PACKET, OverLapped);
1266 +
1267 +        lpPacket->bIoComplete = TRUE;
1268 +        recycle_write_packet(lpPacket);
1269 + }
1270 +
1271 + static bool tap_send_packet(
1272 +        LPADAPTER fd,
1273 +        LPPACKET lpPacket,
1274 +        BOOLEAN Sync,
1275 +        BOOLEAN RecyclingAllowed)
1276 + {
1277 +        BOOLEAN Result;
1278 +
1279 +        lpPacket->OverLapped.Offset = 0;
1280 +        lpPacket->OverLapped.OffsetHigh = 0;
1281 +        lpPacket->bIoComplete = FALSE;
1282 +
1283 +        if (Sync) {
1284 +                Result = WriteFile(fd->hFile,
1285 +                                                   lpPacket->Buffer,
1286 +                                                   lpPacket->Length,
1287 +                                                   &lpPacket->BytesReceived,
1288 +                                                   &lpPacket->OverLapped);
1289 +                if (Result) {
1290 +                        GetOverlappedResult(fd->hFile,
1291 +                                                                &lpPacket->OverLapped,
1292 +                                                                &lpPacket->BytesReceived,
1293 +                                                                TRUE);
1294 +                }
1295 +                lpPacket->bIoComplete = TRUE;
1296 +                if (RecyclingAllowed)
1297 +                        PacketFreePacket(lpPacket);
1298 +        }
1299 +        else {
1300 +                Result = WriteFileEx(fd->hFile,
1301 +                                                         lpPacket->Buffer,
1302 +                                                         lpPacket->Length,
1303 +                                                         &lpPacket->OverLapped,
1304 +                                                         tap_write_completion);
1305 +
1306 +                if (!Result && RecyclingAllowed)
1307 +                        recycle_write_packet(lpPacket);
1308 +        }
1309 +
1310 +        return Result;
1311 + }
1312 +
1313 + static bool tap_receive_packet(LPADAPTER fd, LPPACKET lpPacket, BOOLEAN Sync)
1314 + {
1315 +        BOOLEAN Result;
1316 +
1317 +        lpPacket->OverLapped.Offset = 0;
1318 +        lpPacket->OverLapped.OffsetHigh = 0;
1319 +        lpPacket->bIoComplete = FALSE;
1320 +
1321 +        if (Sync) {
1322 +                Result = ReadFile(fd->hFile,
1323 +                                                  lpPacket->Buffer,
1324 +                                                  lpPacket->Length,
1325 +                                                  &lpPacket->BytesReceived,
1326 +                                                  &lpPacket->OverLapped);
1327 +                if (Result) {
1328 +                        Result = GetOverlappedResult(fd->hFile,
1329 +                                                                                 &lpPacket->OverLapped,
1330 +                                                                                 &lpPacket->BytesReceived,
1331 +                                                                                 TRUE);
1332 +                        if (Result)
1333 +                                lpPacket->bIoComplete = TRUE;
1334 +                        else
1335 +                                lpPacket->free = TRUE;
1336 +                }
1337 +        }
1338 +        else {
1339 +                Result = ReadFileEx(fd->hFile,
1340 +                                                        lpPacket->Buffer,
1341 +                                                        lpPacket->Length,
1342 +                                                        &lpPacket->OverLapped,
1343 +                                                        packet_read_completion);
1344 +
1345 +                if (!Result)
1346 +                        lpPacket->BytesReceived = 0;
1347 +        }
1348 +
1349 +        return Result;
1350 + }
1351 +
1352 +
1353 + /*
1354   *  SLIRP output buffer glue
1355   */
1356  
# Line 1073 | Line 1364 | void slirp_output(const uint8 *packet, i
1364          enqueue_packet(packet, len);
1365   }
1366  
1367 < unsigned int slirp_receive_func(void *arg)
1367 > static unsigned int slirp_receive_func(void *arg)
1368   {
1369          D(bug("slirp_receive_func\n"));
1370          thread_active_2 = true;
# Line 1151 | Line 1442 | VOID CALLBACK packet_read_completion(
1442                                          break;
1443                                  }
1444                          }
1445 +                        // XXX drop packets that are not for us
1446 +                        if (net_if_type == NET_IF_TAP) {
1447 +                                if (memcmp((LPBYTE)lpPacket->Buffer, ether_addr, 6) != 0)
1448 +                                        dwNumberOfBytesTransfered = 0;
1449 +                        }
1450                          if(dwNumberOfBytesTransfered) {
1451                                  if(net_if_type != NET_IF_ROUTER || !router_read_packet((uint8 *)lpPacket->Buffer, dwNumberOfBytesTransfered)) {
1452                                          enqueue_packet( (LPBYTE)lpPacket->Buffer, dwNumberOfBytesTransfered );
# Line 1223 | Line 1519 | static unsigned int ether_thread_get_pac
1519          // Obey the golden rules; keep the reads pending.
1520          while(thread_active) {
1521  
1522 <                if(net_if_type == NET_IF_B2ETHER) {
1522 >                if(net_if_type == NET_IF_B2ETHER || net_if_type == NET_IF_TAP) {
1523                          D(bug("Pending reads\n"));
1524                          for( i=0; thread_active && i<PACKET_POOL_COUNT; i++ ) {
1525                                  if(packets[i]->free) {
1526                                          packets[i]->free = FALSE;
1527 <                                        if(PacketReceivePacket(fd,packets[i],FALSE)) {
1527 >                                        BOOLEAN Result;
1528 >                                        switch (net_if_type) {
1529 >                                        case NET_IF_B2ETHER:
1530 >                                                Result = PacketReceivePacket(fd, packets[i], FALSE);
1531 >                                                break;
1532 >                                        case NET_IF_TAP:
1533 >                                                Result = tap_receive_packet(fd, packets[i], FALSE);
1534 >                                                break;
1535 >                                        }
1536 >                                        if (Result) {
1537                                                  if(packets[i]->bIoComplete) {
1538                                                          D(bug("Early io completion...\n"));
1539                                                          packet_read_completion(

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines