import NAT-Router code from original Basilisk II for Windows

This commit is contained in:
gbeauche 2004-12-05 16:48:36 +00:00
parent eec1f6928a
commit 2de1c1760f
25 changed files with 4367 additions and 0 deletions

View 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;
}

View 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_

View 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
}

View 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_

View 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;
}

View 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_

View 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 ));
}
}

View 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_

View 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" ));
}
}

View 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_

View 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);
}
}
}

View 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_

View 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 );
}

View 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_

View 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;
}

View 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_

View 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]);
}

View 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

View 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 );
}

View 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_

View 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_

File diff suppressed because it is too large Load Diff

View 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_

View 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()
{
}

View 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_