Bochs/bochs/iodev/network/netutil.h
Volker Ruppert 9c3a99856e Added basic TCP handling and FTP server stub for testing.
- 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).
2020-05-12 20:51:26 +00:00

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