9c3a99856e
- Partly re-implemented host_to_guest methods from legacy eth_vnet.cc. - Added two dynamic packet buffers for vnet server replies. - TFTP and FTP servers are only available if root directory is configured. - Added TCP port handler methods similar to the UDP ones. - Added basic TCP connection management and 3-way handshake. - Added FTP server stub for testing TCP (only login/logout for now).
339 lines
9.3 KiB
C++
339 lines
9.3 KiB
C++
/////////////////////////////////////////////////////////////////////////
|
|
// $Id$
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (C) 2004-2020 The Bochs Project
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// This library 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
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
//
|
|
|
|
// netutil.h - shared code for eth_vnet.cc and bxhub.cc
|
|
|
|
#ifndef BX_NETUTIL_H
|
|
#define BX_NETUTIL_H
|
|
|
|
#define ETHERNET_MAC_ADDR_LEN 6
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma pack(push, 1)
|
|
#elif defined(__MWERKS__) && defined(macintosh)
|
|
#pragma options align=packed
|
|
#endif
|
|
|
|
typedef struct ethernet_header {
|
|
#if defined(_MSC_VER) && (_MSC_VER>=1300)
|
|
__declspec(align(1))
|
|
#endif
|
|
Bit8u dst_mac_addr[ETHERNET_MAC_ADDR_LEN];
|
|
Bit8u src_mac_addr[ETHERNET_MAC_ADDR_LEN];
|
|
Bit16u type;
|
|
}
|
|
#if !defined(_MSC_VER)
|
|
GCC_ATTRIBUTE((packed))
|
|
#endif
|
|
ethernet_header_t;
|
|
|
|
typedef struct arp_header {
|
|
#if defined(_MSC_VER) && (_MSC_VER>=1300)
|
|
__declspec(align(1))
|
|
#endif
|
|
Bit16u hw_addr_space;
|
|
Bit16u proto_addr_space;
|
|
Bit8u hw_addr_len;
|
|
Bit8u proto_addr_len;
|
|
Bit16u opcode;
|
|
/* HW address of sender */
|
|
/* Protocol address of sender */
|
|
/* HW address of target*/
|
|
/* Protocol address of target */
|
|
}
|
|
#if !defined(_MSC_VER)
|
|
GCC_ATTRIBUTE((packed))
|
|
#endif
|
|
arp_header_t;
|
|
|
|
typedef struct ip_header {
|
|
#if defined(_MSC_VER) && (_MSC_VER>=1300)
|
|
__declspec(align(1))
|
|
#endif
|
|
#ifdef BX_LITTLE_ENDIAN
|
|
Bit8u header_len : 4;
|
|
Bit8u version : 4;
|
|
#else
|
|
Bit8u version : 4;
|
|
Bit8u header_len : 4;
|
|
#endif
|
|
Bit8u tos;
|
|
Bit16u total_len;
|
|
Bit16u id;
|
|
Bit16u frag_offs;
|
|
Bit8u ttl;
|
|
Bit8u protocol;
|
|
Bit16u checksum;
|
|
Bit32u src_addr;
|
|
Bit32u dst_addr;
|
|
}
|
|
#if !defined(_MSC_VER)
|
|
GCC_ATTRIBUTE((packed))
|
|
#endif
|
|
ip_header_t;
|
|
|
|
typedef struct udp_header {
|
|
#if defined(_MSC_VER) && (_MSC_VER>=1300)
|
|
__declspec(align(1))
|
|
#endif
|
|
Bit16u src_port;
|
|
Bit16u dst_port;
|
|
Bit16u length;
|
|
Bit16u checksum;
|
|
}
|
|
#if !defined(_MSC_VER)
|
|
GCC_ATTRIBUTE((packed))
|
|
#endif
|
|
udp_header_t;
|
|
|
|
typedef struct tcp_header {
|
|
#if defined(_MSC_VER) && (_MSC_VER>=1300)
|
|
__declspec(align(1))
|
|
#endif
|
|
Bit16u src_port;
|
|
Bit16u dst_port;
|
|
Bit32u seq_num;
|
|
Bit32u ack_num;
|
|
#ifdef BX_LITTLE_ENDIAN
|
|
Bit8u reserved : 4;
|
|
Bit8u data_offset : 4;
|
|
#else
|
|
Bit8u data_offset : 4;
|
|
Bit8u reserved : 4;
|
|
#endif
|
|
struct {
|
|
#ifdef BX_LITTLE_ENDIAN
|
|
Bit8u fin : 1;
|
|
Bit8u syn : 1;
|
|
Bit8u rst : 1;
|
|
Bit8u psh : 1;
|
|
Bit8u ack : 1;
|
|
Bit8u urg : 1;
|
|
Bit8u ece : 1;
|
|
Bit8u cwr : 1;
|
|
#else
|
|
Bit8u cwr : 1;
|
|
Bit8u ece : 1;
|
|
Bit8u urg : 1;
|
|
Bit8u ack : 1;
|
|
Bit8u psh : 1;
|
|
Bit8u rst : 1;
|
|
Bit8u syn : 1;
|
|
Bit8u fin : 1;
|
|
#endif
|
|
} flags;
|
|
Bit16u window;
|
|
Bit16u checksum;
|
|
Bit16u urgent_ptr;
|
|
}
|
|
#if !defined(_MSC_VER)
|
|
GCC_ATTRIBUTE((packed))
|
|
#endif
|
|
tcp_header_t;
|
|
|
|
#if defined(_MSC_VER)
|
|
#pragma pack(pop)
|
|
#elif defined(__MWERKS__) && defined(macintosh)
|
|
#pragma options align=reset
|
|
#endif
|
|
|
|
// DHCP configuration structure
|
|
typedef struct {
|
|
Bit8u host_macaddr[6];
|
|
Bit8u host_ipv4addr[4];
|
|
Bit8u dns_ipv4addr[4];
|
|
} dhcp_cfg_t;
|
|
|
|
// vnet functions shared with bxhub
|
|
#ifdef BXHUB
|
|
#define bx_devmodel_c void
|
|
#endif
|
|
Bit16u ip_checksum(const Bit8u *buf, unsigned buf_len);
|
|
|
|
typedef struct tftp_session {
|
|
char filename[BX_PATHNAME_LEN];
|
|
Bit16u tid;
|
|
bx_bool write;
|
|
unsigned options;
|
|
size_t tsize_val;
|
|
unsigned blksize_val;
|
|
unsigned timeout_val;
|
|
unsigned timestamp;
|
|
struct tftp_session *next;
|
|
} tftp_session_t;
|
|
|
|
// VNET server
|
|
|
|
#define VNET_MAX_CLIENTS 6
|
|
#define LAYER4_LISTEN_MAX 128
|
|
|
|
typedef int (*layer4_handler_t)(
|
|
void *this_ptr,
|
|
const Bit8u *ipheader,
|
|
unsigned ipheader_len,
|
|
unsigned sourceport,
|
|
unsigned targetport,
|
|
const Bit8u *data,
|
|
unsigned data_len,
|
|
Bit8u *reply
|
|
);
|
|
|
|
typedef struct tcp_conn {
|
|
Bit8u clientid;
|
|
Bit16u src_port;
|
|
Bit16u dst_port;
|
|
Bit32u host_seq_num;
|
|
Bit32u guest_seq_num;
|
|
Bit16u window;
|
|
Bit8u state;
|
|
void *data;
|
|
struct tcp_conn *next;
|
|
} tcp_conn_t;
|
|
|
|
typedef void (*tcp_handler_t)(
|
|
void *this_ptr,
|
|
tcp_conn_t *tcp_conn,
|
|
const Bit8u *data,
|
|
unsigned data_len
|
|
);
|
|
|
|
typedef struct ftp_session {
|
|
Bit8u state;
|
|
bx_bool anonymous;
|
|
struct ftp_session *next;
|
|
} ftp_session_t;
|
|
|
|
|
|
class vnet_server_c {
|
|
public:
|
|
vnet_server_c();
|
|
virtual ~vnet_server_c();
|
|
|
|
void init(bx_devmodel_c *netdev, dhcp_cfg_t *dhcpc, const char *tftp_rootdir);
|
|
void init_client(Bit8u clientid, const Bit8u *macaddr, const Bit8u *default_ipv4addr);
|
|
void handle_packet(const Bit8u *buf, unsigned len);
|
|
unsigned get_packet(Bit8u *buf);
|
|
#ifdef BXHUB
|
|
void init_log(const char *logfn);
|
|
#endif
|
|
|
|
layer4_handler_t get_layer4_handler(unsigned ipprotocol, unsigned port);
|
|
bx_bool register_layer4_handler(unsigned ipprotocol, unsigned port,
|
|
layer4_handler_t func);
|
|
bx_bool unregister_layer4_handler(unsigned ipprotocol, unsigned port);
|
|
|
|
tcp_handler_t get_tcp_handler(unsigned port);
|
|
bx_bool register_tcp_handler(unsigned port, tcp_handler_t func);
|
|
bx_bool unregister_tcp_handler(unsigned port);
|
|
|
|
private:
|
|
#ifdef BXHUB
|
|
void bx_printf(const char *fmt, ...);
|
|
#endif
|
|
bx_bool find_client(const Bit8u *mac_addr, Bit8u *clientid);
|
|
bx_bool find_client2(const Bit8u *ipv4addr, Bit8u *clientid);
|
|
|
|
void host_to_guest(Bit8u clientid, Bit8u *buf, unsigned len, unsigned l3type);
|
|
|
|
void process_arp(Bit8u clientid, const Bit8u *buf, unsigned len);
|
|
|
|
void process_ipv4(Bit8u clientid, const Bit8u *buf, unsigned len);
|
|
void host_to_guest_ipv4(Bit8u clientid, bx_bool dns_srv, Bit8u *buf, unsigned len);
|
|
|
|
void process_icmpipv4(Bit8u clientid, const Bit8u *ipheader, unsigned ipheader_len,
|
|
const Bit8u *l4pkt, unsigned l4pkt_len);
|
|
void process_tcpipv4(Bit8u clientid, const Bit8u *ipheader, unsigned ipheader_len,
|
|
const Bit8u *l4pkt, unsigned l4pkt_len);
|
|
void process_udpipv4(Bit8u clientid, const Bit8u *ipheader, unsigned ipheader_len,
|
|
const Bit8u *l4pkt, unsigned l4pkt_len);
|
|
|
|
void host_to_guest_tcpipv4(Bit8u clientid, Bit16u src_port, Bit16u dst_port,
|
|
Bit8u *data, unsigned data_len, unsigned hdr_len);
|
|
void tcpipv4_send_data(const tcp_conn_t *tcp_conn, const Bit8u *data,
|
|
unsigned data_len, bx_bool push);
|
|
void tcpipv4_send_ack(const tcp_conn_t *tcp_conn, unsigned data_len);
|
|
|
|
static void tcpipv4_ftp_handler(void *this_ptr, tcp_conn_t *tcp_conn,
|
|
const Bit8u *data, unsigned data_len);
|
|
void tcpipv4_ftp_handler_ns(tcp_conn_t *tcp_conn, const Bit8u *data,
|
|
unsigned data_len);
|
|
|
|
static int udpipv4_dhcp_handler(void *this_ptr, const Bit8u *ipheader,
|
|
unsigned ipheader_len, unsigned sourceport,
|
|
unsigned targetport, const Bit8u *data,
|
|
unsigned data_len, Bit8u *reply);
|
|
int udpipv4_dhcp_handler_ns(const Bit8u *ipheader, unsigned ipheader_len,
|
|
unsigned sourceport, unsigned targetport,
|
|
const Bit8u *data, unsigned data_len, Bit8u *reply);
|
|
static int udpipv4_tftp_handler(void *this_ptr, const Bit8u *ipheader,
|
|
unsigned ipheader_len, unsigned sourceport,
|
|
unsigned targetport, const Bit8u *data,
|
|
unsigned data_len, Bit8u *reply);
|
|
int udpipv4_tftp_handler_ns(const Bit8u *ipheader, unsigned ipheader_len,
|
|
unsigned sourceport, unsigned targetport,
|
|
const Bit8u *data, unsigned data_len, Bit8u *reply);
|
|
static int udpipv4_dns_handler(void *this_ptr, const Bit8u *ipheader,
|
|
unsigned ipheader_len, unsigned sourceport,
|
|
unsigned targetport, const Bit8u *data,
|
|
unsigned data_len, Bit8u *reply);
|
|
int udpipv4_dns_handler_ns(const Bit8u *ipheader, unsigned ipheader_len,
|
|
unsigned sourceport, unsigned targetport,
|
|
const Bit8u *data, unsigned data_len, Bit8u *reply);
|
|
|
|
void tftp_parse_options(const char *mode, const Bit8u *data, unsigned data_len,
|
|
tftp_session_t *s);
|
|
|
|
#ifdef BXHUB
|
|
FILE *logfd;
|
|
#endif
|
|
bx_devmodel_c *netdev;
|
|
dhcp_cfg_t *dhcp;
|
|
const char *tftp_root;
|
|
|
|
struct {
|
|
bx_bool init;
|
|
const Bit8u *macaddr;
|
|
const Bit8u *default_ipv4addr;
|
|
Bit8u ipv4addr[4];
|
|
char *hostname;
|
|
} client[VNET_MAX_CLIENTS];
|
|
|
|
struct {
|
|
unsigned ipprotocol;
|
|
unsigned port;
|
|
layer4_handler_t func;
|
|
} l4data[LAYER4_LISTEN_MAX];
|
|
|
|
struct {
|
|
unsigned port;
|
|
tcp_handler_t func;
|
|
} tcpfn[LAYER4_LISTEN_MAX];
|
|
|
|
unsigned l4data_used;
|
|
unsigned tcpfn_used;
|
|
|
|
Bit8u *packet_buffer[2];
|
|
unsigned packet_len[2];
|
|
Bit8u packet_count;
|
|
};
|
|
|
|
#endif
|