- applied SF patch #1695652 by Duane Voth
* dumps vnet traffic to a .pcap file for use with wireshark et. al. * sets the default PXE boot filename to pxelinux.0 * fills out the TFTP implementation far enough to use an etherboot rom
This commit is contained in:
parent
feb2f45a3e
commit
1ce5222640
@ -1,5 +1,5 @@
|
|||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// $Id: eth_vnet.cc,v 1.18 2005-12-10 18:37:35 vruppert Exp $
|
// $Id: eth_vnet.cc,v 1.19 2007-07-01 07:28:14 vruppert Exp $
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// virtual Ethernet locator
|
// virtual Ethernet locator
|
||||||
@ -27,6 +27,11 @@
|
|||||||
#define LOG_THIS bx_devices.pluginNE2kDevice->
|
#define LOG_THIS bx_devices.pluginNE2kDevice->
|
||||||
|
|
||||||
#define BX_ETH_VNET_LOGGING 1
|
#define BX_ETH_VNET_LOGGING 1
|
||||||
|
#define BX_ETH_VNET_PCAP_LOGGING 0
|
||||||
|
|
||||||
|
#if BX_ETH_VNET_PCAP_LOGGING
|
||||||
|
#include <pcap.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
// handler to send/receive packets
|
// handler to send/receive packets
|
||||||
@ -78,6 +83,7 @@ typedef void (*layer4_handler_t)(
|
|||||||
#define TFTP_DATA 3
|
#define TFTP_DATA 3
|
||||||
#define TFTP_ACK 4
|
#define TFTP_ACK 4
|
||||||
#define TFTP_ERROR 5
|
#define TFTP_ERROR 5
|
||||||
|
#define TFTP_OPTACK 6
|
||||||
|
|
||||||
#define TFTP_BUFFER_SIZE 512
|
#define TFTP_BUFFER_SIZE 512
|
||||||
|
|
||||||
@ -190,6 +196,10 @@ private:
|
|||||||
Bit8u *buffer,
|
Bit8u *buffer,
|
||||||
unsigned sourceport, unsigned targetport,
|
unsigned sourceport, unsigned targetport,
|
||||||
unsigned block_nr);
|
unsigned block_nr);
|
||||||
|
void tftp_send_optack(
|
||||||
|
Bit8u *buffer,
|
||||||
|
unsigned sourceport, unsigned targetport,
|
||||||
|
unsigned tsize_option, unsigned blksize_option);
|
||||||
|
|
||||||
char tftp_filename[BX_PATHNAME_LEN];
|
char tftp_filename[BX_PATHNAME_LEN];
|
||||||
char tftp_rootdir[BX_PATHNAME_LEN];
|
char tftp_rootdir[BX_PATHNAME_LEN];
|
||||||
@ -216,6 +226,11 @@ private:
|
|||||||
#if BX_ETH_VNET_LOGGING
|
#if BX_ETH_VNET_LOGGING
|
||||||
FILE *pktlog_txt;
|
FILE *pktlog_txt;
|
||||||
#endif // BX_ETH_VNET_LOGGING
|
#endif // BX_ETH_VNET_LOGGING
|
||||||
|
#if BX_ETH_VNET_PCAP_LOGGING
|
||||||
|
pcap_t *pcapp;
|
||||||
|
pcap_dumper_t *pktlog_pcap;
|
||||||
|
struct pcap_pkthdr pcaphdr;
|
||||||
|
#endif // BX_ETH_VNET_PCAP_LOGGING
|
||||||
};
|
};
|
||||||
|
|
||||||
class bx_vnet_locator_c : public eth_locator_c {
|
class bx_vnet_locator_c : public eth_locator_c {
|
||||||
@ -281,12 +296,33 @@ static Bit16u ip_checksum(const Bit8u *buf, unsigned buf_len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// duplicate the part of tftp_send_data() that constructs the filename
|
||||||
|
// but ignore errors since tftp_send_data() will respond for us
|
||||||
|
static size_t get_file_size(const char *tpath, const char *tname)
|
||||||
|
{
|
||||||
|
struct stat stbuf;
|
||||||
|
char path[BX_PATHNAME_LEN];
|
||||||
|
|
||||||
|
if (strlen(tname) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((strlen(tpath) + strlen(tname)) > BX_PATHNAME_LEN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sprintf(path, "%s/%s", tpath, tname);
|
||||||
|
if (stat(path, &stbuf) < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
BX_INFO(("tftp filesize: %lu", (unsigned long)stbuf.st_size));
|
||||||
|
return stbuf.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bx_vnet_pktmover_c::bx_vnet_pktmover_c()
|
bx_vnet_pktmover_c::bx_vnet_pktmover_c()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::pktmover_init(
|
||||||
bx_vnet_pktmover_c::pktmover_init(
|
|
||||||
const char *netif, const char *macaddr,
|
const char *netif, const char *macaddr,
|
||||||
eth_rx_handler_t rxh, void *rxarg, char *script)
|
eth_rx_handler_t rxh, void *rxarg, char *script)
|
||||||
{
|
{
|
||||||
@ -328,16 +364,19 @@ bx_vnet_pktmover_c::pktmover_init(
|
|||||||
fprintf (pktlog_txt, "--\n");
|
fprintf (pktlog_txt, "--\n");
|
||||||
fflush (pktlog_txt);
|
fflush (pktlog_txt);
|
||||||
#endif
|
#endif
|
||||||
|
#if BX_ETH_VNET_PCAP_LOGGING
|
||||||
|
pcapp = pcap_open_dead (DLT_EN10MB, BX_PACKET_BUFSIZE);
|
||||||
|
pktlog_pcap = pcap_dump_open (pcapp, "ne2k-pktlog.pcap");
|
||||||
|
if (pktlog_pcap == NULL) BX_PANIC (("ne2k-pktlog.pcap failed"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::sendpkt(void *buf, unsigned io_len)
|
||||||
bx_vnet_pktmover_c::sendpkt(void *buf, unsigned io_len)
|
|
||||||
{
|
{
|
||||||
guest_to_host((const Bit8u *)buf,io_len);
|
guest_to_host((const Bit8u *)buf,io_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::guest_to_host(const Bit8u *buf, unsigned io_len)
|
||||||
bx_vnet_pktmover_c::guest_to_host(const Bit8u *buf, unsigned io_len)
|
|
||||||
{
|
{
|
||||||
#if BX_ETH_VNET_LOGGING
|
#if BX_ETH_VNET_LOGGING
|
||||||
fprintf (pktlog_txt, "a packet from guest to host, length %u\n", io_len);
|
fprintf (pktlog_txt, "a packet from guest to host, length %u\n", io_len);
|
||||||
@ -351,6 +390,17 @@ bx_vnet_pktmover_c::guest_to_host(const Bit8u *buf, unsigned io_len)
|
|||||||
fprintf (pktlog_txt, "\n--\n");
|
fprintf (pktlog_txt, "\n--\n");
|
||||||
fflush (pktlog_txt);
|
fflush (pktlog_txt);
|
||||||
#endif
|
#endif
|
||||||
|
#if BX_ETH_VNET_PCAP_LOGGING
|
||||||
|
if (pktlog_pcap && !ferror((FILE *)pktlog_pcap)) {
|
||||||
|
Bit64u time = bx_pc_system.time_usec();
|
||||||
|
pcaphdr.ts.tv_usec = time % 1000000;
|
||||||
|
pcaphdr.ts.tv_sec = time / 1000000;
|
||||||
|
pcaphdr.caplen = io_len;
|
||||||
|
pcaphdr.len = io_len;
|
||||||
|
pcap_dump((u_char *)pktlog_pcap, &pcaphdr, buf);
|
||||||
|
fflush((FILE *)pktlog_pcap);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
this->tx_time = (64 + 96 + 4 * 8 + io_len * 8) / 10;
|
this->tx_time = (64 + 96 + 4 * 8 + io_len * 8) / 10;
|
||||||
if ((io_len >= 14) &&
|
if ((io_len >= 14) &&
|
||||||
@ -371,16 +421,14 @@ bx_vnet_pktmover_c::guest_to_host(const Bit8u *buf, unsigned io_len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The receive poll process
|
// The receive poll process
|
||||||
void
|
void bx_vnet_pktmover_c::rx_timer_handler(void *this_ptr)
|
||||||
bx_vnet_pktmover_c::rx_timer_handler(void *this_ptr)
|
|
||||||
{
|
{
|
||||||
bx_vnet_pktmover_c *class_ptr = (bx_vnet_pktmover_c *) this_ptr;
|
bx_vnet_pktmover_c *class_ptr = (bx_vnet_pktmover_c *) this_ptr;
|
||||||
|
|
||||||
class_ptr->rx_timer();
|
class_ptr->rx_timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::rx_timer(void)
|
||||||
bx_vnet_pktmover_c::rx_timer(void)
|
|
||||||
{
|
{
|
||||||
this->rxh(this->rxarg, (void *)packet_buffer, packet_len);
|
this->rxh(this->rxarg, (void *)packet_buffer, packet_len);
|
||||||
#if BX_ETH_VNET_LOGGING
|
#if BX_ETH_VNET_LOGGING
|
||||||
@ -395,10 +443,20 @@ bx_vnet_pktmover_c::rx_timer(void)
|
|||||||
fprintf (pktlog_txt, "\n--\n");
|
fprintf (pktlog_txt, "\n--\n");
|
||||||
fflush (pktlog_txt);
|
fflush (pktlog_txt);
|
||||||
#endif
|
#endif
|
||||||
|
#if BX_ETH_VNET_PCAP_LOGGING
|
||||||
|
if (pktlog_pcap && !ferror((FILE *)pktlog_pcap)) {
|
||||||
|
Bit64u time = bx_pc_system.time_usec();
|
||||||
|
pcaphdr.ts.tv_usec = time % 1000000;
|
||||||
|
pcaphdr.ts.tv_sec = time / 1000000;
|
||||||
|
pcaphdr.caplen = packet_len;
|
||||||
|
pcaphdr.len = packet_len;
|
||||||
|
pcap_dump((u_char *)pktlog_pcap, &pcaphdr, packet_buffer);
|
||||||
|
fflush((FILE *)pktlog_pcap);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::host_to_guest(Bit8u *buf, unsigned io_len)
|
||||||
bx_vnet_pktmover_c::host_to_guest(Bit8u *buf, unsigned io_len)
|
|
||||||
{
|
{
|
||||||
Bit8u localbuf[60];
|
Bit8u localbuf[60];
|
||||||
|
|
||||||
@ -424,8 +482,7 @@ bx_vnet_pktmover_c::host_to_guest(Bit8u *buf, unsigned io_len)
|
|||||||
// ARP
|
// ARP
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::process_arp(const Bit8u *buf, unsigned io_len)
|
||||||
bx_vnet_pktmover_c::process_arp(const Bit8u *buf, unsigned io_len)
|
|
||||||
{
|
{
|
||||||
unsigned opcode;
|
unsigned opcode;
|
||||||
unsigned protocol;
|
unsigned protocol;
|
||||||
@ -485,8 +542,7 @@ bx_vnet_pktmover_c::process_arp(const Bit8u *buf, unsigned io_len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::host_to_guest_arp(Bit8u *buf, unsigned io_len)
|
||||||
bx_vnet_pktmover_c::host_to_guest_arp(Bit8u *buf, unsigned io_len)
|
|
||||||
{
|
{
|
||||||
memcpy(&buf[0],&this->guest_macaddr[0],6);
|
memcpy(&buf[0],&this->guest_macaddr[0],6);
|
||||||
memcpy(&buf[6],&this->host_macaddr[0],6);
|
memcpy(&buf[6],&this->host_macaddr[0],6);
|
||||||
@ -499,8 +555,7 @@ bx_vnet_pktmover_c::host_to_guest_arp(Bit8u *buf, unsigned io_len)
|
|||||||
// IPv4
|
// IPv4
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::process_ipv4(const Bit8u *buf, unsigned io_len)
|
||||||
bx_vnet_pktmover_c::process_ipv4(const Bit8u *buf, unsigned io_len)
|
|
||||||
{
|
{
|
||||||
unsigned total_len;
|
unsigned total_len;
|
||||||
unsigned packet_id;
|
unsigned packet_id;
|
||||||
@ -575,8 +630,7 @@ bx_vnet_pktmover_c::process_ipv4(const Bit8u *buf, unsigned io_len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::host_to_guest_ipv4(Bit8u *buf, unsigned io_len)
|
||||||
bx_vnet_pktmover_c::host_to_guest_ipv4(Bit8u *buf, unsigned io_len)
|
|
||||||
{
|
{
|
||||||
unsigned l3header_len;
|
unsigned l3header_len;
|
||||||
|
|
||||||
@ -594,8 +648,7 @@ bx_vnet_pktmover_c::host_to_guest_ipv4(Bit8u *buf, unsigned io_len)
|
|||||||
host_to_guest(buf,io_len);
|
host_to_guest(buf,io_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
layer4_handler_t
|
layer4_handler_t bx_vnet_pktmover_c::get_layer4_handler(
|
||||||
bx_vnet_pktmover_c::get_layer4_handler(
|
|
||||||
unsigned ipprotocol, unsigned port)
|
unsigned ipprotocol, unsigned port)
|
||||||
{
|
{
|
||||||
unsigned n;
|
unsigned n;
|
||||||
@ -608,8 +661,7 @@ bx_vnet_pktmover_c::get_layer4_handler(
|
|||||||
return (layer4_handler_t)NULL;
|
return (layer4_handler_t)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bx_bool
|
bx_bool bx_vnet_pktmover_c::register_layer4_handler(
|
||||||
bx_vnet_pktmover_c::register_layer4_handler(
|
|
||||||
unsigned ipprotocol, unsigned port,layer4_handler_t func)
|
unsigned ipprotocol, unsigned port,layer4_handler_t func)
|
||||||
{
|
{
|
||||||
if (get_layer4_handler(ipprotocol,port) != (layer4_handler_t)NULL) {
|
if (get_layer4_handler(ipprotocol,port) != (layer4_handler_t)NULL) {
|
||||||
@ -641,8 +693,7 @@ bx_vnet_pktmover_c::register_layer4_handler(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bx_bool
|
bx_bool bx_vnet_pktmover_c::unregister_layer4_handler(
|
||||||
bx_vnet_pktmover_c::unregister_layer4_handler(
|
|
||||||
unsigned ipprotocol, unsigned port)
|
unsigned ipprotocol, unsigned port)
|
||||||
{
|
{
|
||||||
unsigned n;
|
unsigned n;
|
||||||
@ -659,8 +710,7 @@ bx_vnet_pktmover_c::unregister_layer4_handler(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::process_icmpipv4(
|
||||||
bx_vnet_pktmover_c::process_icmpipv4(
|
|
||||||
const Bit8u *ipheader, unsigned ipheader_len,
|
const Bit8u *ipheader, unsigned ipheader_len,
|
||||||
const Bit8u *l4pkt, unsigned l4pkt_len)
|
const Bit8u *l4pkt, unsigned l4pkt_len)
|
||||||
{
|
{
|
||||||
@ -688,8 +738,7 @@ bx_vnet_pktmover_c::process_icmpipv4(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::process_tcpipv4(
|
||||||
bx_vnet_pktmover_c::process_tcpipv4(
|
|
||||||
const Bit8u *ipheader, unsigned ipheader_len,
|
const Bit8u *ipheader, unsigned ipheader_len,
|
||||||
const Bit8u *l4pkt, unsigned l4pkt_len)
|
const Bit8u *l4pkt, unsigned l4pkt_len)
|
||||||
{
|
{
|
||||||
@ -698,8 +747,7 @@ bx_vnet_pktmover_c::process_tcpipv4(
|
|||||||
BX_INFO(("tcp packet - not implemented"));
|
BX_INFO(("tcp packet - not implemented"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::process_udpipv4(
|
||||||
bx_vnet_pktmover_c::process_udpipv4(
|
|
||||||
const Bit8u *ipheader, unsigned ipheader_len,
|
const Bit8u *ipheader, unsigned ipheader_len,
|
||||||
const Bit8u *l4pkt, unsigned l4pkt_len)
|
const Bit8u *l4pkt, unsigned l4pkt_len)
|
||||||
{
|
{
|
||||||
@ -722,8 +770,7 @@ bx_vnet_pktmover_c::process_udpipv4(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::host_to_guest_udpipv4_packet(
|
||||||
bx_vnet_pktmover_c::host_to_guest_udpipv4_packet(
|
|
||||||
unsigned target_port, unsigned source_port,
|
unsigned target_port, unsigned source_port,
|
||||||
const Bit8u *udpdata, unsigned udpdata_len)
|
const Bit8u *udpdata, unsigned udpdata_len)
|
||||||
{
|
{
|
||||||
@ -765,8 +812,7 @@ bx_vnet_pktmover_c::host_to_guest_udpipv4_packet(
|
|||||||
// ICMP/IPv4
|
// ICMP/IPv4
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::process_icmpipv4_echo(
|
||||||
bx_vnet_pktmover_c::process_icmpipv4_echo(
|
|
||||||
const Bit8u *ipheader, unsigned ipheader_len,
|
const Bit8u *ipheader, unsigned ipheader_len,
|
||||||
const Bit8u *l4pkt, unsigned l4pkt_len)
|
const Bit8u *l4pkt, unsigned l4pkt_len)
|
||||||
{
|
{
|
||||||
@ -792,8 +838,7 @@ bx_vnet_pktmover_c::process_icmpipv4_echo(
|
|||||||
// DHCP/UDP/IPv4
|
// DHCP/UDP/IPv4
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::udpipv4_dhcp_handler(
|
||||||
bx_vnet_pktmover_c::udpipv4_dhcp_handler(
|
|
||||||
void *this_ptr,
|
void *this_ptr,
|
||||||
const Bit8u *ipheader, unsigned ipheader_len,
|
const Bit8u *ipheader, unsigned ipheader_len,
|
||||||
unsigned sourceport, unsigned targetport,
|
unsigned sourceport, unsigned targetport,
|
||||||
@ -803,8 +848,7 @@ bx_vnet_pktmover_c::udpipv4_dhcp_handler(
|
|||||||
ipheader,ipheader_len,sourceport,targetport,data,data_len);
|
ipheader,ipheader_len,sourceport,targetport,data,data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::udpipv4_dhcp_handler_ns(
|
||||||
bx_vnet_pktmover_c::udpipv4_dhcp_handler_ns(
|
|
||||||
const Bit8u *ipheader, unsigned ipheader_len,
|
const Bit8u *ipheader, unsigned ipheader_len,
|
||||||
unsigned sourceport, unsigned targetport,
|
unsigned sourceport, unsigned targetport,
|
||||||
const Bit8u *data, unsigned data_len)
|
const Bit8u *data, unsigned data_len)
|
||||||
@ -912,10 +956,8 @@ bx_vnet_pktmover_c::udpipv4_dhcp_handler_ns(
|
|||||||
memcpy(&replybuf[16],default_guest_ipv4addr,4);
|
memcpy(&replybuf[16],default_guest_ipv4addr,4);
|
||||||
memcpy(&replybuf[20],host_ipv4addr,4);
|
memcpy(&replybuf[20],host_ipv4addr,4);
|
||||||
memcpy(&replybuf[28],&data[28],6);
|
memcpy(&replybuf[28],&data[28],6);
|
||||||
replybuf[44] = 'v';
|
memcpy(&replybuf[44],"vnet",4);
|
||||||
replybuf[45] = 'n';
|
memcpy(&replybuf[108],"pxelinux.0",10);
|
||||||
replybuf[46] = 'e';
|
|
||||||
replybuf[47] = 't';
|
|
||||||
replybuf[236] = 0x63;
|
replybuf[236] = 0x63;
|
||||||
replybuf[237] = 0x82;
|
replybuf[237] = 0x82;
|
||||||
replybuf[238] = 0x53;
|
replybuf[238] = 0x53;
|
||||||
@ -1104,8 +1146,7 @@ bx_vnet_pktmover_c::udpipv4_dhcp_handler_ns(
|
|||||||
replybuf, opts_len);
|
replybuf, opts_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::udpipv4_tftp_handler(
|
||||||
bx_vnet_pktmover_c::udpipv4_tftp_handler(
|
|
||||||
void *this_ptr,
|
void *this_ptr,
|
||||||
const Bit8u *ipheader, unsigned ipheader_len,
|
const Bit8u *ipheader, unsigned ipheader_len,
|
||||||
unsigned sourceport, unsigned targetport,
|
unsigned sourceport, unsigned targetport,
|
||||||
@ -1115,8 +1156,7 @@ bx_vnet_pktmover_c::udpipv4_tftp_handler(
|
|||||||
ipheader,ipheader_len,sourceport,targetport,data,data_len);
|
ipheader,ipheader_len,sourceport,targetport,data,data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::udpipv4_tftp_handler_ns(
|
||||||
bx_vnet_pktmover_c::udpipv4_tftp_handler_ns(
|
|
||||||
const Bit8u *ipheader, unsigned ipheader_len,
|
const Bit8u *ipheader, unsigned ipheader_len,
|
||||||
unsigned sourceport, unsigned targetport,
|
unsigned sourceport, unsigned targetport,
|
||||||
const Bit8u *data, unsigned data_len)
|
const Bit8u *data, unsigned data_len)
|
||||||
@ -1133,16 +1173,48 @@ bx_vnet_pktmover_c::udpipv4_tftp_handler_ns(
|
|||||||
strncpy((char*)buffer, (const char*)data + 2, data_len - 2);
|
strncpy((char*)buffer, (const char*)data + 2, data_len - 2);
|
||||||
buffer[data_len - 4] = 0;
|
buffer[data_len - 4] = 0;
|
||||||
|
|
||||||
// transfer mode
|
// options
|
||||||
|
size_t tsize_option = 0;
|
||||||
|
int blksize_option = 0;
|
||||||
if (strlen((char*)buffer) < data_len - 2) {
|
if (strlen((char*)buffer) < data_len - 2) {
|
||||||
const char *mode = (const char*)data + 2 + strlen((char*)buffer) + 1;
|
const char *mode = (const char*)data + 2 + strlen((char*)buffer) + 1;
|
||||||
if (memcmp(mode, "octet\0", 6) != 0) {
|
int octet_option = 0;
|
||||||
|
while (mode < (const char*)data + data_len) {
|
||||||
|
if (memcmp(mode, "octet\0", 6) == 0) {
|
||||||
|
mode += 6;
|
||||||
|
octet_option = 1;
|
||||||
|
} else if (memcmp(mode, "tsize\0", 6) == 0) {
|
||||||
|
mode += 6;
|
||||||
|
tsize_option = 1; // size needed
|
||||||
|
mode += strlen(mode)+1;
|
||||||
|
} else if (memcmp(mode, "blksize\0", 8) == 0) {
|
||||||
|
mode += 8;
|
||||||
|
blksize_option = atoi(mode);
|
||||||
|
mode += strlen(mode)+1;
|
||||||
|
} else {
|
||||||
|
BX_INFO(("tftp req: unknown option %s", mode));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!octet_option) {
|
||||||
tftp_send_error(buffer, sourceport, targetport, 4, "Unsupported transfer mode");
|
tftp_send_error(buffer, sourceport, targetport, 4, "Unsupported transfer mode");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(tftp_filename, (char*)buffer);
|
strcpy(tftp_filename, (char*)buffer);
|
||||||
|
BX_INFO(("tftp req: %s", tftp_filename));
|
||||||
|
if (tsize_option) {
|
||||||
|
tsize_option = get_file_size(tftp_rootdir, tftp_filename);
|
||||||
|
if (tsize_option > 0) {
|
||||||
|
// if tsize requested and file exists, send optack and return
|
||||||
|
// optack ack will pick up where we leave off here.
|
||||||
|
// if blksize_option is less than TFTP_BUFFER_SIZE should
|
||||||
|
// probably use blksize_option...
|
||||||
|
tftp_send_optack(buffer, sourceport, targetport, tsize_option, TFTP_BUFFER_SIZE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
tftp_tid = sourceport;
|
tftp_tid = sourceport;
|
||||||
tftp_write = 0;
|
tftp_write = 0;
|
||||||
tftp_send_data(buffer, sourceport, targetport, 1);
|
tftp_send_data(buffer, sourceport, targetport, 1);
|
||||||
@ -1227,8 +1299,7 @@ bx_vnet_pktmover_c::udpipv4_tftp_handler_ns(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::tftp_send_error(
|
||||||
bx_vnet_pktmover_c::tftp_send_error(
|
|
||||||
Bit8u *buffer,
|
Bit8u *buffer,
|
||||||
unsigned sourceport, unsigned targetport,
|
unsigned sourceport, unsigned targetport,
|
||||||
unsigned code, const char *msg)
|
unsigned code, const char *msg)
|
||||||
@ -1240,8 +1311,7 @@ bx_vnet_pktmover_c::tftp_send_error(
|
|||||||
tftp_tid = 0;
|
tftp_tid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::tftp_send_data(
|
||||||
bx_vnet_pktmover_c::tftp_send_data(
|
|
||||||
Bit8u *buffer,
|
Bit8u *buffer,
|
||||||
unsigned sourceport, unsigned targetport,
|
unsigned sourceport, unsigned targetport,
|
||||||
unsigned block_nr)
|
unsigned block_nr)
|
||||||
@ -1289,8 +1359,7 @@ bx_vnet_pktmover_c::tftp_send_data(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void bx_vnet_pktmover_c::tftp_send_ack(
|
||||||
bx_vnet_pktmover_c::tftp_send_ack(
|
|
||||||
Bit8u *buffer,
|
Bit8u *buffer,
|
||||||
unsigned sourceport, unsigned targetport,
|
unsigned sourceport, unsigned targetport,
|
||||||
unsigned block_nr)
|
unsigned block_nr)
|
||||||
@ -1300,5 +1369,24 @@ bx_vnet_pktmover_c::tftp_send_ack(
|
|||||||
host_to_guest_udpipv4_packet(sourceport, targetport, buffer, 4);
|
host_to_guest_udpipv4_packet(sourceport, targetport, buffer, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bx_vnet_pktmover_c::tftp_send_optack(
|
||||||
|
Bit8u *buffer,
|
||||||
|
unsigned sourceport, unsigned targetport,
|
||||||
|
size_t tsize_option, unsigned blksize_option)
|
||||||
|
{
|
||||||
|
Bit8u *p = buffer;
|
||||||
|
put_net2(p, TFTP_OPTACK);
|
||||||
|
p += 2;
|
||||||
|
if (tsize_option > 0) {
|
||||||
|
*p++='t'; *p++='s'; *p++='i'; *p++='z'; *p++='e'; *p++='\0';
|
||||||
|
sprintf((char *)p, "%lu", (unsigned long)tsize_option);
|
||||||
|
p += strlen((const char *)p) + 1;
|
||||||
|
}
|
||||||
|
if (blksize_option > 0) {
|
||||||
|
*p++='b'; *p++='l'; *p++='k'; *p++='s'; *p++='i'; *p++='z'; *p++='e'; *p++='\0';
|
||||||
|
sprintf((char *)p, "%d", blksize_option); p += strlen((const char *)p) + 1;
|
||||||
|
}
|
||||||
|
host_to_guest_udpipv4_packet(sourceport, targetport, buffer, p - buffer);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* if BX_NETWORKING */
|
#endif /* if BX_NETWORKING */
|
||||||
|
Loading…
Reference in New Issue
Block a user