mirror of
https://github.com/solemnwarning/ipxwrapper
synced 2024-12-30 16:45:37 +01:00
Refactored Ethernet frame (de)serialisation.
Reworked the (de)serialising of Ethernet frames into seperate functions in preparation for supporting IEEE 802.2 LLC frames.
This commit is contained in:
parent
d65fb92480
commit
b7b4a953d8
2
Makefile
2
Makefile
@ -46,7 +46,7 @@ VERSION := git
|
||||
|
||||
IPXWRAPPER_DEPS := src/ipxwrapper.o src/winsock.o src/ipxwrapper_stubs.o src/log.o src/common.o \
|
||||
src/interface.o src/router.o src/ipxwrapper.def src/addrcache.o src/config.o src/addr.o \
|
||||
src/firewall.o src/wpcap_stubs.o
|
||||
src/firewall.o src/wpcap_stubs.o src/ethernet.o
|
||||
|
||||
BIN_FILES := $(shell cat manifest.bin.txt)
|
||||
SRC_FILES := $(shell cat manifest.src.txt)
|
||||
|
@ -17,6 +17,8 @@ src/common.c
|
||||
src/common.h
|
||||
src/config.c
|
||||
src/config.h
|
||||
src/ethernet.c
|
||||
src/ethernet.h
|
||||
src/directplay.c
|
||||
src/dpwsockx.def
|
||||
src/dpwsockx_stubs.txt
|
||||
|
208
src/ethernet.c
Normal file
208
src/ethernet.c
Normal file
@ -0,0 +1,208 @@
|
||||
/* IPXWrapper - Ethernet frame handling
|
||||
* Copyright (C) 2017 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* 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., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/* This file implements three types of functions:
|
||||
*
|
||||
* XXX_frame_size
|
||||
*
|
||||
* Returns the size of a whole frame and IPX packet with the given number of
|
||||
* bytes of payload.
|
||||
*
|
||||
* Returns zero if the payload is too large to fit in a frame of this format.
|
||||
*
|
||||
* XXX_frame_pack
|
||||
*
|
||||
* Serialises a frame and IPX packet to the given buffer, which must be at
|
||||
* least as large as the size returned by the corresponding XXX_frame_size()
|
||||
* function.
|
||||
*
|
||||
* XXX_frame_unpack
|
||||
*
|
||||
* Deserialises a frame, giving the inner IPX packet and its size. Returns
|
||||
* true on success, false if the frame was invalid.
|
||||
*/
|
||||
|
||||
#define WINSOCK_API_LINKAGE
|
||||
#include <winsock2.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "addr.h"
|
||||
#include "ethernet.h"
|
||||
|
||||
#define ETHERTYPE_IPX 0x8137
|
||||
|
||||
typedef struct ethernet_header ethernet_header;
|
||||
|
||||
struct ethernet_header
|
||||
{
|
||||
unsigned char dest_mac[6];
|
||||
unsigned char src_mac[6];
|
||||
|
||||
union {
|
||||
/* Depends on frame type. */
|
||||
uint16_t ethertype;
|
||||
uint16_t length;
|
||||
};
|
||||
} __attribute__((__packed__));
|
||||
|
||||
static void _pack_ipx_packet(void *buf,
|
||||
uint8_t type,
|
||||
addr32_t src_net, addr48_t src_node, uint16_t src_socket,
|
||||
addr32_t dst_net, addr48_t dst_node, uint16_t dst_socket,
|
||||
const void *payload, size_t payload_len)
|
||||
{
|
||||
novell_ipx_packet *packet = buf;
|
||||
|
||||
packet->checksum = 0xFFFF;
|
||||
packet->length = htons(sizeof(novell_ipx_packet) + payload_len);
|
||||
packet->hops = 0;
|
||||
packet->type = type;
|
||||
|
||||
addr32_out(packet->dest_net, dst_net);
|
||||
addr48_out(packet->dest_node, dst_node);
|
||||
packet->dest_socket = dst_socket;
|
||||
|
||||
addr32_out(packet->src_net, src_net);
|
||||
addr48_out(packet->src_node, src_node);
|
||||
packet->src_socket = src_socket;
|
||||
|
||||
memcpy(packet->data, payload, payload_len);
|
||||
}
|
||||
|
||||
size_t ethII_frame_size(size_t ipx_payload_len)
|
||||
{
|
||||
if(ipx_payload_len > NOVELL_IPX_PACKET_MAX_PAYLOAD)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sizeof(ethernet_header)
|
||||
+ sizeof(novell_ipx_packet)
|
||||
+ ipx_payload_len;
|
||||
}
|
||||
|
||||
void ethII_frame_pack(void *frame_buffer,
|
||||
uint8_t type,
|
||||
addr32_t src_net, addr48_t src_node, uint16_t src_socket,
|
||||
addr32_t dst_net, addr48_t dst_node, uint16_t dst_socket,
|
||||
const void *payload, size_t payload_len)
|
||||
{
|
||||
ethernet_header *eth_h = frame_buffer;
|
||||
|
||||
addr48_out(eth_h->dest_mac, dst_node);
|
||||
eth_h->ethertype = htons(ETHERTYPE_IPX);
|
||||
|
||||
_pack_ipx_packet(eth_h + 1,
|
||||
type,
|
||||
src_net, src_node, src_socket,
|
||||
dst_net, dst_node, dst_socket,
|
||||
payload, payload_len);
|
||||
}
|
||||
|
||||
bool ethII_frame_unpack(const novell_ipx_packet **packet, size_t *packet_len, const void *frame_data, size_t frame_len)
|
||||
{
|
||||
if(frame_len < sizeof(ethernet_header) + sizeof(novell_ipx_packet))
|
||||
{
|
||||
/* Frame is too small to contain all the necessary headers. */
|
||||
return false;
|
||||
}
|
||||
|
||||
const ethernet_header *eth_h = frame_data;
|
||||
|
||||
if(ntohs(eth_h->ethertype) != ETHERTYPE_IPX)
|
||||
{
|
||||
/* The ethertype field isn't IPX. */
|
||||
return false;
|
||||
}
|
||||
|
||||
*packet = (const novell_ipx_packet*)(eth_h + 1);
|
||||
*packet_len = frame_len - sizeof(ethernet_header);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t novell_frame_size(size_t ipx_payload_len)
|
||||
{
|
||||
static const size_t OVERHEAD
|
||||
= sizeof(ethernet_header)
|
||||
+ sizeof(novell_ipx_packet);
|
||||
|
||||
if(ipx_payload_len > NOVELL_IPX_PACKET_MAX_PAYLOAD
|
||||
|| ipx_payload_len > (1500 - OVERHEAD))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return OVERHEAD + ipx_payload_len;
|
||||
}
|
||||
|
||||
void novell_frame_pack(void *frame_buffer,
|
||||
uint8_t type,
|
||||
addr32_t src_net, addr48_t src_node, uint16_t src_socket,
|
||||
addr32_t dst_net, addr48_t dst_node, uint16_t dst_socket,
|
||||
const void *payload, size_t payload_len)
|
||||
{
|
||||
ethernet_header *eth_h = frame_buffer;
|
||||
|
||||
addr48_out(eth_h->dest_mac, dst_node);
|
||||
eth_h->length = htons(sizeof(novell_ipx_packet) + payload_len);
|
||||
|
||||
_pack_ipx_packet(eth_h + 1,
|
||||
type,
|
||||
src_net, src_node, src_socket,
|
||||
dst_net, dst_node, dst_socket,
|
||||
payload, payload_len);
|
||||
}
|
||||
|
||||
bool novell_frame_unpack(const novell_ipx_packet **packet, size_t *packet_len, const void *frame_data, size_t frame_len)
|
||||
{
|
||||
if(frame_len < sizeof(ethernet_header) + sizeof(novell_ipx_packet))
|
||||
{
|
||||
/* Frame is too small to contain all the necessary headers. */
|
||||
return false;
|
||||
}
|
||||
|
||||
const ethernet_header *eth_h = frame_data;
|
||||
|
||||
uint16_t payload_len = ntohs(eth_h->length);
|
||||
|
||||
if(payload_len > 1500)
|
||||
{
|
||||
/* Payload too big, probably an Ethernet II frame. */
|
||||
return false;
|
||||
}
|
||||
else if(payload_len < sizeof(novell_ipx_packet))
|
||||
{
|
||||
/* Too small to hold an IPX header. */
|
||||
return false;
|
||||
}
|
||||
else if(payload_len > frame_len - sizeof(ethernet_header))
|
||||
{
|
||||
/* Payload length runs past the end of frame_len, was the frame
|
||||
* somehow truncated?
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
*packet = (const novell_ipx_packet*)(eth_h + 1);
|
||||
*packet_len = payload_len;
|
||||
|
||||
return true;
|
||||
}
|
88
src/ethernet.h
Normal file
88
src/ethernet.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* IPXWrapper - Ethernet frame handling
|
||||
* Copyright (C) 2017 Daniel Collins <solemnwarning@solemnwarning.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* 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., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef IPXWRAPPER_ETHERNET_H
|
||||
#define IPXWRAPPER_ETHERNET_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "addr.h"
|
||||
|
||||
/* An IPX packet in its normal form on the wire */
|
||||
|
||||
#define NOVELL_IPX_PACKET_MAX_PAYLOAD ((uint16_t)(0xFFFF) - sizeof(novell_ipx_packet))
|
||||
|
||||
typedef struct novell_ipx_packet novell_ipx_packet;
|
||||
|
||||
struct novell_ipx_packet {
|
||||
uint16_t checksum;
|
||||
uint16_t length;
|
||||
uint8_t hops;
|
||||
uint8_t type;
|
||||
|
||||
unsigned char dest_net[4];
|
||||
unsigned char dest_node[6];
|
||||
uint16_t dest_socket;
|
||||
|
||||
unsigned char src_net[4];
|
||||
unsigned char src_node[6];
|
||||
uint16_t src_socket;
|
||||
|
||||
unsigned char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
/* This file declares three types of functions:
|
||||
*
|
||||
* XXX_frame_size
|
||||
*
|
||||
* Returns the size of a whole frame and IPX packet with the given number of
|
||||
* bytes of payload.
|
||||
*
|
||||
* Returns zero if the payload is too large to fit in a frame of this format.
|
||||
*
|
||||
* XXX_frame_pack
|
||||
*
|
||||
* Serialises a frame and IPX packet to the given buffer, which must be at
|
||||
* least as large as the size returned by the corresponding XXX_frame_size()
|
||||
* function.
|
||||
*
|
||||
* XXX_frame_unpack
|
||||
*
|
||||
* Deserialises a frame, giving the inner IPX packet and its size. Returns
|
||||
* true on success, false if the frame was invalid.
|
||||
*/
|
||||
|
||||
size_t ethII_frame_size(size_t ipx_payload_len);
|
||||
void ethII_frame_pack(void *frame_buffer,
|
||||
uint8_t type,
|
||||
addr32_t src_net, addr48_t src_node, uint16_t src_socket,
|
||||
addr32_t dest_net, addr48_t dest_node, uint16_t dest_socket,
|
||||
const void *payload, size_t payload_len);
|
||||
bool ethII_frame_unpack(const novell_ipx_packet **packet, size_t *packet_len,
|
||||
const void *frame_data, size_t frame_len);
|
||||
|
||||
size_t novell_frame_size(size_t ipx_payload_len);
|
||||
void novell_frame_pack(void *frame_buffer,
|
||||
uint8_t type,
|
||||
addr32_t src_net, addr48_t src_node, uint16_t src_socket,
|
||||
addr32_t dest_net, addr48_t dest_node, uint16_t dest_socket,
|
||||
const void *payload, size_t payload_len);
|
||||
bool novell_frame_unpack(const novell_ipx_packet **packet, size_t *packet_len,
|
||||
const void *frame_data, size_t frame_len);
|
||||
|
||||
#endif /* !IPXWRAPPER_ETHERNET_H */
|
@ -90,41 +90,6 @@ struct ipx_packet {
|
||||
char data[1];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
typedef struct real_ipx_packet real_ipx_packet_t;
|
||||
|
||||
struct real_ipx_packet {
|
||||
uint16_t checksum;
|
||||
uint16_t length;
|
||||
uint8_t hops;
|
||||
uint8_t type;
|
||||
|
||||
unsigned char dest_net[4];
|
||||
unsigned char dest_node[6];
|
||||
uint16_t dest_socket;
|
||||
|
||||
unsigned char src_net[4];
|
||||
unsigned char src_node[6];
|
||||
uint16_t src_socket;
|
||||
|
||||
unsigned char data[0];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
typedef struct ethernet_frame ethernet_frame_t;
|
||||
|
||||
struct ethernet_frame
|
||||
{
|
||||
unsigned char dest_mac[6];
|
||||
unsigned char src_mac[6];
|
||||
|
||||
union {
|
||||
/* Depends on frame type. */
|
||||
uint16_t ethertype;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
real_ipx_packet_t packet;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define IPX_MAGIC_SPXLOOKUP 1
|
||||
|
||||
typedef struct spxlookup_req spxlookup_req_t;
|
||||
|
88
src/router.c
88
src/router.c
@ -29,6 +29,7 @@
|
||||
#include "ipxwrapper.h"
|
||||
#include "interface.h"
|
||||
#include "addrcache.h"
|
||||
#include "ethernet.h"
|
||||
|
||||
static bool router_running = false;
|
||||
static WSAEVENT router_event = WSA_INVALID_EVENT;
|
||||
@ -497,67 +498,42 @@ static void _handle_pcap_frame(u_char *user, const struct pcap_pkthdr *pkt_heade
|
||||
{
|
||||
ipx_interface_t *iface = (ipx_interface_t*)(user);
|
||||
|
||||
if(pkt_header->caplen < sizeof(ethernet_frame_t))
|
||||
const novell_ipx_packet *ipx;
|
||||
size_t ipx_len;
|
||||
|
||||
switch(main_config.frame_type)
|
||||
{
|
||||
/* Frame isn't big enough to contain a full IPX header. */
|
||||
return;
|
||||
case FRAME_TYPE_ETH_II:
|
||||
if(!ethII_frame_unpack(&ipx, &ipx_len, pkt_data, pkt_header->caplen))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FRAME_TYPE_NOVELL:
|
||||
if(!novell_frame_unpack(&ipx, &ipx_len, pkt_data, pkt_header->caplen))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ethernet_frame_t *frame = (ethernet_frame_t*)(pkt_data);
|
||||
|
||||
uint16_t ipx_packet_len = ntohs(frame->packet.length);
|
||||
|
||||
if(main_config.frame_type == FRAME_TYPE_ETH_II)
|
||||
{
|
||||
/* 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)
|
||||
if(ipx->checksum != 0xFFFF)
|
||||
{
|
||||
/* The "checksum" field doesn't have the magic IPX value. */
|
||||
return;
|
||||
}
|
||||
|
||||
if(ipx_packet_len > (pkt_header->caplen - (sizeof(*frame) - sizeof(frame->packet))))
|
||||
if(ntohs(ipx->length) > ipx_len)
|
||||
{
|
||||
/* The "length" field in the IPX header is too big. */
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
addr48_t dest = addr48_in(frame->packet.dest_node);
|
||||
addr48_t dest = addr48_in(ipx->dest_node);
|
||||
addr48_t bcast = addr48_in((unsigned char[]){0xFF,0xFF,0xFF,0xFF,0xFF,0xFF});
|
||||
|
||||
if(dest != iface->mac_addr && dest != bcast)
|
||||
@ -569,17 +545,17 @@ static void _handle_pcap_frame(u_char *user, const struct pcap_pkthdr *pkt_heade
|
||||
}
|
||||
}
|
||||
|
||||
_deliver_packet(frame->packet.type,
|
||||
addr32_in(frame->packet.src_net),
|
||||
addr48_in(frame->packet.src_node),
|
||||
frame->packet.src_socket,
|
||||
_deliver_packet(ipx->type,
|
||||
addr32_in(ipx->src_net),
|
||||
addr48_in(ipx->src_node),
|
||||
ipx->src_socket,
|
||||
|
||||
addr32_in(frame->packet.dest_net),
|
||||
addr48_in(frame->packet.dest_node),
|
||||
frame->packet.dest_socket,
|
||||
addr32_in(ipx->dest_net),
|
||||
addr48_in(ipx->dest_node),
|
||||
ipx->dest_socket,
|
||||
|
||||
frame->packet.data,
|
||||
(ntohs(frame->packet.length) - sizeof(real_ipx_packet_t)));
|
||||
ipx->data,
|
||||
(ntohs(ipx->length) - sizeof(novell_ipx_packet)));
|
||||
}
|
||||
|
||||
static DWORD router_main(void *arg)
|
||||
|
118
src/winsock.c
118
src/winsock.c
@ -29,6 +29,7 @@
|
||||
#include "interface.h"
|
||||
#include "router.h"
|
||||
#include "addrcache.h"
|
||||
#include "ethernet.h"
|
||||
|
||||
struct sockaddr_ipx_ext {
|
||||
short sa_family;
|
||||
@ -49,9 +50,22 @@ static size_t strsize(void *str, bool unicode)
|
||||
|
||||
static int _max_ipx_payload(void)
|
||||
{
|
||||
return ipx_use_pcap
|
||||
? (ETHERNET_MTU - sizeof(real_ipx_packet_t))
|
||||
: MAX_DATA_SIZE;
|
||||
if(ipx_use_pcap)
|
||||
{
|
||||
/* TODO: Use real interface MTU */
|
||||
|
||||
switch(main_config.frame_type)
|
||||
{
|
||||
case FRAME_TYPE_ETH_II:
|
||||
case FRAME_TYPE_NOVELL:
|
||||
return 1500 - (14 + sizeof(novell_ipx_packet));
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
else{
|
||||
return MAX_DATA_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
#define PUSH_NAME(name) \
|
||||
@ -1198,64 +1212,64 @@ static DWORD ipx_send_packet(
|
||||
ipx_interface_t *iface = ipx_interface_by_addr(src_net, src_node);
|
||||
if(iface)
|
||||
{
|
||||
size_t packet_size = sizeof(real_ipx_packet_t) + data_size;
|
||||
size_t frame_size = sizeof(ethernet_frame_t) + data_size;
|
||||
ethernet_frame_t *frame = malloc(frame_size);
|
||||
/* Calculate the frame size and check we can actually
|
||||
* fit this much data in it.
|
||||
*/
|
||||
|
||||
size_t frame_size;
|
||||
|
||||
switch(main_config.frame_type)
|
||||
{
|
||||
case FRAME_TYPE_ETH_II:
|
||||
frame_size = ethII_frame_size(data_size);
|
||||
break;
|
||||
|
||||
case FRAME_TYPE_NOVELL:
|
||||
frame_size = novell_frame_size(data_size);
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: Check frame_size against interface MTU */
|
||||
|
||||
if(frame_size == 0)
|
||||
{
|
||||
log_printf(LOG_ERROR,
|
||||
"Tried sending a %u byte packet, too large for the selected frame type",
|
||||
(unsigned int)(data_size));
|
||||
|
||||
return WSAEMSGSIZE;
|
||||
}
|
||||
|
||||
log_printf(LOG_DEBUG, "...frame size = %u", (unsigned int)(frame_size));
|
||||
|
||||
/* Serialise the frame. */
|
||||
|
||||
void *frame = malloc(frame_size);
|
||||
if(!frame)
|
||||
{
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if(main_config.frame_type == FRAME_TYPE_ETH_II)
|
||||
switch(main_config.frame_type)
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
case FRAME_TYPE_ETH_II:
|
||||
ethII_frame_pack(frame,
|
||||
type,
|
||||
src_net, src_node, src_socket,
|
||||
dest_net, dest_node, dest_socket,
|
||||
data, data_size);
|
||||
break;
|
||||
|
||||
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();
|
||||
case FRAME_TYPE_NOVELL:
|
||||
novell_frame_pack(frame,
|
||||
type,
|
||||
src_net, src_node, src_socket,
|
||||
dest_net, dest_node, dest_socket,
|
||||
data, data_size);
|
||||
break;
|
||||
}
|
||||
|
||||
frame->packet.checksum = 0xFFFF;
|
||||
frame->packet.length = htons(packet_size);
|
||||
frame->packet.hops = 0;
|
||||
frame->packet.type = type;
|
||||
|
||||
addr32_out(frame->packet.dest_net, dest_net);
|
||||
addr48_out(frame->packet.dest_node, dest_node);
|
||||
frame->packet.dest_socket = dest_socket;
|
||||
|
||||
addr32_out(frame->packet.src_net, src_net);
|
||||
addr48_out(frame->packet.src_node, src_node);
|
||||
frame->packet.src_socket = src_socket;
|
||||
|
||||
memcpy(frame->packet.data, data, data_size);
|
||||
/* Transmit the frame. */
|
||||
|
||||
if(pcap_sendpacket(iface->pcap, (void*)(frame), frame_size) == 0)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user