network: Do not apply ethernet headers for loopback devices.
This reverts large portions ofe2b57695fc
and all of4e9653027d
, and adjusts the "tunnel" and "loopback_frame" handlers appropriately. Initially, this logic was added so that libpcap continued working; however, it seems that we can change some of the Haiku-specific code in libpcap and have it continue to operate without requiring such ethernet headers to be appended. Fixes #18801. Change-Id: Ie06908affde894ad1516fbc27e06298309a4e082 Reviewed-on: https://review.haiku-os.org/c/haiku/+/7403 Reviewed-by: Alex von Gluck IV <kallisti5@unixzen.com> Reviewed-by: Jérôme Duval <jerome.duval@gmail.com> Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
23cfed803a
commit
98166ebe04
@ -35,10 +35,6 @@ status_t
|
||||
loopback_deframe(net_device* device, net_buffer* buffer)
|
||||
{
|
||||
// there is not that much to do...
|
||||
NetBufferHeaderRemover<ether_header> bufferHeader(buffer);
|
||||
if (bufferHeader.Status() != B_OK)
|
||||
return bufferHeader.Status();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -69,7 +65,7 @@ loopback_frame_init(struct net_interface*interface, net_domain* domain,
|
||||
// buffer reception is handled internally.
|
||||
} else if (interface->device->type == IFT_TUNNEL) {
|
||||
status = stack->register_domain_device_handler(
|
||||
interface->device, B_NET_FRAME_TYPE(IFT_ETHER, ETHER_TYPE_IP), domain);
|
||||
interface->device, B_NET_FRAME_TYPE_IPV4, domain);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
}
|
||||
@ -111,37 +107,6 @@ loopback_frame_uninit(net_datalink_protocol* protocol)
|
||||
status_t
|
||||
loopback_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer)
|
||||
{
|
||||
// Packet capture expects ethernet frames, so we apply framing
|
||||
// (and deframing) even for loopback packets.
|
||||
|
||||
NetBufferPrepend<ether_header> bufferHeader(buffer);
|
||||
if (bufferHeader.Status() != B_OK)
|
||||
return bufferHeader.Status();
|
||||
|
||||
ether_header &header = bufferHeader.Data();
|
||||
|
||||
int family;
|
||||
if (buffer->interface_address != NULL)
|
||||
family = buffer->interface_address->domain->family;
|
||||
else
|
||||
family = buffer->destination->sa_family;
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
header.type = B_HOST_TO_BENDIAN_INT16(ETHER_TYPE_IP);
|
||||
break;
|
||||
case AF_INET6:
|
||||
header.type = B_HOST_TO_BENDIAN_INT16(ETHER_TYPE_IPV6);
|
||||
break;
|
||||
default:
|
||||
header.type = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(header.source, 0, ETHER_ADDRESS_LENGTH);
|
||||
memset(header.destination, 0, ETHER_ADDRESS_LENGTH);
|
||||
bufferHeader.Sync();
|
||||
|
||||
return protocol->next->module->send_data(protocol->next, buffer);
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <net_buffer.h>
|
||||
#include <net_device.h>
|
||||
#include <net_stack.h>
|
||||
#include <NetBufferUtilities.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
@ -163,14 +162,8 @@ tunnel_read(void* _cookie, off_t position, void* data, size_t* _length)
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
size_t offset = 0;
|
||||
if (!cookie->device->is_tap) {
|
||||
// TUN: Skip ethernet header.
|
||||
offset = ETHER_HEADER_LENGTH;
|
||||
}
|
||||
|
||||
const size_t length = min_c(*_length, buffer->size - offset);
|
||||
status = gBufferModule->read(buffer, offset, data, length);
|
||||
const size_t length = min_c(*_length, buffer->size);
|
||||
status = gBufferModule->read(buffer, 0, data, length);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
*_length = length;
|
||||
@ -196,7 +189,7 @@ tunnel_write(void* _cookie, off_t position, const void* data, size_t* _length)
|
||||
}
|
||||
|
||||
if (!cookie->device->is_tap) {
|
||||
// TUN: Detect packet type and prepend ethernet header.
|
||||
// TUN: Detect packet type.
|
||||
uint8 version;
|
||||
status = gBufferModule->read(buffer, 0, &version, 1);
|
||||
if (status != B_OK) {
|
||||
@ -213,30 +206,12 @@ tunnel_write(void* _cookie, off_t position, const void* data, size_t* _length)
|
||||
buffer->type = (version == 6) ? B_NET_FRAME_TYPE_IPV6
|
||||
: B_NET_FRAME_TYPE_IPV4;
|
||||
|
||||
NetBufferPrepend<ether_header> bufferHeader(buffer);
|
||||
if (bufferHeader.Status() != B_OK) {
|
||||
gBufferModule->free(buffer);
|
||||
return bufferHeader.Status();
|
||||
}
|
||||
|
||||
ether_header &header = bufferHeader.Data();
|
||||
header.type = (version == 6) ? htons(ETHER_TYPE_IPV6)
|
||||
: htons(ETHER_TYPE_IP);
|
||||
|
||||
memset(header.source, 0, ETHER_ADDRESS_LENGTH);
|
||||
memset(header.destination, 0, ETHER_ADDRESS_LENGTH);
|
||||
bufferHeader.Sync();
|
||||
|
||||
// At least sdl_type and sdl_e_type must be set.
|
||||
struct sockaddr_dl& src = *(struct sockaddr_dl*)buffer->source;
|
||||
struct sockaddr_dl& dst = *(struct sockaddr_dl*)buffer->destination;
|
||||
src.sdl_len = dst.sdl_len = sizeof(sockaddr_dl);
|
||||
src.sdl_family = dst.sdl_family = AF_LINK;
|
||||
src.sdl_index = dst.sdl_index = cookie->device->index;
|
||||
src.sdl_type = dst.sdl_type = IFT_ETHER;
|
||||
src.sdl_e_type = dst.sdl_e_type = header.type;
|
||||
src.sdl_nlen = src.sdl_slen = dst.sdl_nlen = dst.sdl_slen = 0;
|
||||
src.sdl_alen = dst.sdl_alen = 0;
|
||||
struct sockaddr_in& src = *(struct sockaddr_in*)buffer->source;
|
||||
struct sockaddr_in& dst = *(struct sockaddr_in*)buffer->destination;
|
||||
src.sin_len = dst.sin_len = sizeof(sockaddr_in);
|
||||
src.sin_family = dst.sin_family = (version == 6) ? AF_INET6 : AF_INET;
|
||||
src.sin_port = dst.sin_port = 0;
|
||||
src.sin_addr.s_addr = dst.sin_addr.s_addr = 0;
|
||||
}
|
||||
|
||||
// We use a queue and the receive_data() hook instead of device_enqueue_buffer()
|
||||
@ -448,13 +423,8 @@ tunnel_send_data(net_device* _device, net_buffer* buffer)
|
||||
status_t status = B_OK;
|
||||
if (!device->is_tap) {
|
||||
// Ensure this is an IP frame.
|
||||
uint16 type;
|
||||
status = gBufferModule->read(buffer, offsetof(ether_header, type),
|
||||
&type, sizeof(type));
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
if (type != htons(ETHER_TYPE_IP) && type != htons(ETHER_TYPE_IPV6))
|
||||
struct sockaddr_in& dst = *(struct sockaddr_in*)buffer->destination;
|
||||
if (dst.sin_family != AF_INET && dst.sin_family != AF_INET6)
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
|
@ -18,17 +18,14 @@
|
||||
#include <string.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
#include <ByteOrder.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <net_datalink.h>
|
||||
#include <net_device.h>
|
||||
#include <NetBufferUtilities.h>
|
||||
#include <NetUtilities.h>
|
||||
|
||||
#include "device_interfaces.h"
|
||||
#include "domains.h"
|
||||
#include "ethernet.h"
|
||||
#include "interfaces.h"
|
||||
#include "routes.h"
|
||||
#include "stack_private.h"
|
||||
@ -394,36 +391,8 @@ datalink_send_routed_data(struct net_route* route, net_buffer* buffer)
|
||||
address->AcquireReference();
|
||||
set_interface_address(buffer->interface_address, address);
|
||||
|
||||
if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0) {
|
||||
{
|
||||
NetBufferPrepend<ether_header,StackNetBufferModuleGetter> bufferHeader(buffer);
|
||||
if (bufferHeader.Status() != B_OK)
|
||||
return bufferHeader.Status();
|
||||
|
||||
ether_header &header = bufferHeader.Data();
|
||||
switch (buffer->interface_address->domain->family) {
|
||||
case AF_INET:
|
||||
header.type = B_HOST_TO_BENDIAN_INT16(ETHER_TYPE_IP);
|
||||
break;
|
||||
case AF_INET6:
|
||||
header.type = B_HOST_TO_BENDIAN_INT16(ETHER_TYPE_IPV6);
|
||||
break;
|
||||
default:
|
||||
header.type = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(header.source, 0, ETHER_ADDRESS_LENGTH);
|
||||
memset(header.destination, 0, ETHER_ADDRESS_LENGTH);
|
||||
bufferHeader.Sync();
|
||||
}
|
||||
if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0)
|
||||
device_interface_monitor_receive(interface->DeviceInterface(), buffer);
|
||||
{
|
||||
NetBufferHeaderRemover<ether_header,StackNetBufferModuleGetter> bufferHeader(buffer);
|
||||
if (bufferHeader.Status() != B_OK)
|
||||
return bufferHeader.Status();
|
||||
}
|
||||
}
|
||||
|
||||
// this one goes back to the domain directly
|
||||
const size_t packetSize = buffer->size;
|
||||
|
@ -56,10 +56,4 @@ status_t init_stack();
|
||||
status_t uninit_stack();
|
||||
|
||||
|
||||
class StackNetBufferModuleGetter {
|
||||
public:
|
||||
static net_buffer_module_info *Get() { return &gNetBufferModule; }
|
||||
};
|
||||
|
||||
|
||||
#endif // STACK_PRIVATE_H
|
||||
|
Loading…
Reference in New Issue
Block a user