1
0
mirror of https://github.com/solemnwarning/ipxwrapper synced 2024-12-30 16:45:37 +01:00

Implemented support for Novell "raw" Ethernet frames.

Manual selection of frame type (defaults to Ethernet II) only, don't want to
mess with trying to guess/detect the frame type right now.
This commit is contained in:
Daniel Collins 2017-03-27 23:32:43 +01:00
parent d7c9e10349
commit 20a636b933
5 changed files with 109 additions and 22 deletions

View File

@ -27,11 +27,12 @@ main_config_t get_main_config(void)
main_config_t config;
config.udp_port = DEFAULT_PORT;
config.w95_bug = true;
config.fw_except = false;
config.use_pcap = false;
config.log_level = LOG_INFO;
config.udp_port = DEFAULT_PORT;
config.w95_bug = true;
config.fw_except = false;
config.use_pcap = false;
config.frame_type = FRAME_TYPE_ETH_II;
config.log_level = LOG_INFO;
HKEY reg = reg_open_main(false);
@ -49,11 +50,24 @@ main_config_t get_main_config(void)
/* Overlay with any 0.4.x config values. */
config.udp_port = reg_get_dword(reg, "port", config.udp_port);
config.w95_bug = reg_get_dword(reg, "w95_bug", config.w95_bug);
config.fw_except = reg_get_dword(reg, "fw_except", config.fw_except);
config.use_pcap = reg_get_dword(reg, "use_pcap", config.use_pcap);
config.log_level = reg_get_dword(reg, "log_level", config.log_level);
config.udp_port = reg_get_dword(reg, "port", config.udp_port);
config.w95_bug = reg_get_dword(reg, "w95_bug", config.w95_bug);
config.fw_except = reg_get_dword(reg, "fw_except", config.fw_except);
config.use_pcap = reg_get_dword(reg, "use_pcap", config.use_pcap);
config.frame_type = reg_get_dword(reg, "frame_type", config.frame_type);
config.log_level = reg_get_dword(reg, "log_level", config.log_level);
/* Check for valid frame_type */
if( config.frame_type != FRAME_TYPE_ETH_II
&& config.frame_type != FRAME_TYPE_NOVELL)
{
log_printf(LOG_WARNING, "Ignoring unknown frame_type %u",
(unsigned int)(config.frame_type));
config.frame_type = FRAME_TYPE_ETH_II;
}
reg_close(reg);
@ -64,11 +78,12 @@ bool set_main_config(const main_config_t *config)
{
HKEY reg = reg_open_main(true);
bool ok = reg_set_dword(reg, "port", config->udp_port)
&& reg_set_dword(reg, "w95_bug", config->w95_bug)
&& reg_set_dword(reg, "fw_except", config->fw_except)
&& reg_set_dword(reg, "use_pcap", config->use_pcap)
&& reg_set_dword(reg, "log_level", config->log_level);
bool ok = reg_set_dword(reg, "port", config->udp_port)
&& reg_set_dword(reg, "w95_bug", config->w95_bug)
&& reg_set_dword(reg, "fw_except", config->fw_except)
&& reg_set_dword(reg, "use_pcap", config->use_pcap)
&& reg_set_dword(reg, "frame_type", config->frame_type)
&& reg_set_dword(reg, "log_level", config->log_level);
reg_close(reg);

View File

@ -26,12 +26,19 @@
extern "C" {
#endif
enum main_config_frame_type
{
FRAME_TYPE_ETH_II = 1,
FRAME_TYPE_NOVELL = 2
};
typedef struct main_config {
uint16_t udp_port;
bool w95_bug;
bool fw_except;
bool use_pcap;
enum main_config_frame_type frame_type;
enum ipx_log_level log_level;
} main_config_t;

View File

@ -116,7 +116,11 @@ struct ethernet_frame
unsigned char dest_mac[6];
unsigned char src_mac[6];
uint16_t ethertype;
union {
/* Depends on frame type. */
uint16_t ethertype;
uint16_t length;
};
real_ipx_packet_t packet;
} __attribute__((__packed__));

View File

@ -505,10 +505,43 @@ static void _handle_pcap_frame(u_char *user, const struct pcap_pkthdr *pkt_heade
ethernet_frame_t *frame = (ethernet_frame_t*)(pkt_data);
if(ntohs(frame->ethertype) != 0x8137)
uint16_t ipx_packet_len = ntohs(frame->packet.length);
if(main_config.frame_type == FRAME_TYPE_ETH_II)
{
/* The ethertype field isn't IPX. */
return;
/* Configured for standard Ethernet. */
if(ntohs(frame->ethertype) != 0x8137)
{
/* The ethertype field isn't IPX. */
return;
}
}
else if(main_config.frame_type == FRAME_TYPE_NOVELL)
{
/* Configured for Novell "raw" Ethernet. */
uint16_t eth_payload_len = ntohs(frame->length);
if(eth_payload_len > 1500)
{
/* Too big, must be an Ethernet II frame (or garbage). */
return;
}
else if(eth_payload_len < sizeof(frame->packet))
{
/* Too small to hold an IPX header. */
return;
}
else if(eth_payload_len < ipx_packet_len)
{
/* Too small to hold the IPX payload within. */
return;
}
}
else{
/* Unknown frame type configured. */
abort();
}
if(frame->packet.checksum != 0xFFFF)
@ -517,7 +550,7 @@ static void _handle_pcap_frame(u_char *user, const struct pcap_pkthdr *pkt_heade
return;
}
if(ntohs(frame->packet.length) > (pkt_header->caplen - (sizeof(*frame) - sizeof(frame->packet))))
if(ipx_packet_len > (pkt_header->caplen - (sizeof(*frame) - sizeof(frame->packet))))
{
/* The "length" field in the IPX header is too big. */
return;

View File

@ -1206,13 +1206,41 @@ static DWORD ipx_send_packet(
return ERROR_OUTOFMEMORY;
}
log_printf(LOG_DEBUG, "...packet size = %d, frame size = %d",
log_printf(LOG_DEBUG, "...packet size = %u, frame size = %u",
(unsigned int)(packet_size), (unsigned int)(frame_size));
addr48_out(frame->dest_mac, dest_node);
addr48_out(frame->src_mac, iface->mac_addr);
frame->ethertype = htons(0x8137);
if(main_config.frame_type == FRAME_TYPE_ETH_II)
{
/* Configured for standard Ethernet. */
frame->ethertype = htons(0x8137);
}
else if(main_config.frame_type == FRAME_TYPE_NOVELL)
{
/* Configured for Novell "raw" Ethernet. */
if(packet_size > 1500)
{
/* Can't fit a payload this big into a
* Novell Ethernet frame.
*/
log_printf(LOG_ERROR,
"Tried sending a %u byte packet in a Novell (\"raw\") Ethernet frame",
(unsigned int)(packet_size));
free(frame);
return WSAEMSGSIZE;
}
frame->length = htons(packet_size);
}
else{
/* Unknown frame type configured. */
abort();
}
frame->packet.checksum = 0xFFFF;
frame->packet.length = htons(packet_size);