network: Do not apply ethernet headers for loopback devices.

This reverts large portions of e2b57695fc
and all of 4e9653027d, 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:
Augustin Cavalier 2024-02-15 09:53:00 -05:00 committed by waddlesplash
parent 23cfed803a
commit 98166ebe04
4 changed files with 13 additions and 115 deletions

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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