mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-07-27 00:31:28 +00:00
import NAT-Router code from original Basilisk II for Windows
This commit is contained in:
parent
eec1f6928a
commit
2de1c1760f
95
BasiliskII/src/Windows/router/arp.cpp
Executable file
95
BasiliskII/src/Windows/router/arp.cpp
Executable file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* arp.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2004 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "prefs.h"
|
||||
#include "ether_windows.h"
|
||||
#include "ether.h"
|
||||
#include "router.h"
|
||||
#include "router_types.h"
|
||||
#include "iphelp.h"
|
||||
#include "arp.h"
|
||||
#include "icmp.h"
|
||||
#include "dump.h"
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// ARP queries can be replied immediately.
|
||||
|
||||
bool write_arp( arp_t *req, int len )
|
||||
{
|
||||
D(bug("write_arp() len=%d, htype=%d, ptype=%04x, opcode=%d, halen=%d, palen=%d\r\n",len, ntohs(req->htype), ntohs(req->ptype), ntohs(req->opcode), req->halen, req->palen));
|
||||
|
||||
start_icmp_listen();
|
||||
|
||||
bool result = false;
|
||||
|
||||
if( len >= sizeof(arp_t) &&
|
||||
req->htype == htons(arp_hwtype_enet) &&
|
||||
req->ptype == htons(mac_type_ip4) &&
|
||||
req->opcode == htons(arp_request) &&
|
||||
req->halen == 6 &&
|
||||
req->palen == 4
|
||||
)
|
||||
{
|
||||
if(memcmp( req->srcp, req->dstp, 4 ) == 0) {
|
||||
// No reply. MacOS is making sure that there are no duplicate ip addresses.
|
||||
// Update localhost (==Mac) ip address (needed by incoming icmp)
|
||||
macos_ip_address = ntohl( *((uint32 *)&req->srcp[0]) );
|
||||
D(bug("Mac ip: %02x %02x %02x %02x\r\n", req->srcp[0], req->srcp[1], req->srcp[2], req->srcp[3]));
|
||||
} else {
|
||||
arp_t arp;
|
||||
|
||||
D(bug("Source NIC: %02x %02x %02x %02x\r\n", req->srcp[0], req->srcp[1], req->srcp[2], req->srcp[3]));
|
||||
D(bug("Dest NIC: %02x %02x %02x %02x\r\n", req->dstp[0], req->dstp[1], req->dstp[2], req->dstp[3]));
|
||||
|
||||
// memcpy( arp.mac.dest, req->mac.src, 6 );
|
||||
memcpy( arp.mac.dest, ether_addr, 6 );
|
||||
memcpy( arp.mac.src, router_mac_addr, 6 );
|
||||
arp.mac.type = htons(mac_type_arp);
|
||||
arp.htype = htons(arp_hwtype_enet);
|
||||
arp.ptype = htons(mac_type_ip4);
|
||||
arp.halen = 6;
|
||||
arp.palen = 4;
|
||||
arp.opcode = htons(arp_reply);
|
||||
memcpy( arp.srch, router_mac_addr, 6 );
|
||||
memcpy( arp.srcp, req->dstp, 4 );
|
||||
// memcpy( arp.dsth, req->srch, 6 );
|
||||
memcpy( arp.dsth, ether_addr, 6 );
|
||||
memcpy( arp.dstp, req->srcp, 4 );
|
||||
|
||||
// Update here, too, just in case.
|
||||
macos_ip_address = ntohl( *((uint32 *)&req->srcp[0]) );
|
||||
|
||||
enqueue_packet( (uint8 *)&arp, sizeof(arp) );
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
28
BasiliskII/src/Windows/router/arp.h
Executable file
28
BasiliskII/src/Windows/router/arp.h
Executable file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* arp.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ARP_H_
|
||||
#define _ARP_H_
|
||||
|
||||
bool write_arp( arp_t *req, int len );
|
||||
|
||||
#endif // _ARP_H_
|
49
BasiliskII/src/Windows/router/dump.cpp
Executable file
49
BasiliskII/src/Windows/router/dump.cpp
Executable file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* dump.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "dump.h"
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
void dump_bytes( uint8 *packet, int length )
|
||||
{
|
||||
#if DEBUG
|
||||
char buf[1000], sm[10];
|
||||
|
||||
*buf = 0;
|
||||
|
||||
if(length > 256) length = 256;
|
||||
|
||||
for (int i=0; i<length; i++) {
|
||||
sprintf(sm,"%02x", (int)packet[i]);
|
||||
strcat( buf, sm );
|
||||
}
|
||||
strcat( buf, "\r\n" );
|
||||
bug(buf);
|
||||
#endif
|
||||
}
|
30
BasiliskII/src/Windows/router/dump.h
Executable file
30
BasiliskII/src/Windows/router/dump.h
Executable file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* dump.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _DUMP_H_
|
||||
#define _DUMP_H_
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
void dump_bytes( uint8 *packet, int length );
|
||||
|
||||
#endif // _DUMP_H_
|
184
BasiliskII/src/Windows/router/dynsockets.cpp
Executable file
184
BasiliskII/src/Windows/router/dynsockets.cpp
Executable file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* dynsockets.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "dynsockets.h"
|
||||
#include "dump.h"
|
||||
#include "main.h"
|
||||
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
/*
|
||||
Cannot link statically to winsock. We need ws2, but there are
|
||||
Win95 b2 users who can't (or won't) upgrade.
|
||||
*/
|
||||
|
||||
static const char *wslib = "WS2_32.DLL";
|
||||
|
||||
static HMODULE hWinsock32 = 0;
|
||||
static WSADATA WSAData;
|
||||
|
||||
int (WSAAPI *_WSAStartup) (WORD, LPWSADATA) = 0;
|
||||
int (WSAAPI *_WSACleanup) (void) = 0;
|
||||
int (WSAAPI *_gethostname) (char *, int) = 0;
|
||||
char * (WSAAPI *_inet_ntoa) (struct in_addr) = 0;
|
||||
struct hostent * (WSAAPI *_gethostbyname) (const char *) = 0;
|
||||
int (WSAAPI *_send) (SOCKET, const char *, int, int) = 0;
|
||||
int (WSAAPI *_sendto) (SOCKET, const char *, int, int, const struct sockaddr *, int) = 0;
|
||||
int (WSAAPI *_recv) (SOCKET, char *, int, int) = 0;
|
||||
int (WSAAPI *_recvfrom) (SOCKET, char *, int, int, struct sockaddr *, int *) = 0;
|
||||
int (WSAAPI *_listen) (SOCKET, int) = 0;
|
||||
SOCKET (WSAAPI *_accept) (SOCKET, struct sockaddr *, int *) = 0;
|
||||
SOCKET (WSAAPI *_socket) (int, int, int) = 0;
|
||||
int (WSAAPI *_bind) (SOCKET, const struct sockaddr *, int) = 0;
|
||||
int (WSAAPI *_WSAAsyncSelect) (SOCKET, HWND, u_int, long) = 0;
|
||||
int (WSAAPI *_closesocket) (SOCKET) = 0;
|
||||
int (WSAAPI *_getsockname) (SOCKET, struct sockaddr *, int *) = 0;
|
||||
int (WSAAPI *_WSARecvFrom) (SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, struct sockaddr *, LPINT, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE) = 0;
|
||||
int (WSAAPI *_WSAGetLastError) (void) = 0;
|
||||
int (WSAAPI *_WSAConnect) (SOCKET, const struct sockaddr *, int, LPWSABUF, LPWSABUF, LPQOS, LPQOS) = 0;
|
||||
int (WSAAPI *_setsockopt) (SOCKET, int, int, const char *, int) = 0;
|
||||
int (WSAAPI *_WSAEventSelect) (SOCKET, WSAEVENT, long) = 0;
|
||||
WSAEVENT (WSAAPI *_WSACreateEvent) (void) = 0;
|
||||
BOOL (WSAAPI *_WSACloseEvent) (WSAEVENT) = 0;
|
||||
BOOL (WSAAPI *_WSAResetEvent) (WSAEVENT) = 0;
|
||||
int (WSAAPI *_WSAEnumNetworkEvents) (SOCKET, WSAEVENT, LPWSANETWORKEVENTS) = 0;
|
||||
int (WSAAPI *_shutdown) (SOCKET, int) = 0;
|
||||
int (WSAAPI *_WSASend) (SOCKET, LPWSABUF, DWORD, LPDWORD, DWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE) = 0;
|
||||
int (WSAAPI *_WSARecv) (SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE) = 0;
|
||||
unsigned long (WSAAPI *_inet_addr) (const char *) = 0;
|
||||
|
||||
static bool load_sockets()
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
hWinsock32 = LoadLibrary( wslib );
|
||||
if(!hWinsock32) {
|
||||
ErrorAlert("Could not load Winsock libraries; router module is not available. Please install Windows sockets 2.");
|
||||
} else {
|
||||
_WSAStartup = (int (WSAAPI *)(WORD, LPWSADATA))GetProcAddress( hWinsock32, "WSAStartup" );
|
||||
_WSACleanup = (int (WSAAPI *)(void))GetProcAddress( hWinsock32, "WSACleanup" );
|
||||
_gethostname = (int (WSAAPI *)(char *, int))GetProcAddress( hWinsock32, "gethostname" );
|
||||
_inet_ntoa = (char * (WSAAPI *)(struct in_addr))GetProcAddress( hWinsock32, "inet_ntoa" );
|
||||
_gethostbyname = (struct hostent * (WSAAPI *)(const char *))GetProcAddress( hWinsock32, "gethostbyname" );
|
||||
_send = (int (WSAAPI *)(SOCKET, const char *, int, int))GetProcAddress( hWinsock32, "send" );
|
||||
_sendto = (int (WSAAPI *)(SOCKET, const char *, int, int, const struct sockaddr *, int))GetProcAddress( hWinsock32, "sendto" );
|
||||
_recv = (int (WSAAPI *)(SOCKET, char *, int, int))GetProcAddress( hWinsock32, "recv" );
|
||||
_recvfrom = (int (WSAAPI *)(SOCKET, char *, int, int, struct sockaddr *, int *))GetProcAddress( hWinsock32, "recvfrom" );
|
||||
_listen = (int (WSAAPI *)(SOCKET, int))GetProcAddress( hWinsock32, "listen" );
|
||||
_accept = (SOCKET (WSAAPI *)(SOCKET, struct sockaddr *, int *))GetProcAddress( hWinsock32, "accept" );
|
||||
_socket = (SOCKET (WSAAPI *)(int, int, int))GetProcAddress( hWinsock32, "socket" );
|
||||
_bind = (int (WSAAPI *)(SOCKET, const struct sockaddr *, int))GetProcAddress( hWinsock32, "bind" );
|
||||
_WSAAsyncSelect = (int (WSAAPI *)(SOCKET, HWND, u_int, long))GetProcAddress( hWinsock32, "WSAAsyncSelect" );
|
||||
_closesocket = (int (WSAAPI *)(SOCKET))GetProcAddress( hWinsock32, "closesocket" );
|
||||
_getsockname = (int (WSAAPI *)(SOCKET, struct sockaddr *, int *))GetProcAddress( hWinsock32, "getsockname" );
|
||||
_WSARecvFrom = (int (WSAAPI *)(SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, struct sockaddr *, LPINT, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE))GetProcAddress( hWinsock32, "WSARecvFrom" );
|
||||
_WSAGetLastError = (int (WSAAPI *)(void))GetProcAddress( hWinsock32, "WSAGetLastError" );
|
||||
_WSAConnect = (int (WSAAPI *)(SOCKET, const struct sockaddr *, int, LPWSABUF, LPWSABUF, LPQOS, LPQOS))GetProcAddress( hWinsock32, "WSAConnect" );
|
||||
_setsockopt = (int (WSAAPI *)(SOCKET, int, int, const char *, int))GetProcAddress( hWinsock32, "setsockopt" );
|
||||
_WSAEventSelect = (int (WSAAPI *)(SOCKET, WSAEVENT, long))GetProcAddress( hWinsock32, "WSAEventSelect" );
|
||||
_WSACreateEvent = (WSAEVENT (WSAAPI *)(void))GetProcAddress( hWinsock32, "WSACreateEvent" );
|
||||
_WSACloseEvent = (BOOL (WSAAPI *)(WSAEVENT))GetProcAddress( hWinsock32, "WSACloseEvent" );
|
||||
_WSAResetEvent = (BOOL (WSAAPI *)(WSAEVENT))GetProcAddress( hWinsock32, "WSAResetEvent" );
|
||||
_WSAEnumNetworkEvents = (BOOL (WSAAPI *)(SOCKET, WSAEVENT, LPWSANETWORKEVENTS))GetProcAddress( hWinsock32, "WSAEnumNetworkEvents" );
|
||||
_shutdown = (int (WSAAPI *)(SOCKET, int))GetProcAddress( hWinsock32, "shutdown" );
|
||||
_WSASend = (int (WSAAPI *)(SOCKET, LPWSABUF, DWORD, LPDWORD, DWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE))GetProcAddress( hWinsock32, "WSASend" );
|
||||
_WSARecv = (int (WSAAPI *)(SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE))GetProcAddress( hWinsock32, "WSARecv" );
|
||||
_inet_addr = (unsigned long (WSAAPI *)(const char *))GetProcAddress( hWinsock32, "inet_addr" );
|
||||
|
||||
if( _WSAStartup && _WSACleanup && _gethostname && _inet_ntoa && _gethostbyname &&
|
||||
_send && _sendto && _recv && _recvfrom && _listen && _accept && _socket && _bind &&
|
||||
_WSAAsyncSelect && _closesocket && _getsockname && _WSARecvFrom && _WSAGetLastError &&
|
||||
_WSAConnect && _setsockopt && _WSAEventSelect && _WSACreateEvent && _WSACloseEvent &&
|
||||
_WSAResetEvent && _WSAEnumNetworkEvents && _shutdown && _WSASend && _WSARecv && _inet_addr
|
||||
)
|
||||
{
|
||||
result = true;
|
||||
} else {
|
||||
ErrorAlert("Could not find required entry points; router module is not available. Please install Windows sockets 2.");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool dynsockets_init(void)
|
||||
{
|
||||
bool result = false;
|
||||
if(load_sockets()) {
|
||||
if( (_WSAStartup(MAKEWORD(2,0), &WSAData)) != 0 ||
|
||||
LOBYTE( WSAData.wVersion ) != 2 ||
|
||||
HIBYTE( WSAData.wVersion ) != 0 )
|
||||
{
|
||||
ErrorAlert("Could not start Windows sockets version 2.");
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void dynsockets_final(void)
|
||||
{
|
||||
if(hWinsock32) {
|
||||
_WSACleanup();
|
||||
FreeLibrary( hWinsock32 );
|
||||
hWinsock32 = 0;
|
||||
}
|
||||
_WSAStartup = 0;
|
||||
_WSACleanup = 0;
|
||||
_gethostname = 0;
|
||||
_inet_ntoa = 0;
|
||||
_gethostbyname = 0;
|
||||
_send = 0;
|
||||
_sendto = 0;
|
||||
_recv = 0;
|
||||
_recvfrom = 0;
|
||||
_listen = 0;
|
||||
_accept = 0;
|
||||
_socket = 0;
|
||||
_bind = 0;
|
||||
_WSAAsyncSelect = 0;
|
||||
_closesocket = 0;
|
||||
_getsockname = 0;
|
||||
_WSARecvFrom = 0;
|
||||
_WSAGetLastError = 0;
|
||||
_WSAConnect = 0;
|
||||
_setsockopt = 0;
|
||||
_WSAEventSelect = 0;
|
||||
_WSACreateEvent = 0;
|
||||
_WSACloseEvent = 0;
|
||||
_WSAResetEvent = 0;
|
||||
_WSAEnumNetworkEvents = 0;
|
||||
_shutdown = 0;
|
||||
_WSASend = 0;
|
||||
_WSARecv = 0;
|
||||
_inet_addr = 0;
|
||||
}
|
59
BasiliskII/src/Windows/router/dynsockets.h
Executable file
59
BasiliskII/src/Windows/router/dynsockets.h
Executable file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* dynsockets.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _DYNSOCKETS_H_
|
||||
#define _DYNSOCKETS_H_
|
||||
|
||||
bool dynsockets_init(void);
|
||||
void dynsockets_final(void);
|
||||
|
||||
extern int (WSAAPI *_WSAStartup) (WORD, LPWSADATA);
|
||||
extern int (WSAAPI *_WSACleanup) (void);
|
||||
extern int (WSAAPI *_gethostname) (char *, int);
|
||||
extern char * (WSAAPI *_inet_ntoa) (struct in_addr);
|
||||
extern struct hostent * (WSAAPI *_gethostbyname) (const char *);
|
||||
extern int (WSAAPI *_send) (SOCKET, const char *, int, int);
|
||||
extern int (WSAAPI *_sendto) (SOCKET, const char *, int, int, const struct sockaddr *, int);
|
||||
extern int (WSAAPI *_recv) (SOCKET, char *, int, int);
|
||||
extern int (WSAAPI *_recvfrom) (SOCKET, char *, int, int, struct sockaddr *, int *);
|
||||
extern int (WSAAPI *_listen) (SOCKET, int);
|
||||
extern SOCKET (WSAAPI *_accept) (SOCKET, struct sockaddr *, int *);
|
||||
extern SOCKET (WSAAPI *_socket) (int, int, int);
|
||||
extern int (WSAAPI *_bind) (SOCKET, const struct sockaddr *, int);
|
||||
extern int (WSAAPI *_WSAAsyncSelect) (SOCKET, HWND, u_int, long);
|
||||
extern int (WSAAPI *_closesocket) (SOCKET);
|
||||
extern int (WSAAPI *_getsockname) (SOCKET, struct sockaddr *, int *);
|
||||
extern int (WSAAPI *_WSARecvFrom) (SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, struct sockaddr *, LPINT, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
|
||||
extern int (WSAAPI *_WSAGetLastError) (void);
|
||||
extern int (WSAAPI *_WSAConnect) (SOCKET, const struct sockaddr *, int, LPWSABUF, LPWSABUF, LPQOS, LPQOS);
|
||||
extern int (WSAAPI *_setsockopt) (SOCKET, int, int, const char *, int);
|
||||
extern int (WSAAPI *_WSAEventSelect) (SOCKET, WSAEVENT, long);
|
||||
extern WSAEVENT (WSAAPI *_WSACreateEvent) (void);
|
||||
extern BOOL (WSAAPI *_WSACloseEvent) (WSAEVENT);
|
||||
extern BOOL (WSAAPI *_WSAResetEvent) (WSAEVENT);
|
||||
extern int (WSAAPI *_WSAEnumNetworkEvents) (SOCKET, WSAEVENT, LPWSANETWORKEVENTS);
|
||||
extern int (WSAAPI *_shutdown) (SOCKET, int);
|
||||
extern int (WSAAPI *_WSASend) (SOCKET, LPWSABUF, DWORD, LPDWORD, DWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
|
||||
extern int (WSAAPI *_WSARecv) (SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
|
||||
extern unsigned long (WSAAPI *_inet_addr) (const char *);
|
||||
|
||||
#endif // _DYNSOCKETS_H_
|
192
BasiliskII/src/Windows/router/ftp.cpp
Executable file
192
BasiliskII/src/Windows/router/ftp.cpp
Executable file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* ftp.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include <ctype.h>
|
||||
#include "dump.h"
|
||||
#include "prefs.h"
|
||||
#include "ftp.h"
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
static int m_ftp_port_count = 0;
|
||||
#define MAX_FTP_PORTS 100
|
||||
static uint16 m_ftp_ports[MAX_FTP_PORTS];
|
||||
|
||||
bool ftp_is_ftp_port( uint16 port )
|
||||
{
|
||||
for( int i=0; i<m_ftp_port_count; i++ ) {
|
||||
if( m_ftp_ports[i] == port ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void init_ftp()
|
||||
{
|
||||
const char *str = PrefsFindString("ftp_port_list");
|
||||
|
||||
if(str) {
|
||||
char *ftp = new char [ strlen(str) + 1 ];
|
||||
if(ftp) {
|
||||
strcpy( ftp, str );
|
||||
char *p = ftp;
|
||||
while( p && *p ) {
|
||||
char *pp = strchr( p, ',' );
|
||||
if(pp) *pp++ = 0;
|
||||
if( m_ftp_port_count < MAX_FTP_PORTS ) {
|
||||
m_ftp_ports[m_ftp_port_count++] = (uint16)strtoul(p,0,0);
|
||||
}
|
||||
p = pp;
|
||||
}
|
||||
delete [] ftp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ftp_modify_port_command(
|
||||
char *buf,
|
||||
int &count,
|
||||
const uint32 max_size,
|
||||
const uint32 ip,
|
||||
const uint16 port,
|
||||
const bool is_pasv
|
||||
)
|
||||
{
|
||||
if( max_size < 100 ) {
|
||||
// impossible
|
||||
return;
|
||||
}
|
||||
|
||||
sprintf(
|
||||
buf,
|
||||
(is_pasv ? "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d).%c%c" : "PORT %d,%d,%d,%d,%d,%d%c%c"),
|
||||
ip >> 24,
|
||||
(ip >> 16) & 0xFF,
|
||||
(ip >> 8) & 0xFF,
|
||||
ip & 0xFF,
|
||||
(port >> 8) & 0xFF,
|
||||
port & 0xFF,
|
||||
0x0d, 0x0a
|
||||
);
|
||||
|
||||
count = strlen(buf);
|
||||
|
||||
D(bug("ftp_modify_port_command: \"%s\"\r\n", buf ));
|
||||
}
|
||||
|
||||
// this should be robust. rather skip it than do anything dangerous.
|
||||
void ftp_parse_port_command(
|
||||
char *buf,
|
||||
uint32 count,
|
||||
uint16 &ftp_data_port,
|
||||
bool is_pasv
|
||||
)
|
||||
{
|
||||
ftp_data_port = 0;
|
||||
|
||||
if( !count ) return;
|
||||
|
||||
uint8 b[100];
|
||||
uint32 ftp_ip = 0;
|
||||
|
||||
// make it a c-string
|
||||
if( count >= sizeof(b) ) count = sizeof(b)-1;
|
||||
memcpy( b, buf, count );
|
||||
b[ count ] = 0;
|
||||
|
||||
for( uint32 i=0; i<count; i++ ) {
|
||||
if( b[i] < ' ' || b[i] > 'z' ) {
|
||||
b[i] = ' ';
|
||||
} else {
|
||||
b[i] = tolower(b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// D(bug("FTP: \"%s\"\r\n", b ));
|
||||
|
||||
char *s = (char *)b;
|
||||
|
||||
while( *s == ' ' ) s++;
|
||||
|
||||
if(is_pasv) {
|
||||
/*
|
||||
LOCAL SERVER: ..227 Entering Passive Mode (192,168,0,2,6,236). 0d 0a
|
||||
*/
|
||||
if( atoi(s) == 227 && strstr(s,"passive") ) {
|
||||
while( *s && *s != '(' ) s++;
|
||||
if( *s++ == 0 ) s = 0;
|
||||
} else {
|
||||
s = 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
LOCAL CLIENT: PORT 192,168,0,1,14,147 0d 0a
|
||||
*/
|
||||
if( strncmp(s,"port ",5) == 0 ) {
|
||||
s += 5;
|
||||
} else {
|
||||
s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(s && *s) {
|
||||
// get remote ip (used only for verification)
|
||||
for( uint32 i=0; i<4; i++ ) {
|
||||
while( *s == ' ' ) s++;
|
||||
if(!isdigit(*s)) {
|
||||
ftp_ip = 0;
|
||||
break;
|
||||
}
|
||||
ftp_ip = (ftp_ip << 8) + atoi(s);
|
||||
while( *s && *s != ',' ) s++;
|
||||
if(!*s) {
|
||||
ftp_ip = 0;
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
if(ftp_ip) {
|
||||
// get local port
|
||||
for( uint32 i=0; i<2; i++ ) {
|
||||
while( *s == ' ' ) s++;
|
||||
if(!isdigit(*s)) {
|
||||
ftp_data_port = 0;
|
||||
break;
|
||||
}
|
||||
ftp_data_port = (ftp_data_port << 8) + atoi(s);
|
||||
while( *s && *s != ',' && *s != ')' ) s++;
|
||||
if(!*s)
|
||||
break;
|
||||
else
|
||||
s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ftp_data_port) {
|
||||
D(bug("ftp_parse_port_command: \"%s\"; port is %d\r\n", b, ftp_data_port ));
|
||||
}
|
||||
}
|
50
BasiliskII/src/Windows/router/ftp.h
Executable file
50
BasiliskII/src/Windows/router/ftp.h
Executable file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* ftp.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _FTP_H_
|
||||
#define _FTP_H_
|
||||
|
||||
// Read the preferences.
|
||||
void init_ftp();
|
||||
|
||||
// Compares against a list provided by the user.
|
||||
bool ftp_is_ftp_port( uint16 port );
|
||||
|
||||
// Determine whether this is a ftp client PORT command or ftp server entering to passive mode.
|
||||
void ftp_parse_port_command(
|
||||
char *buf,
|
||||
uint32 count,
|
||||
uint16 &ftp_data_port,
|
||||
bool is_pasv
|
||||
);
|
||||
|
||||
// Build a new command using ip and port.
|
||||
void ftp_modify_port_command(
|
||||
char *buf,
|
||||
int &count,
|
||||
const uint32 max_size,
|
||||
const uint32 ip,
|
||||
const uint16 port,
|
||||
const bool is_pasv
|
||||
);
|
||||
|
||||
#endif // _FTP_H_
|
220
BasiliskII/src/Windows/router/icmp.cpp
Executable file
220
BasiliskII/src/Windows/router/icmp.cpp
Executable file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* icmp.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2004 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "ws2tcpip.h"
|
||||
#include "prefs.h"
|
||||
#include "ether_windows.h"
|
||||
#include "ether.h"
|
||||
#include "router.h"
|
||||
#include "router_types.h"
|
||||
#include "dynsockets.h"
|
||||
#include "ipsocket.h"
|
||||
#include "iphelp.h"
|
||||
#include "icmp.h"
|
||||
#include "dump.h"
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
// Saved for cleanup.
|
||||
static socket_t *icmp_incoming_s = 0;
|
||||
|
||||
|
||||
void stop_icmp_listen()
|
||||
{
|
||||
if(icmp_incoming_s) {
|
||||
delete icmp_incoming_s;
|
||||
icmp_incoming_s = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void start_icmp_listen()
|
||||
{
|
||||
if(!icmp_incoming_s) {
|
||||
icmp_incoming_s = new socket_t(IPPROTO_ICMP);
|
||||
|
||||
icmp_incoming_s->permanent = TRUE;
|
||||
icmp_incoming_s->s = _socket( AF_INET, SOCK_RAW, IPPROTO_ICMP );
|
||||
|
||||
memset( &icmp_incoming_s->from, 0, icmp_incoming_s->from_len );
|
||||
icmp_incoming_s->from.sin_family = AF_INET;
|
||||
|
||||
if(icmp_incoming_s->s == INVALID_SOCKET) {
|
||||
D(bug("Failed to create icmp listening socket (NT/no admin?)\r\n" ));
|
||||
delete icmp_incoming_s;
|
||||
icmp_incoming_s = 0;
|
||||
} else {
|
||||
D(bug("icmp listening socket created\r\n" ));
|
||||
raw_sockets_available = true;
|
||||
struct sockaddr_in to;
|
||||
memset( &to, 0, sizeof(to) );
|
||||
to.sin_family = AF_INET;
|
||||
if( _bind ( icmp_incoming_s->s, (const struct sockaddr *)&to, sizeof(to) ) == SOCKET_ERROR ) {
|
||||
D(bug("Listening to inbound icmp failed, error code = %d\r\n", _WSAGetLastError() ));
|
||||
_closesocket( icmp_incoming_s->s );
|
||||
delete icmp_incoming_s;
|
||||
icmp_incoming_s = 0;
|
||||
} else {
|
||||
D(bug("icmp listening socket bound\r\n" ));
|
||||
if(!icmp_incoming_s->b_recfrom()) {
|
||||
D(bug("b_recfrom() from inbound icmp failed, error code = %d\r\n", _WSAGetLastError() ));
|
||||
// _closesocket( icmp_incoming_s->s );
|
||||
// delete icmp_incoming_s;
|
||||
// icmp_incoming_s = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CALLBACK icmp_read_completion(
|
||||
DWORD error,
|
||||
DWORD bytes_read,
|
||||
LPWSAOVERLAPPED lpOverlapped,
|
||||
DWORD flags
|
||||
)
|
||||
{
|
||||
D(bug("icmp_read_completion(error=0x%x, bytes_read=%d, flags=0x%x)\r\n", error, bytes_read, flags));
|
||||
|
||||
socket_t *cmpl = (socket_t *)lpOverlapped->hEvent;
|
||||
|
||||
if(error == 0 && macos_ip_address != 0) {
|
||||
if(bytes_read > 1460) {
|
||||
D(bug("discarding oversized icmp packet, size = \r\n", bytes_read));
|
||||
} else {
|
||||
int icmp_size = sizeof(mac_t) + bytes_read;
|
||||
icmp_t *icmp = (icmp_t *)malloc( icmp_size );
|
||||
if(icmp) {
|
||||
mac_t *mac = (mac_t *)icmp;
|
||||
ip_t *ip = (ip_t *)icmp;
|
||||
|
||||
memcpy( mac->dest, ether_addr, 6 );
|
||||
memcpy( mac->src, router_mac_addr, 6 );
|
||||
mac->type = htons(mac_type_ip4);
|
||||
|
||||
// Copy payload (used by ICMP checksum)
|
||||
memcpy( (char *)icmp + sizeof(mac_t), cmpl->buffers[0].buf, bytes_read );
|
||||
|
||||
switch( icmp->type ) {
|
||||
// May need to patch the returned ip header.
|
||||
case icmp_Destination_unreachable:
|
||||
case icmp_Source_quench:
|
||||
case icmp_Redirect:
|
||||
case icmp_Time_exceeded:
|
||||
case icmp_Parameter_problem:
|
||||
ip_t *ip_if = (ip_t *)( (char *)icmp + sizeof(icmp_t) + sizeof(uint32) - sizeof(mac_t) );
|
||||
|
||||
// This would be needed (traceroute)
|
||||
// ip_if->ident = ??;
|
||||
|
||||
// Cannot fix some fields, this should be enough:
|
||||
ip_if->src = htonl(macos_ip_address);
|
||||
|
||||
if(ip_if->proto == ip_proto_udp) {
|
||||
udp_t *udp_if = (udp_t *)ip_if;
|
||||
// udp_if->src_port = ... don't know!;
|
||||
} else if(ip_if->proto == ip_proto_tcp) {
|
||||
tcp_t *tcp_if = (tcp_t *)ip_if;
|
||||
// tcp_if->src_port = ... don't know!;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
make_icmp_checksum( icmp, icmp_size );
|
||||
|
||||
// Replace the target ip address
|
||||
ip->dest = htonl(macos_ip_address);
|
||||
ip->ttl--;
|
||||
make_ip4_checksum( ip );
|
||||
|
||||
dump_bytes( (uint8 *)icmp, icmp_size );
|
||||
|
||||
if( ip->ttl == 0 ) {
|
||||
D(bug("icmp packet ttl expired\r\n"));
|
||||
} else {
|
||||
enqueue_packet( (uint8 *)icmp, icmp_size );
|
||||
}
|
||||
free(icmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memset( &cmpl->from, 0, cmpl->from_len );
|
||||
|
||||
if(is_router_shutting_down) {
|
||||
delete cmpl;
|
||||
} else if(cmpl->s == INVALID_SOCKET || !cmpl->b_recfrom()) {
|
||||
// delete cmpl;
|
||||
}
|
||||
}
|
||||
|
||||
void write_icmp( icmp_t *icmp, int len )
|
||||
{
|
||||
struct in_addr ia;
|
||||
ia.s_addr = icmp->ip.dest;
|
||||
D(bug("write_icmp(%s)\r\n", _inet_ntoa(ia) ));
|
||||
|
||||
if(!raw_sockets_available) {
|
||||
D(bug("write_icmp() cannot proceed, raw sockets not available\r\n" ));
|
||||
return;
|
||||
}
|
||||
|
||||
if(len < sizeof(icmp_t)) {
|
||||
D(bug("Too small icmp packet(%d), dropped\r\n", len));
|
||||
return;
|
||||
}
|
||||
|
||||
// must be updated, ttl changed
|
||||
make_icmp_checksum( icmp, len );
|
||||
|
||||
SOCKET s = _socket( AF_INET, SOCK_RAW, IPPROTO_ICMP );
|
||||
if(s != INVALID_SOCKET) {
|
||||
struct sockaddr_in to;
|
||||
memset( &to, 0, sizeof(to) );
|
||||
to.sin_family = AF_INET;
|
||||
to.sin_addr.s_addr = icmp->ip.dest;
|
||||
|
||||
char *data = (char *)icmp + sizeof(ip_t);
|
||||
int dlen = len - sizeof(ip_t);
|
||||
|
||||
int ttl = icmp->ip.ttl;
|
||||
if(_setsockopt( s, IPPROTO_IP, IP_TTL, (const char *)&ttl, sizeof(int) ) == SOCKET_ERROR ) {
|
||||
D(bug("could not set ttl to %d.\r\n", ttl));
|
||||
} else {
|
||||
D(bug("ttl set to %d.\r\n", ttl));
|
||||
}
|
||||
|
||||
if(SOCKET_ERROR == _sendto( s, data, dlen, 0, (struct sockaddr *)&to, sizeof(to) )) {
|
||||
D(bug("Failed to send icmp via raw socket\r\n" ));
|
||||
}
|
||||
_closesocket(s);
|
||||
} else {
|
||||
D(bug("Could not create raw socket for icmp\r\n" ));
|
||||
}
|
||||
}
|
38
BasiliskII/src/Windows/router/icmp.h
Executable file
38
BasiliskII/src/Windows/router/icmp.h
Executable file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* icmp.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ICMP_H_
|
||||
#define _ICMP_H_
|
||||
|
||||
void start_icmp_listen();
|
||||
void stop_icmp_listen();
|
||||
|
||||
void write_icmp( icmp_t *icmp, int len );
|
||||
|
||||
void CALLBACK icmp_read_completion(
|
||||
DWORD error,
|
||||
DWORD bytes_read,
|
||||
LPWSAOVERLAPPED lpOverlapped,
|
||||
DWORD flags
|
||||
);
|
||||
|
||||
#endif // _ICMP_H_
|
235
BasiliskII/src/Windows/router/iphelp.cpp
Executable file
235
BasiliskII/src/Windows/router/iphelp.cpp
Executable file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* iphelp.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "ether_windows.h"
|
||||
#include "ether.h"
|
||||
#include "router.h"
|
||||
#include "router_types.h"
|
||||
#include "tcp.h"
|
||||
#include "icmp.h"
|
||||
#include "udp.h"
|
||||
#include "iphelp.h"
|
||||
#include "dump.h"
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
void make_icmp_checksum( icmp_t *icmp, int len )
|
||||
{
|
||||
icmp->checksum = 0;
|
||||
|
||||
uint16 sz = (len-sizeof(ip_t))/2;
|
||||
uint16 *p = (uint16 *)( (uint8 *)icmp + sizeof(ip_t) );
|
||||
|
||||
uint32 sum32 = 0;
|
||||
for( int i=0; i<sz; i++ ) {
|
||||
sum32 += ntohs(p[i]);
|
||||
}
|
||||
|
||||
while( HIWORD(sum32) ) {
|
||||
sum32 = HIWORD(sum32) + LOWORD(sum32);
|
||||
}
|
||||
sum32 = ~sum32;
|
||||
icmp->checksum = htons((uint16)sum32);
|
||||
}
|
||||
|
||||
void make_tcp_checksum( tcp_t *tcp, int len )
|
||||
{
|
||||
tcp->checksum = 0;
|
||||
|
||||
int tcp_len = len - sizeof(ip_t);
|
||||
uint16 sz = tcp_len/2;
|
||||
uint16 *p = (uint16 *)( (uint8 *)tcp + sizeof(ip_t) );
|
||||
|
||||
uint32 sum32 = 0;
|
||||
for( int i=0; i<sz; i++ ) {
|
||||
sum32 += ntohs(p[i]);
|
||||
}
|
||||
|
||||
if(len & 1) {
|
||||
uint8 *p8 = (uint8 *)p;
|
||||
sum32 += p8[tcp_len-1] << 8;
|
||||
}
|
||||
|
||||
pseudo_ip_t pseudo;
|
||||
pseudo.src_lo = LOWORD(ntohl(tcp->ip.src));
|
||||
pseudo.src_hi = HIWORD(ntohl(tcp->ip.src));
|
||||
pseudo.dest_lo = LOWORD(ntohl(tcp->ip.dest));
|
||||
pseudo.dest_hi = HIWORD(ntohl(tcp->ip.dest));
|
||||
pseudo.proto = (uint16)tcp->ip.proto;
|
||||
pseudo.msg_len = tcp->header_len >> 2;
|
||||
|
||||
int datalen = len - sizeof(tcp_t);
|
||||
pseudo.msg_len += datalen;
|
||||
|
||||
p = (uint16 *)&pseudo;
|
||||
|
||||
for( int i=0; i<sizeof(pseudo_ip_t)/2; i++ ) {
|
||||
sum32 += p[i];
|
||||
}
|
||||
|
||||
while( HIWORD(sum32) ) {
|
||||
sum32 = HIWORD(sum32) + LOWORD(sum32);
|
||||
}
|
||||
sum32 = ~sum32;
|
||||
tcp->checksum = htons((uint16)sum32);
|
||||
}
|
||||
|
||||
void make_ip4_checksum( ip_t *ip )
|
||||
{
|
||||
ip->checksum = 0;
|
||||
uint16 sz = ip->header_len * 2;
|
||||
uint16 *p = (uint16 *)( (uint8 *)ip + sizeof(mac_t) );
|
||||
|
||||
uint32 sum32 = 0;
|
||||
for( int i=0; i<sz; i++ ) {
|
||||
sum32 += ntohs(p[i]);
|
||||
}
|
||||
|
||||
while( HIWORD(sum32) ) {
|
||||
sum32 = HIWORD(sum32) + LOWORD(sum32);
|
||||
}
|
||||
|
||||
sum32 = ~sum32;
|
||||
ip->checksum = htons((uint16)sum32);
|
||||
}
|
||||
|
||||
void make_udp_checksum( udp_t *udp )
|
||||
{
|
||||
udp->checksum = 0;
|
||||
return;
|
||||
|
||||
// UDP checksums are optional.
|
||||
|
||||
/*
|
||||
uint16 sz = ntohs(udp->msg_len) / 2;
|
||||
uint16 *p = (uint16 *)( (uint8 *)udp + sizeof(ip_t) );
|
||||
|
||||
uint32 sum32 = 0;
|
||||
for( int i=0; i<sz; i++ ) {
|
||||
sum32 += ntohs(p[i]);
|
||||
}
|
||||
|
||||
// last byte??
|
||||
|
||||
pseudo_ip_t pseudo;
|
||||
pseudo.src_lo = LOWORD(ntohl(udp->ip.src));
|
||||
pseudo.src_hi = HIWORD(ntohl(udp->ip.src));
|
||||
pseudo.dest_lo = LOWORD(ntohl(udp->ip.dest));
|
||||
pseudo.dest_hi = HIWORD(ntohl(udp->ip.dest));
|
||||
pseudo.proto = (uint16)udp->ip.proto;
|
||||
pseudo.msg_len = ntohs(udp->msg_len); // ???
|
||||
|
||||
p = (uint16 *)&pseudo;
|
||||
|
||||
for( i=0; i<sizeof(pseudo_ip_t)/2; i++ ) {
|
||||
sum32 += p[i];
|
||||
}
|
||||
|
||||
while( HIWORD(sum32) ) {
|
||||
sum32 = HIWORD(sum32) + LOWORD(sum32);
|
||||
}
|
||||
sum32 = ~sum32;
|
||||
udp->checksum = htons((uint16)sum32);
|
||||
*/
|
||||
}
|
||||
|
||||
void error_winsock_2_icmp( int err, ip_t *ip_err, int dlen_err )
|
||||
{
|
||||
int type = -1, code = -1, msg_size = 0;
|
||||
|
||||
switch( err ) {
|
||||
case WSAEHOSTUNREACH:
|
||||
case WSAETIMEDOUT:
|
||||
type = icmp_Destination_unreachable;
|
||||
code = 1; // Host unreachable
|
||||
msg_size = (ip_err->header_len << 2) + 4 + 8; // ip header + unused + 64 msg bits
|
||||
break;
|
||||
case WSAENETDOWN:
|
||||
case WSAENETUNREACH:
|
||||
type = icmp_Destination_unreachable;
|
||||
code = 0; // Network unreachable
|
||||
msg_size = (ip_err->header_len << 2) + 4 + 8; // ip header + unused + 64 msg bits
|
||||
break;
|
||||
case WSAETTLEXCEEDED:
|
||||
type = icmp_Time_exceeded;
|
||||
code = 0; // Transit TTL exceeded
|
||||
msg_size = (ip_err->header_len << 2) + 4 + 8; // ip header + unused + 64 msg bits
|
||||
break;
|
||||
}
|
||||
|
||||
if(type >= 0 && macos_ip_address != 0) {
|
||||
D(bug("sending icmp error reply. type=%d, code=%d, msg_size=%d\r\n", type, code, msg_size));
|
||||
|
||||
int icmp_size = sizeof(icmp_t) + msg_size;
|
||||
|
||||
icmp_t *icmp = (icmp_t *)malloc( icmp_size );
|
||||
if(icmp) {
|
||||
mac_t *mac = (mac_t *)icmp;
|
||||
ip_t *ip = (ip_t *)icmp;
|
||||
|
||||
memcpy( mac->dest, ether_addr, 6 );
|
||||
memcpy( mac->src, router_mac_addr, 6 );
|
||||
mac->type = htons(mac_type_ip4);
|
||||
|
||||
ip->version = 4;
|
||||
ip->header_len = 5;
|
||||
ip->tos = 0;
|
||||
ip->total_len = htons(sizeof(icmp_t) - sizeof(mac_t) + msg_size);
|
||||
|
||||
ip->ident = htons(next_ip_ident_number++);
|
||||
ip->flags_n_frag_offset = 0;
|
||||
ip->ttl = 128;
|
||||
ip->proto = ip_proto_icmp;
|
||||
ip->src = htonl(router_ip_address);
|
||||
ip->dest = htonl(macos_ip_address);
|
||||
make_ip4_checksum( ip );
|
||||
|
||||
icmp->type = type;
|
||||
icmp->code = code;
|
||||
|
||||
// zero out the unused field
|
||||
memset( (char *)icmp + sizeof(icmp_t), 0, sizeof(uint32) );
|
||||
|
||||
// copy 64 bits of original message
|
||||
memcpy(
|
||||
(char *)icmp + sizeof(icmp_t) + sizeof(uint32),
|
||||
(char *)ip_err + sizeof(mac_t),
|
||||
msg_size
|
||||
);
|
||||
|
||||
make_icmp_checksum( icmp, icmp_size );
|
||||
|
||||
dump_bytes( (uint8 *)icmp, icmp_size );
|
||||
|
||||
enqueue_packet( (uint8 *)icmp, icmp_size );
|
||||
free(icmp);
|
||||
}
|
||||
}
|
||||
}
|
36
BasiliskII/src/Windows/router/iphelp.h
Executable file
36
BasiliskII/src/Windows/router/iphelp.h
Executable file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* iphelp.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _IPHELP_H_
|
||||
#define _IPHELP_H_
|
||||
|
||||
// Fake ttl exceeded code.
|
||||
#define WSAETTLEXCEEDED (WSABASEERR + 1999 + 17)
|
||||
|
||||
void error_winsock_2_icmp( int err, ip_t *ip_err, int dlen_err );
|
||||
|
||||
void make_icmp_checksum( icmp_t *icmp, int len );
|
||||
void make_ip4_checksum( ip_t *ip );
|
||||
void make_udp_checksum( udp_t *udp );
|
||||
void make_tcp_checksum( tcp_t *tcp, int len );
|
||||
|
||||
#endif // _IPHELP_H_
|
265
BasiliskII/src/Windows/router/ipsocket.cpp
Executable file
265
BasiliskII/src/Windows/router/ipsocket.cpp
Executable file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* ipsocket.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "ws2tcpip.h"
|
||||
#include "prefs.h"
|
||||
#include "ether_windows.h"
|
||||
#include "ether.h"
|
||||
#include "router.h"
|
||||
#include "router_types.h"
|
||||
#include "dynsockets.h"
|
||||
#include "ipsocket.h"
|
||||
#include "icmp.h"
|
||||
#include "tcp.h"
|
||||
#include "udp.h"
|
||||
#include "dump.h"
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
socket_t::socket_t( int _proto )
|
||||
{
|
||||
s = INVALID_SOCKET;
|
||||
proto = _proto;
|
||||
|
||||
ip_src = ip_dest = 0;
|
||||
src_port = dest_port = 0;
|
||||
|
||||
memset( &overlapped, 0, sizeof(overlapped) );
|
||||
overlapped.hEvent = (HANDLE)this;
|
||||
|
||||
bytes_received = 0;
|
||||
flags = 0;
|
||||
from_len = sizeof(struct sockaddr_in);
|
||||
memset( &from, 0, sizeof(from) );
|
||||
from.sin_family = AF_INET;
|
||||
|
||||
buffer_count = 1;
|
||||
buffers[0].len = 1460;
|
||||
buffers[0].buf = new char [buffers[0].len];
|
||||
|
||||
out_buffers[0].len = 1460;
|
||||
out_buffers[0].buf = new char [out_buffers[0].len];
|
||||
|
||||
socket_ttl = GetTickCount() + 60000L;
|
||||
permanent = false;
|
||||
}
|
||||
|
||||
socket_t::~socket_t()
|
||||
{
|
||||
if(s != INVALID_SOCKET) {
|
||||
_closesocket( s ); // slam!
|
||||
s = INVALID_SOCKET;
|
||||
}
|
||||
delete [] out_buffers[0].buf;
|
||||
delete [] buffers[0].buf;
|
||||
}
|
||||
|
||||
int socket_t::WSARecvFrom()
|
||||
{
|
||||
return _WSARecvFrom(
|
||||
s,
|
||||
buffers,
|
||||
buffer_count,
|
||||
&bytes_received,
|
||||
&flags,
|
||||
(struct sockaddr *)&from,
|
||||
&from_len,
|
||||
&overlapped,
|
||||
proto == IPPROTO_UDP ? udp_read_completion : icmp_read_completion
|
||||
);
|
||||
}
|
||||
|
||||
bool socket_t::b_recfrom()
|
||||
{
|
||||
bool result;
|
||||
|
||||
int ret = WSARecvFrom();
|
||||
|
||||
if(ret == SOCKET_ERROR) {
|
||||
int socket_error = _WSAGetLastError();
|
||||
if(socket_error == WSA_IO_PENDING) {
|
||||
D(bug("WSARecvFrom() i/o pending\r\n"));
|
||||
result = true;
|
||||
} else {
|
||||
D(bug("_WSAGetLastError() returned %d\r\n", socket_error));
|
||||
result = false;
|
||||
}
|
||||
} else /*if(ret == 0) */ {
|
||||
D(bug("WSARecvFrom() ok\r\n"));
|
||||
// Completion routine call is already scheduled.
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void socket_t::set_ttl( uint8 ttl )
|
||||
{
|
||||
int _ttl = ttl; // defensive programming, I know VCx
|
||||
|
||||
if(_setsockopt( s, IPPROTO_IP, IP_TTL, (const char *)&_ttl, sizeof(int) ) == SOCKET_ERROR ) {
|
||||
D(bug("could not set ttl to %d.\r\n", ttl));
|
||||
} else {
|
||||
D(bug("ttl set to %d.\r\n", ttl));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define MAX_OPEN_SOCKETS 1024
|
||||
static socket_t *all_sockets[MAX_OPEN_SOCKETS];
|
||||
static int open_sockets = 0;
|
||||
|
||||
int get_socket_index( uint16 src_port, uint16 dest_port, int proto )
|
||||
{
|
||||
int result = -1;
|
||||
for( int i=0; i<open_sockets; i++ ) {
|
||||
socket_t *cmpl = all_sockets[i];
|
||||
if(cmpl->src_port == src_port && cmpl->dest_port == dest_port && cmpl->proto == proto ) {
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int get_socket_index( uint16 src_port, int proto )
|
||||
{
|
||||
int result = -1;
|
||||
for( int i=0; i<open_sockets; i++ ) {
|
||||
socket_t *cmpl = all_sockets[i];
|
||||
if(cmpl->src_port == src_port && cmpl->proto == proto ) {
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int get_socket_index( socket_t *cmpl )
|
||||
{
|
||||
int result = -1;
|
||||
for( int i=0; i<open_sockets; i++ ) {
|
||||
if(cmpl == all_sockets[i]) {
|
||||
result = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void delete_socket( socket_t *cmpl )
|
||||
{
|
||||
D(bug("deleting socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port));
|
||||
|
||||
EnterCriticalSection( &router_section );
|
||||
int i = get_socket_index( cmpl );
|
||||
if( i >= 0 ) {
|
||||
delete all_sockets[i];
|
||||
all_sockets[i] = all_sockets[--open_sockets];
|
||||
} else {
|
||||
D(bug("Deleted socket not in table!\r\n"));
|
||||
// delete cmpl;
|
||||
}
|
||||
LeaveCriticalSection( &router_section );
|
||||
}
|
||||
|
||||
socket_t *find_socket( uint16 src_port, uint16 dest_port, int proto )
|
||||
{
|
||||
socket_t *result = 0;
|
||||
EnterCriticalSection( &router_section );
|
||||
int i = get_socket_index( src_port, dest_port, proto );
|
||||
if( i >= 0 ) {
|
||||
result = all_sockets[i];
|
||||
} else {
|
||||
i = get_socket_index( src_port, proto );
|
||||
if( i >= 0 ) {
|
||||
delete_socket( all_sockets[i] );
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection( &router_section );
|
||||
|
||||
D(bug("find_socket(%d,%d): %s\r\n", src_port, dest_port, result ? "found" : "not found"));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void add_socket( socket_t *cmpl )
|
||||
{
|
||||
D(bug("adding socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port));
|
||||
|
||||
EnterCriticalSection( &router_section );
|
||||
if( open_sockets < MAX_OPEN_SOCKETS ) {
|
||||
all_sockets[open_sockets++] = cmpl;
|
||||
} else {
|
||||
// Urgchiyuppijee! (that's finnish language, meaning "do something about this")
|
||||
delete all_sockets[0];
|
||||
all_sockets[0] = cmpl;
|
||||
}
|
||||
LeaveCriticalSection( &router_section );
|
||||
}
|
||||
|
||||
void close_old_sockets()
|
||||
{
|
||||
DWORD now = GetTickCount();
|
||||
|
||||
EnterCriticalSection( &router_section );
|
||||
for( int i=open_sockets-1; i>=0; i-- ) {
|
||||
socket_t *cmpl = all_sockets[i];
|
||||
if( !cmpl->permanent && now >= cmpl->socket_ttl ) {
|
||||
D(bug("expiring socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port));
|
||||
if(cmpl->s == INVALID_SOCKET) {
|
||||
delete all_sockets[i];
|
||||
all_sockets[i] = all_sockets[--open_sockets];
|
||||
} else {
|
||||
// read completion will deallocate
|
||||
_closesocket( cmpl->s );
|
||||
}
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection( &router_section );
|
||||
}
|
||||
|
||||
void close_all_sockets()
|
||||
{
|
||||
D(bug("closing all(%d) sockets\r\n", open_sockets));
|
||||
|
||||
EnterCriticalSection( &router_section );
|
||||
for( int i=0; i<open_sockets; i++ ) {
|
||||
socket_t *cmpl = all_sockets[i];
|
||||
D(bug("closing socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port));
|
||||
if(cmpl->s == INVALID_SOCKET) {
|
||||
delete all_sockets[i];
|
||||
all_sockets[i] = all_sockets[--open_sockets];
|
||||
} else {
|
||||
// read completion will deallocate
|
||||
_closesocket( cmpl->s );
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection( &router_section );
|
||||
}
|
66
BasiliskII/src/Windows/router/ipsocket.h
Executable file
66
BasiliskII/src/Windows/router/ipsocket.h
Executable file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* ipsocket.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _IPSOCKET_H_
|
||||
#define _IPSOCKET_H_
|
||||
|
||||
class socket_t {
|
||||
public:
|
||||
socket_t( int _proto );
|
||||
~socket_t();
|
||||
bool b_recfrom();
|
||||
void set_ttl( uint8 ttl );
|
||||
|
||||
protected:
|
||||
int WSARecvFrom();
|
||||
|
||||
public:
|
||||
SOCKET s; // Always a valid socket
|
||||
BOOL permanent; // T: a user-defined listening socket,
|
||||
int proto; // udp/icmp
|
||||
WSABUF buffers[1];
|
||||
WSABUF out_buffers[1];
|
||||
DWORD buffer_count;
|
||||
DWORD bytes_received;
|
||||
DWORD flags;
|
||||
struct sockaddr_in from;
|
||||
int from_len;
|
||||
WSAOVERLAPPED overlapped;
|
||||
uint32 ip_src;
|
||||
uint32 ip_dest;
|
||||
uint16 src_port;
|
||||
uint16 dest_port;
|
||||
DWORD socket_ttl;
|
||||
};
|
||||
|
||||
|
||||
int get_socket_index( uint16 src_port, uint16 dest_port, int proto );
|
||||
int get_socket_index( uint16 src_port, int proto );
|
||||
int get_socket_index( socket_t *cmpl );
|
||||
void delete_socket( socket_t *cmpl );
|
||||
socket_t *find_socket( uint16 src_port, uint16 dest_port, int proto );
|
||||
void add_socket( socket_t *cmpl );
|
||||
void close_old_sockets();
|
||||
void close_all_sockets();
|
||||
|
||||
|
||||
#endif // _IPSOCKET_H_
|
68
BasiliskII/src/Windows/router/mib/interfaces.cpp
Executable file
68
BasiliskII/src/Windows/router/mib/interfaces.cpp
Executable file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* interfaces.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "interfaces.h"
|
||||
#include "../dump.h"
|
||||
#include "mibaccess.h"
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
static UINT ip_array[100];
|
||||
static UINT ip_array_sz = 0;
|
||||
|
||||
void init_interfaces()
|
||||
{
|
||||
MibII _mibs(false);
|
||||
|
||||
ip_array_sz = sizeof(ip_array) / sizeof(ip_array[0]);
|
||||
|
||||
if(_mibs.Init()) {
|
||||
_mibs.GetIPAddress( ip_array, ip_array_sz );
|
||||
}
|
||||
|
||||
if(ip_array_sz == 0) {
|
||||
ip_array_sz = 1;
|
||||
ip_array[0] = 0; // localhost
|
||||
}
|
||||
|
||||
D(bug("init_interfaces() found %d interfaces.\r\n", ip_array_sz));
|
||||
}
|
||||
|
||||
void final_interfaces()
|
||||
{
|
||||
// Currently nothing to do.
|
||||
}
|
||||
|
||||
int get_ip_count()
|
||||
{
|
||||
return ip_array_sz;
|
||||
}
|
||||
|
||||
uint32 get_ip_by_index( int index )
|
||||
{
|
||||
return index >= 0 && index < (int)ip_array_sz ? ip_array[index] : 0;
|
||||
}
|
35
BasiliskII/src/Windows/router/mib/interfaces.h
Executable file
35
BasiliskII/src/Windows/router/mib/interfaces.h
Executable file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* intercafes.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _INTERFACES_H_
|
||||
#define _INTERFACES_H_
|
||||
|
||||
// A wrapper to the MibII class. Enumerates all ip interfaces
|
||||
// currently in this computer. The interface list is not static.
|
||||
|
||||
void init_interfaces();
|
||||
void final_interfaces();
|
||||
|
||||
int get_ip_count();
|
||||
uint32 get_ip_by_index( int index );
|
||||
|
||||
#endif // _INTERFACES_H_
|
308
BasiliskII/src/Windows/router/mib/mibaccess.cpp
Executable file
308
BasiliskII/src/Windows/router/mib/mibaccess.cpp
Executable file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
* MibAccess.cpp
|
||||
*
|
||||
* The original code by Stas Khirman modified by Lauri Pesonen, December, 2000:
|
||||
*
|
||||
* SnmpUtilVarBindFree(), SnmpUtilOidNCmp() and SnmpUtilOidCpy() now loaded from
|
||||
* "snmpapi.dll" dynamically instead of linking statically.
|
||||
*
|
||||
* MibII ctor now takes a parameter whether to load Winsock or not.
|
||||
* WSAStartup maintains an internal reference counter so it would have been ok
|
||||
* to let it load always.
|
||||
*
|
||||
* Fixed a bug where the return value of LoadLibrary() was compared against
|
||||
* HINSTANCE_ERROR instead of NULL.
|
||||
*
|
||||
* Removed some type conversion warnings by casting.
|
||||
*
|
||||
* Added a check in MibExtLoad ctor that the function entry points were found.
|
||||
*
|
||||
* Added a check in GetIPMask() and GetIPAddress() that the library was loaded
|
||||
* before accessing the functions.
|
||||
*
|
||||
* Changed the return type of GetIPAddress() and GetIPMask() from BOOL to void
|
||||
* as they always returned TRUE.
|
||||
*
|
||||
*/
|
||||
|
||||
/************************************************************************/
|
||||
/* Copyright (C) Stas Khirman 1998. All rights reserved. */
|
||||
/* Written by Stas Khirman (staskh@rocketmail.com). */
|
||||
/* and */
|
||||
/* Raz Galili (razgalili@hotmail.com) */
|
||||
/* */
|
||||
/* Free software: no warranty; use anywhere is ok; spread the */
|
||||
/* sources; note any modifications; share variations and */
|
||||
/* derivatives (including sending to staskh@rocketmail.com). */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
* MibAccess.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "mibaccess.h"
|
||||
#include "..\dynsockets.h"
|
||||
#include "..\dump.h"
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
MibExtLoad::MibExtLoad( LPSTR MibDllName, LPSTR SnmpDllName )
|
||||
{
|
||||
|
||||
m_Init = NULL;
|
||||
|
||||
m_InitEx = NULL;
|
||||
m_Query = NULL;
|
||||
m_Trap = NULL;
|
||||
|
||||
m_hInst_snmputil = NULL;
|
||||
|
||||
m_SnmpUtilVarBindFree = NULL;
|
||||
m_SnmpUtilOidNCmp = NULL;
|
||||
m_SnmpUtilOidCpy = NULL;
|
||||
|
||||
m_hInst = LoadLibrary( MibDllName );
|
||||
if(!m_hInst) {
|
||||
D(bug("MIB: library %s could not be loaded.\r\n", MibDllName));
|
||||
return;
|
||||
}
|
||||
D(bug("MIB: library %s loaded ok.\r\n", MibDllName));
|
||||
|
||||
m_Init = (pSnmpExtensionInit)GetProcAddress(m_hInst ,"SnmpExtensionInit");
|
||||
m_InitEx= (pSnmpExtensionInitEx)GetProcAddress(m_hInst ,"SnmpExtensionInitEx");
|
||||
m_Query = (pSnmpExtensionQuery)GetProcAddress(m_hInst ,"SnmpExtensionQuery");
|
||||
m_Trap = (pSnmpExtensionTrap)GetProcAddress(m_hInst ,"SnmpExtensionTrap");
|
||||
|
||||
if( !m_Init || !m_InitEx || !m_Query || !m_Trap )
|
||||
{
|
||||
D(bug("MIB: required entry points not found in library %s.\r\n", MibDllName));
|
||||
FreeLibrary( m_hInst );
|
||||
m_hInst = NULL;
|
||||
}
|
||||
|
||||
m_hInst_snmputil = LoadLibrary( SnmpDllName );
|
||||
if(!m_hInst_snmputil){
|
||||
D(bug("MIB: library %s could not be loaded.\r\n", SnmpDllName));
|
||||
FreeLibrary( m_hInst );
|
||||
m_hInst = NULL;
|
||||
return;
|
||||
}
|
||||
D(bug("MIB: library %s loaded ok.\r\n", SnmpDllName));
|
||||
|
||||
m_SnmpUtilVarBindFree = (VOID (SNMP_FUNC_TYPE *)(SnmpVarBind *))GetProcAddress( m_hInst_snmputil, "SnmpUtilVarBindFree" );
|
||||
m_SnmpUtilOidNCmp = (SNMPAPI (SNMP_FUNC_TYPE *)(AsnObjectIdentifier *, AsnObjectIdentifier *, UINT))GetProcAddress( m_hInst_snmputil, "SnmpUtilOidNCmp" );
|
||||
m_SnmpUtilOidCpy = (SNMPAPI (SNMP_FUNC_TYPE *)(AsnObjectIdentifier *, AsnObjectIdentifier *))GetProcAddress( m_hInst_snmputil, "SnmpUtilOidCpy" );
|
||||
|
||||
if( !m_SnmpUtilVarBindFree || !m_SnmpUtilOidNCmp || !m_SnmpUtilOidCpy )
|
||||
{
|
||||
D(bug("MIB: required entry points not found in library %s.\r\n", SnmpDllName));
|
||||
FreeLibrary( m_hInst );
|
||||
FreeLibrary( m_hInst_snmputil );
|
||||
m_hInst = NULL;
|
||||
m_hInst_snmputil = NULL;
|
||||
}
|
||||
|
||||
#undef SNMP_FreeVarBind
|
||||
#undef SNMP_oidncmp
|
||||
#undef SNMP_oidcpy
|
||||
|
||||
#define SNMP_FreeVarBind m_SnmpUtilVarBindFree
|
||||
#define SNMP_oidncmp m_SnmpUtilOidNCmp
|
||||
#define SNMP_oidcpy m_SnmpUtilOidCpy
|
||||
}
|
||||
|
||||
MibExtLoad::~MibExtLoad()
|
||||
{
|
||||
if( m_hInst ) {
|
||||
FreeLibrary( m_hInst );
|
||||
m_hInst = NULL;
|
||||
}
|
||||
if( m_hInst_snmputil ) {
|
||||
FreeLibrary( m_hInst_snmputil );
|
||||
m_hInst_snmputil = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL MibExtLoad::Init(DWORD dwTimeZeroReference,HANDLE *hPollForTrapEvent,AsnObjectIdentifier *supportedView)
|
||||
{
|
||||
if(m_hInst && m_Init)
|
||||
return m_Init(dwTimeZeroReference,hPollForTrapEvent,supportedView);
|
||||
return FALSE;
|
||||
}
|
||||
BOOL MibExtLoad::InitEx(AsnObjectIdentifier *supportedView)
|
||||
{
|
||||
if(m_hInst && m_InitEx)
|
||||
return m_InitEx(supportedView);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL MibExtLoad::Query(BYTE requestType,OUT RFC1157VarBindList *variableBindings,
|
||||
AsnInteger *errorStatus,AsnInteger *errorIndex)
|
||||
{
|
||||
if(m_hInst && m_Query)
|
||||
return m_Query(requestType,variableBindings,errorStatus,errorIndex);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL MibExtLoad::Trap(AsnObjectIdentifier *enterprise, AsnInteger *genericTrap,
|
||||
AsnInteger *specificTrap, AsnTimeticks *timeStamp,
|
||||
RFC1157VarBindList *variableBindings)
|
||||
{
|
||||
if(m_hInst && m_Trap)
|
||||
return m_Trap(enterprise, genericTrap,specificTrap, timeStamp, variableBindings);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MibII::MibII( bool load_winsock ):MibExtLoad("inetmib1.dll","snmpapi.dll")
|
||||
{
|
||||
WSADATA wsa;
|
||||
m_load_winsock = load_winsock;
|
||||
if(load_winsock) {
|
||||
int err = _WSAStartup( 0x0101, &wsa );
|
||||
}
|
||||
}
|
||||
|
||||
MibII::~MibII()
|
||||
{
|
||||
if(m_load_winsock) _WSACleanup();
|
||||
}
|
||||
|
||||
BOOL MibII::Init()
|
||||
{
|
||||
HANDLE PollForTrapEvent;
|
||||
AsnObjectIdentifier SupportedView;
|
||||
|
||||
return MibExtLoad::Init(GetTickCount(),&PollForTrapEvent,&SupportedView);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MibII::GetIPAddress( UINT IpArray[], UINT &IpArraySize )
|
||||
{
|
||||
if(!m_hInst) {
|
||||
IpArraySize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
UINT OID_ipAdEntAddr[] = { 1, 3, 6, 1, 2, 1, 4 , 20, 1 ,1 };
|
||||
AsnObjectIdentifier MIB_ipAdEntAddr = { sizeof(OID_ipAdEntAddr)/sizeof(UINT), OID_ipAdEntAddr };
|
||||
RFC1157VarBindList varBindList;
|
||||
RFC1157VarBind varBind[1];
|
||||
AsnInteger errorStatus;
|
||||
AsnInteger errorIndex;
|
||||
AsnObjectIdentifier MIB_NULL = {0,0};
|
||||
BOOL Exit;
|
||||
int ret;
|
||||
int IpCount=0;
|
||||
DWORD dtmp;
|
||||
|
||||
varBindList.list = varBind;
|
||||
varBindList.len = 1;
|
||||
varBind[0].name = MIB_NULL;
|
||||
SNMP_oidcpy(&varBind[0].name,&MIB_ipAdEntAddr);
|
||||
Exit = FALSE;
|
||||
|
||||
IpCount=0;
|
||||
while(!Exit){
|
||||
ret = Query(ASN_RFC1157_GETNEXTREQUEST,&varBindList,&errorStatus,&errorIndex);
|
||||
|
||||
if(!ret)
|
||||
Exit=TRUE;
|
||||
else{
|
||||
ret = SNMP_oidncmp(&varBind[0].name,&MIB_ipAdEntAddr,MIB_ipAdEntAddr.idLength);
|
||||
if(ret!=0){
|
||||
Exit=TRUE;
|
||||
}
|
||||
else{
|
||||
dtmp = *((DWORD *)varBind[0].value.asnValue.address.stream);
|
||||
IpArray[IpCount] = dtmp;
|
||||
IpCount++;
|
||||
if(IpCount>=(int)IpArraySize)
|
||||
Exit = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IpArraySize = IpCount;
|
||||
|
||||
SNMP_FreeVarBind(&varBind[0]);
|
||||
}
|
||||
|
||||
void MibII::GetIPMask( UINT IpArray[], UINT &IpArraySize )
|
||||
{
|
||||
if(!m_hInst) {
|
||||
IpArraySize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
UINT OID_ipAdEntMask[] = { 1, 3, 6, 1, 2, 1, 4 , 20, 1 ,3 };
|
||||
AsnObjectIdentifier MIB_ipAdEntMask = { sizeof(OID_ipAdEntMask)/sizeof(UINT), OID_ipAdEntMask };
|
||||
RFC1157VarBindList varBindList;
|
||||
RFC1157VarBind varBind[1];
|
||||
AsnInteger errorStatus;
|
||||
AsnInteger errorIndex;
|
||||
AsnObjectIdentifier MIB_NULL = {0,0};
|
||||
BOOL Exit;
|
||||
int ret;
|
||||
int IpCount=0;
|
||||
DWORD dtmp;
|
||||
|
||||
varBindList.list = varBind;
|
||||
varBindList.len = 1;
|
||||
varBind[0].name = MIB_NULL;
|
||||
SNMP_oidcpy(&varBind[0].name,&MIB_ipAdEntMask);
|
||||
Exit = FALSE;
|
||||
|
||||
IpCount=0;
|
||||
while(!Exit){
|
||||
ret = Query(ASN_RFC1157_GETNEXTREQUEST,&varBindList,&errorStatus,&errorIndex);
|
||||
|
||||
if(!ret)
|
||||
Exit=TRUE;
|
||||
else{
|
||||
ret = SNMP_oidncmp(&varBind[0].name,&MIB_ipAdEntMask,MIB_ipAdEntMask.idLength);
|
||||
if(ret!=0){
|
||||
Exit=TRUE;
|
||||
}
|
||||
else{
|
||||
dtmp = *((DWORD *)varBind[0].value.asnValue.address.stream);
|
||||
IpArray[IpCount] = dtmp;
|
||||
IpCount++;
|
||||
if(IpCount>=(int)IpArraySize)
|
||||
Exit = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IpArraySize = IpCount;
|
||||
|
||||
SNMP_FreeVarBind(&varBind[0]);
|
||||
}
|
83
BasiliskII/src/Windows/router/mib/mibaccess.h
Executable file
83
BasiliskII/src/Windows/router/mib/mibaccess.h
Executable file
@ -0,0 +1,83 @@
|
||||
//////////////////////////////////////////////////////
|
||||
// FILE : MibAccess.h
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef _SNMP_ACCESS_H_
|
||||
#define _SNMP_ACCESS_H_
|
||||
|
||||
#include <snmp.h>
|
||||
#ifndef SNMP_FUNC_TYPE
|
||||
#define SNMP_FUNC_TYPE WINAPI
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// Definition of pointers to the four functions in the Mib Dll
|
||||
//
|
||||
typedef BOOL (WINAPI *pSnmpExtensionInit)(
|
||||
IN DWORD dwTimeZeroReference,
|
||||
OUT HANDLE *hPollForTrapEvent,
|
||||
OUT AsnObjectIdentifier *supportedView);
|
||||
|
||||
typedef BOOL (WINAPI *pSnmpExtensionTrap)(
|
||||
OUT AsnObjectIdentifier *enterprise,
|
||||
OUT AsnInteger *genericTrap,
|
||||
OUT AsnInteger *specificTrap,
|
||||
OUT AsnTimeticks *timeStamp,
|
||||
OUT RFC1157VarBindList *variableBindings);
|
||||
|
||||
typedef BOOL (WINAPI *pSnmpExtensionQuery)(
|
||||
IN BYTE requestType,
|
||||
IN OUT RFC1157VarBindList *variableBindings,
|
||||
OUT AsnInteger *errorStatus,
|
||||
OUT AsnInteger *errorIndex);
|
||||
|
||||
typedef BOOL (WINAPI *pSnmpExtensionInitEx)(OUT AsnObjectIdentifier *supportedView);
|
||||
|
||||
|
||||
class MibExtLoad
|
||||
{
|
||||
public:
|
||||
MibExtLoad( LPSTR MibDllName, LPSTR SnmpDllName );
|
||||
~MibExtLoad();
|
||||
BOOL Init(DWORD dwTimeZeroReference,HANDLE *hPollForTrapEvent,AsnObjectIdentifier *supportedView);
|
||||
BOOL InitEx(AsnObjectIdentifier *supportedView);
|
||||
BOOL Query(BYTE requestType,OUT RFC1157VarBindList *variableBindings,
|
||||
AsnInteger *errorStatus,AsnInteger *errorIndex);
|
||||
|
||||
BOOL Trap(AsnObjectIdentifier *enterprise, AsnInteger *genericTrap,
|
||||
AsnInteger *specificTrap, AsnTimeticks *timeStamp,
|
||||
RFC1157VarBindList *variableBindings);
|
||||
|
||||
public:
|
||||
HINSTANCE m_hInst;
|
||||
HINSTANCE m_hInst_snmputil;
|
||||
|
||||
private:
|
||||
pSnmpExtensionInit m_Init;
|
||||
pSnmpExtensionInitEx m_InitEx;
|
||||
pSnmpExtensionQuery m_Query;
|
||||
pSnmpExtensionTrap m_Trap;
|
||||
|
||||
public:
|
||||
VOID (SNMP_FUNC_TYPE *m_SnmpUtilVarBindFree) (SnmpVarBind *);
|
||||
SNMPAPI (SNMP_FUNC_TYPE *m_SnmpUtilOidNCmp) (AsnObjectIdentifier *, AsnObjectIdentifier *, UINT);
|
||||
SNMPAPI (SNMP_FUNC_TYPE *m_SnmpUtilOidCpy) (AsnObjectIdentifier *, AsnObjectIdentifier *);
|
||||
};
|
||||
|
||||
|
||||
class MibII: public MibExtLoad
|
||||
{
|
||||
public:
|
||||
MibII( bool load_winsock );
|
||||
~MibII();
|
||||
BOOL Init();
|
||||
|
||||
void GetIPAddress(UINT IpArray[],UINT &IpArraySize);
|
||||
void GetIPMask(UINT IpArray[],UINT &IpArraySize);
|
||||
|
||||
protected:
|
||||
bool m_load_winsock;
|
||||
};
|
||||
|
||||
#endif
|
204
BasiliskII/src/Windows/router/router.cpp
Executable file
204
BasiliskII/src/Windows/router/router.cpp
Executable file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* router.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This could be implemented by writing three (9x,nt,2k)
|
||||
* NDIS filter drivers. No thanks.
|
||||
* But this is not easy either.
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
#include "cpu_emulation.h"
|
||||
#include "prefs.h"
|
||||
#include "ether_windows.h"
|
||||
#include "ether.h"
|
||||
#include "router.h"
|
||||
#include "router_types.h"
|
||||
#include "dynsockets.h"
|
||||
#include "ipsocket.h"
|
||||
#include "iphelp.h"
|
||||
#include "arp.h"
|
||||
#include "icmp.h"
|
||||
#include "udp.h"
|
||||
#include "tcp.h"
|
||||
#include "ftp.h"
|
||||
#include "mib/interfaces.h"
|
||||
#include "dump.h"
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
uint16 next_ip_ident_number = 1;
|
||||
uint32 macos_ip_address = 0;
|
||||
const uint8 router_mac_addr[6] = { '4', '2', '6', '7', '7', '9' };
|
||||
uint32 router_ip_address = 0;
|
||||
bool raw_sockets_available = false;
|
||||
bool m_router_enabled = true;
|
||||
|
||||
|
||||
|
||||
// Protected data.
|
||||
CRITICAL_SECTION router_section;
|
||||
bool is_router_shutting_down = false;
|
||||
static HANDLE r_handle = 0;
|
||||
static unsigned int rh_tid = 0;
|
||||
|
||||
|
||||
static void write_ip4( ip_t *ip, int len )
|
||||
{
|
||||
if(len < sizeof(ip_t)) {
|
||||
D(bug("Too small ip packet(%d), dropped\r\n", len));
|
||||
} else {
|
||||
uint8 proto = ip->proto;
|
||||
|
||||
// This is a router, decrement the hop count
|
||||
if( --ip->ttl == 0 ) {
|
||||
// Most likely this is some Mac traceroute app
|
||||
D(bug("ip packet ttl expired, proto=%d.\r\n", proto));
|
||||
error_winsock_2_icmp( WSAETTLEXCEEDED, ip, len );
|
||||
} else {
|
||||
switch( proto ) {
|
||||
case ip_proto_icmp:
|
||||
write_icmp( (icmp_t *)ip, len );
|
||||
break;
|
||||
case ip_proto_tcp:
|
||||
write_tcp( (tcp_t *)ip, len );
|
||||
break;
|
||||
case ip_proto_udp:
|
||||
write_udp( (udp_t *)ip, len );
|
||||
break;
|
||||
default:
|
||||
D(bug("write_ip4() len=%d, proto=%d\r\n", len, proto));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool router_write_packet(uint8 *packet, int len)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if( len >= 14 ) {
|
||||
switch( ntohs( ((mac_t *)packet)->type ) ) {
|
||||
case mac_type_ip4:
|
||||
write_ip4( (ip_t *)packet, len );
|
||||
result = true;
|
||||
break;
|
||||
case mac_type_ip6:
|
||||
D(bug("write_ip6() len=%d; unsupported.\r\n", len));
|
||||
result = true;
|
||||
break;
|
||||
case mac_type_arp:
|
||||
result = write_arp( (arp_t *)packet, len );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool router_read_packet(uint8 *packet, int len)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if( len >= 14 ) {
|
||||
switch( ntohs( ((mac_t *)packet)->type ) ) {
|
||||
case mac_type_ip4:
|
||||
case mac_type_ip6:
|
||||
case mac_type_arp:
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
This has nothing to do with TCP TIME_WAITs or CLOSE_WAITs,
|
||||
the thread is needed to close down expired udp sockets.
|
||||
Arguably an ugly hack, but needed since there is no way to
|
||||
listen to all ports w/o writing another ndis filter driver
|
||||
*/
|
||||
static WINAPI unsigned int router_expire_thread(void *arg)
|
||||
{
|
||||
while(!is_router_shutting_down) {
|
||||
close_old_sockets();
|
||||
Sleep(1000);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void router_init(void)
|
||||
{
|
||||
InitializeCriticalSection( &router_section );
|
||||
|
||||
m_router_enabled = PrefsFindBool("routerenabled");
|
||||
|
||||
if(m_router_enabled && dynsockets_init()) {
|
||||
char me[128];
|
||||
if( _gethostname(me, sizeof(me)) == SOCKET_ERROR ) {
|
||||
D(bug("gethostname() failed, error = %d\r\n", _WSAGetLastError()));
|
||||
} else {
|
||||
struct hostent *hent = _gethostbyname(me);
|
||||
if( hent == NULL ) {
|
||||
D(bug("gethostbyname() failed, error = %d\r\n", _WSAGetLastError()));
|
||||
} else {
|
||||
struct in_addr *ina = (struct in_addr *) *hent->h_addr_list;
|
||||
router_ip_address = ntohl(ina->s_addr);
|
||||
D(bug("router protocol address seems to be %s (used only in icmp error messages)\r\n", _inet_ntoa(*ina)));
|
||||
}
|
||||
}
|
||||
is_router_shutting_down = false;
|
||||
r_handle = (HANDLE)_beginthreadex( 0, 0, router_expire_thread, 0, 0, &rh_tid );
|
||||
init_interfaces();
|
||||
init_tcp();
|
||||
init_udp();
|
||||
init_ftp();
|
||||
} else {
|
||||
m_router_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
void router_final(void)
|
||||
{
|
||||
final_interfaces();
|
||||
stop_icmp_listen();
|
||||
close_all_sockets();
|
||||
if(r_handle) {
|
||||
is_router_shutting_down = true;
|
||||
WaitForSingleObject( r_handle, INFINITE );
|
||||
final_tcp();
|
||||
final_udp();
|
||||
dynsockets_final();
|
||||
}
|
||||
DeleteCriticalSection( &router_section );
|
||||
}
|
55
BasiliskII/src/Windows/router/router.h
Executable file
55
BasiliskII/src/Windows/router/router.h
Executable file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* router.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ROUTER_H_
|
||||
#define _ROUTER_H_
|
||||
|
||||
extern bool is_router_shutting_down;
|
||||
extern CRITICAL_SECTION router_section;
|
||||
|
||||
// Increased by one for each ip packet sent to the emulated enet interface.
|
||||
extern uint16 next_ip_ident_number;
|
||||
|
||||
// Used by incoming icmp packets and internal icmp messages. Host byte order.
|
||||
extern uint32 macos_ip_address;
|
||||
|
||||
// The magic constant
|
||||
extern const uint8 router_mac_addr[6];
|
||||
|
||||
// Used by internal icmp messages. Host byte order.
|
||||
extern uint32 router_ip_address;
|
||||
|
||||
// False under NT/Win2k if the user has no admin rights
|
||||
extern bool raw_sockets_available;
|
||||
|
||||
|
||||
|
||||
// Interface exposed to ether_windows module.
|
||||
extern bool m_router_enabled;
|
||||
void router_init(void);
|
||||
void router_final(void);
|
||||
|
||||
// Both of these return true if the ethernet module should drop the packet.
|
||||
bool router_write_packet(uint8 *packet, int len);
|
||||
bool router_read_packet(uint8 *packet, int len);
|
||||
|
||||
#endif // _ROUTER_H_
|
187
BasiliskII/src/Windows/router/router_types.h
Executable file
187
BasiliskII/src/Windows/router/router_types.h
Executable file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* router_types.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _ROUTER_TYPES_H_
|
||||
#define _ROUTER_TYPES_H_
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
|
||||
// --------------------------- MAC ---------------------------
|
||||
typedef struct {
|
||||
uint8 dest[6];
|
||||
uint8 src[6];
|
||||
uint16 type;
|
||||
} ATTRIBUTE_PACKED mac_t;
|
||||
|
||||
enum {
|
||||
mac_type_llc_ipx_limit = 0x05DC, // <= mac_type_llc_ipx_limit -->> 802.3 MAC frame
|
||||
mac_type_ip4 = 0x0800,
|
||||
mac_type_arp = 0x0806,
|
||||
mac_type_rarp = 0x8035,
|
||||
mac_type_ip6 = 0x86DD,
|
||||
mac_type_loopback = 0x9000
|
||||
};
|
||||
|
||||
// --------------------------- ARP ---------------------------
|
||||
typedef struct {
|
||||
mac_t mac;
|
||||
uint16 htype;
|
||||
uint16 ptype;
|
||||
uint8 halen;
|
||||
uint8 palen;
|
||||
uint16 opcode;
|
||||
uint8 srch[6]; // size for ethernet
|
||||
uint8 srcp[4]; // size for ip
|
||||
uint8 dsth[6]; // size for ethernet
|
||||
uint8 dstp[4]; // size for ip
|
||||
} ATTRIBUTE_PACKED arp_t;
|
||||
|
||||
enum {
|
||||
arp_request = 1,
|
||||
arp_reply = 2
|
||||
};
|
||||
enum {
|
||||
arp_hwtype_enet = 1
|
||||
};
|
||||
|
||||
// --------------------------- IP4 ---------------------------
|
||||
typedef struct {
|
||||
mac_t mac;
|
||||
uint8 header_len:4;
|
||||
uint8 version:4;
|
||||
uint8 tos;
|
||||
uint16 total_len;
|
||||
uint16 ident;
|
||||
uint16 flags_n_frag_offset; // foffset 0..11, flags 12..15
|
||||
uint8 ttl;
|
||||
uint8 proto;
|
||||
uint16 checksum;
|
||||
uint32 src;
|
||||
uint32 dest;
|
||||
// ip options, size = 4 * header_len - 20
|
||||
} ATTRIBUTE_PACKED ip_t;
|
||||
|
||||
// Protocol STD numbers
|
||||
enum {
|
||||
ip_proto_icmp = IPPROTO_ICMP,
|
||||
ip_proto_tcp = IPPROTO_TCP,
|
||||
ip_proto_udp = IPPROTO_UDP
|
||||
};
|
||||
|
||||
// --------------------------- ICMP ---------------------------
|
||||
typedef struct {
|
||||
ip_t ip;
|
||||
uint8 type;
|
||||
uint8 code;
|
||||
uint16 checksum;
|
||||
// data
|
||||
} ATTRIBUTE_PACKED icmp_t;
|
||||
|
||||
enum {
|
||||
icmp_Echo_reply = 0,
|
||||
icmp_Destination_unreachable = 3,
|
||||
icmp_Source_quench = 4,
|
||||
icmp_Redirect = 5,
|
||||
icmp_Echo = 8,
|
||||
icmp_Router_advertisement = 9,
|
||||
icmp_Router_solicitation = 10,
|
||||
icmp_Time_exceeded = 11,
|
||||
icmp_Parameter_problem = 12,
|
||||
icmp_Time_Stamp_request = 13,
|
||||
icmp_Time_Stamp_reply = 14,
|
||||
icmp_Information_request_obsolete = 15,
|
||||
icmp_Information_reply_obsolete = 16,
|
||||
icmp_Address_mask_request = 17,
|
||||
icmp_Address_mask_reply = 18,
|
||||
icmp_Traceroute = 30,
|
||||
icmp_Datagram_conversion_error = 31,
|
||||
icmp_Mobile_host_redirect = 32,
|
||||
icmp_IPv6_Where_Are_You = 33,
|
||||
icmp_IPv6_I_Am_Here = 34,
|
||||
icmp_Mobile_registration_request = 35,
|
||||
icmp_Mobile_registration_reply = 36,
|
||||
icmp_Domain_name_request = 37,
|
||||
icmp_Domain_name_reply = 38,
|
||||
icmp_SKIP = 39,
|
||||
icmp_Photuris = 40
|
||||
};
|
||||
|
||||
// --------------------------- TCP ---------------------------
|
||||
typedef struct {
|
||||
ip_t ip;
|
||||
uint16 src_port;
|
||||
uint16 dest_port;
|
||||
uint32 seq;
|
||||
uint32 ack;
|
||||
uint8 header_len; // note: some reserved bits
|
||||
uint8 flags; // note: some reserved bits
|
||||
uint16 window;
|
||||
uint16 checksum;
|
||||
uint16 urgent_ptr;
|
||||
// options + padding: size = dataoffset*4-20
|
||||
// data
|
||||
} ATTRIBUTE_PACKED tcp_t;
|
||||
|
||||
enum {
|
||||
tcp_flags_URG = 0x20, // The urgent pointer field is significant in this segment.
|
||||
tcp_flags_ACK = 0x10, // The acknowledgment field is significant in this segment.
|
||||
tcp_flags_PSH = 0x08, // Push function.
|
||||
tcp_flags_RST = 0x04, // Resets the connection.
|
||||
tcp_flags_SYN = 0x02, // Synchronizes the sequence numbers.
|
||||
tcp_flags_FIN = 0x01 // No more data from sender.
|
||||
};
|
||||
|
||||
enum {
|
||||
tcp_state_closed,
|
||||
tcp_state_listen,
|
||||
tcp_state_syn_sent,
|
||||
tcp_state_syn_rcvd,
|
||||
tcp_state_established,
|
||||
tcp_state_close_wait,
|
||||
tcp_state_last_ack,
|
||||
tcp_state_finwait_1,
|
||||
tcp_state_finwait_2,
|
||||
tcp_state_closing,
|
||||
tcp_state_time_wait
|
||||
};
|
||||
|
||||
// --------------------------- UDP ---------------------------
|
||||
typedef struct {
|
||||
ip_t ip;
|
||||
uint16 src_port;
|
||||
uint16 dest_port;
|
||||
uint16 msg_len;
|
||||
uint16 checksum;
|
||||
// data
|
||||
} ATTRIBUTE_PACKED udp_t;
|
||||
|
||||
typedef struct {
|
||||
uint16 src_lo, src_hi;
|
||||
uint16 dest_lo, dest_hi;
|
||||
uint16 proto;
|
||||
uint16 msg_len;
|
||||
} ATTRIBUTE_PACKED pseudo_ip_t;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
#endif // _ROUTER_TYPES_H_
|
1606
BasiliskII/src/Windows/router/tcp.cpp
Executable file
1606
BasiliskII/src/Windows/router/tcp.cpp
Executable file
File diff suppressed because it is too large
Load Diff
31
BasiliskII/src/Windows/router/tcp.h
Executable file
31
BasiliskII/src/Windows/router/tcp.h
Executable file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* tcp.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _TCP_H_
|
||||
#define _TCP_H_
|
||||
|
||||
void write_tcp( tcp_t *tcp, int len );
|
||||
|
||||
void init_tcp();
|
||||
void final_tcp();
|
||||
|
||||
#endif // _TCP_H_
|
205
BasiliskII/src/Windows/router/udp.cpp
Executable file
205
BasiliskII/src/Windows/router/udp.cpp
Executable file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
* udp.cpp - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "cpu_emulation.h"
|
||||
#include "prefs.h"
|
||||
#include "ether_windows.h"
|
||||
#include "ether.h"
|
||||
#include "router.h"
|
||||
#include "router_types.h"
|
||||
#include "dynsockets.h"
|
||||
#include "ipsocket.h"
|
||||
#include "iphelp.h"
|
||||
#include "udp.h"
|
||||
#include "dump.h"
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#pragma optimize("",off)
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
void CALLBACK udp_read_completion(
|
||||
DWORD error,
|
||||
DWORD bytes_read,
|
||||
LPWSAOVERLAPPED lpOverlapped,
|
||||
DWORD flags
|
||||
)
|
||||
{
|
||||
D(bug("udp_read_completion(error=0x%x, bytes_read=%d, flags=0x%x)\r\n", error, bytes_read, flags));
|
||||
|
||||
socket_t *cmpl = (socket_t *)lpOverlapped->hEvent;
|
||||
|
||||
// It's not easy to know whether empty upd datagrams should be passed along. doh.
|
||||
if(error == 0 && bytes_read > 0) {
|
||||
|
||||
if(bytes_read > 1460) {
|
||||
D(bug("discarding oversized udp packet, size = \r\n", bytes_read));
|
||||
} else {
|
||||
struct sockaddr_in name;
|
||||
int namelen = sizeof(name);
|
||||
memset( &name, 0, sizeof(name) );
|
||||
if( _getsockname( cmpl->s, (struct sockaddr *)&name, &namelen ) == SOCKET_ERROR ) {
|
||||
D(bug("_getsockname() failed, error=%d\r\n", _WSAGetLastError() ));
|
||||
} else {
|
||||
D(bug("_getsockname(): port=%d\r\n", ntohs(name.sin_port) ));
|
||||
}
|
||||
|
||||
int udp_size = sizeof(udp_t) + bytes_read;
|
||||
udp_t *udp = (udp_t *)malloc( udp_size );
|
||||
if(udp) {
|
||||
mac_t *mac = (mac_t *)udp;
|
||||
ip_t *ip = (ip_t *)udp;
|
||||
|
||||
// Build MAC
|
||||
// memcpy( udp->ip.mac.dest, cmpl->mac_src, 6 );
|
||||
memcpy( mac->dest, ether_addr, 6 );
|
||||
memcpy( mac->src, router_mac_addr, 6 );
|
||||
mac->type = htons(mac_type_ip4);
|
||||
|
||||
// Build IP
|
||||
ip->version = 4;
|
||||
ip->header_len = 5;
|
||||
ip->tos = 0;
|
||||
ip->total_len = htons(sizeof(udp_t) - sizeof(mac_t) + bytes_read); // no options
|
||||
ip->ident = htons(next_ip_ident_number++); // htons() might be a macro... but does not really matter here.
|
||||
ip->flags_n_frag_offset = 0;
|
||||
ip->ttl = 128; // one hop actually!
|
||||
ip->proto = ip_proto_udp;
|
||||
ip->src = htonl(cmpl->ip_dest);
|
||||
ip->dest = htonl(cmpl->ip_src);
|
||||
make_ip4_checksum( (ip_t *)udp );
|
||||
|
||||
// Copy payload (used by UDP checksum)
|
||||
memcpy( (char *)udp + sizeof(udp_t), cmpl->buffers[0].buf, bytes_read );
|
||||
|
||||
// Build UDP
|
||||
udp->src_port = htons(cmpl->dest_port);
|
||||
udp->dest_port = htons(cmpl->src_port);
|
||||
udp->msg_len = htons(sizeof(udp_t) - sizeof(ip_t) + bytes_read); // no options
|
||||
make_udp_checksum( udp );
|
||||
|
||||
dump_bytes( (uint8 *)udp, udp_size );
|
||||
|
||||
enqueue_packet( (uint8 *)udp, udp_size );
|
||||
free(udp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!is_router_shutting_down && cmpl->s != INVALID_SOCKET && cmpl->b_recfrom()) {
|
||||
cmpl->socket_ttl = GetTickCount() + 60000L;
|
||||
} else {
|
||||
delete_socket( cmpl );
|
||||
}
|
||||
}
|
||||
|
||||
void write_udp( udp_t *udp, int len )
|
||||
{
|
||||
if( len < sizeof(udp_t) ) {
|
||||
D(bug("Too small udp packet(%d), dropped\r\n", len));
|
||||
return;
|
||||
}
|
||||
|
||||
uint16 src_port = ntohs(udp->src_port);
|
||||
uint16 dest_port = ntohs(udp->dest_port);
|
||||
|
||||
BOOL ok = true;
|
||||
|
||||
socket_t *cmpl = find_socket( src_port, dest_port, IPPROTO_UDP );
|
||||
|
||||
BOOL old_socket_found = cmpl != 0;
|
||||
|
||||
if(!cmpl) {
|
||||
cmpl = new socket_t(IPPROTO_UDP);
|
||||
if(cmpl) {
|
||||
cmpl->s = _socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
|
||||
if(cmpl->s == INVALID_SOCKET) {
|
||||
delete cmpl;
|
||||
cmpl = 0;
|
||||
ok = false;
|
||||
} else {
|
||||
cmpl->src_port = src_port;
|
||||
cmpl->dest_port = dest_port;
|
||||
add_socket( cmpl );
|
||||
}
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(ok) {
|
||||
cmpl->src_port = src_port;
|
||||
cmpl->dest_port = dest_port;
|
||||
cmpl->ip_src = ntohl(udp->ip.src);
|
||||
cmpl->ip_dest = ntohl(udp->ip.dest);
|
||||
|
||||
struct sockaddr_in to;
|
||||
memset( &to, 0, sizeof(to) );
|
||||
to.sin_family = AF_INET;
|
||||
to.sin_port = udp->dest_port;
|
||||
to.sin_addr.s_addr = udp->ip.dest;
|
||||
|
||||
char *data = (char *)udp + sizeof(udp_t);
|
||||
int dlen = len - sizeof(udp_t);
|
||||
|
||||
// ttl changed, update checksum
|
||||
make_udp_checksum( udp );
|
||||
|
||||
cmpl->set_ttl( udp->ip.ttl );
|
||||
|
||||
bool please_close = true;
|
||||
/*
|
||||
Note that broadcast messages fill fail, no setsockopt(SO_BROADCAST).
|
||||
That's exactly what I want.
|
||||
*/
|
||||
if(SOCKET_ERROR != _sendto( cmpl->s, data, dlen, 0, (struct sockaddr *)&to, sizeof(to) )) {
|
||||
if(old_socket_found) {
|
||||
// This socket is not overlapped.
|
||||
please_close = false;
|
||||
} else {
|
||||
if(cmpl->b_recfrom()) please_close = false;
|
||||
}
|
||||
cmpl->socket_ttl = GetTickCount() + 60000L;
|
||||
} else {
|
||||
int socket_error = _WSAGetLastError();
|
||||
D(bug("_sendto() completed with error %d\r\n", socket_error));
|
||||
// TODO: check this out: error_winsock_2_icmp() uses router_ip_address
|
||||
// as source ip; but it's probably allright
|
||||
error_winsock_2_icmp( socket_error, (ip_t *)udp, len );
|
||||
}
|
||||
if(please_close) {
|
||||
delete_socket(cmpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void init_udp()
|
||||
{
|
||||
}
|
||||
|
||||
void final_udp()
|
||||
{
|
||||
}
|
38
BasiliskII/src/Windows/router/udp.h
Executable file
38
BasiliskII/src/Windows/router/udp.h
Executable file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* udp.h - ip router
|
||||
*
|
||||
* Basilisk II (C) 1997-2001 Christian Bauer
|
||||
*
|
||||
* Windows platform specific code copyright (C) Lauri Pesonen
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _UDP_H_
|
||||
#define _UDP_H_
|
||||
|
||||
void write_udp( udp_t *udp, int len );
|
||||
|
||||
void CALLBACK udp_read_completion(
|
||||
DWORD error,
|
||||
DWORD bytes_read,
|
||||
LPWSAOVERLAPPED lpOverlapped,
|
||||
DWORD flags
|
||||
);
|
||||
|
||||
void init_udp();
|
||||
void final_udp();
|
||||
|
||||
#endif // _UDP_H_
|
Loading…
Reference in New Issue
Block a user