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) loopback_deframe(net_device* device, net_buffer* buffer)
{ {
// there is not that much to do... // there is not that much to do...
NetBufferHeaderRemover<ether_header> bufferHeader(buffer);
if (bufferHeader.Status() != B_OK)
return bufferHeader.Status();
return B_OK; return B_OK;
} }
@ -69,7 +65,7 @@ loopback_frame_init(struct net_interface*interface, net_domain* domain,
// buffer reception is handled internally. // buffer reception is handled internally.
} else if (interface->device->type == IFT_TUNNEL) { } else if (interface->device->type == IFT_TUNNEL) {
status = stack->register_domain_device_handler( 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) if (status != B_OK)
return status; return status;
} }
@ -111,37 +107,6 @@ loopback_frame_uninit(net_datalink_protocol* protocol)
status_t status_t
loopback_frame_send_data(net_datalink_protocol* protocol, net_buffer* buffer) 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); return protocol->next->module->send_data(protocol->next, buffer);
} }

View File

@ -19,7 +19,6 @@
#include <net_buffer.h> #include <net_buffer.h>
#include <net_device.h> #include <net_device.h>
#include <net_stack.h> #include <net_stack.h>
#include <NetBufferUtilities.h>
#include <net/if.h> #include <net/if.h>
#include <net/if_dl.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) if (status != B_OK)
return status; return status;
size_t offset = 0; const size_t length = min_c(*_length, buffer->size);
if (!cookie->device->is_tap) { status = gBufferModule->read(buffer, 0, data, length);
// 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);
if (status != B_OK) if (status != B_OK)
return status; return status;
*_length = length; *_length = length;
@ -196,7 +189,7 @@ tunnel_write(void* _cookie, off_t position, const void* data, size_t* _length)
} }
if (!cookie->device->is_tap) { if (!cookie->device->is_tap) {
// TUN: Detect packet type and prepend ethernet header. // TUN: Detect packet type.
uint8 version; uint8 version;
status = gBufferModule->read(buffer, 0, &version, 1); status = gBufferModule->read(buffer, 0, &version, 1);
if (status != B_OK) { 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 buffer->type = (version == 6) ? B_NET_FRAME_TYPE_IPV6
: B_NET_FRAME_TYPE_IPV4; : B_NET_FRAME_TYPE_IPV4;
NetBufferPrepend<ether_header> bufferHeader(buffer); struct sockaddr_in& src = *(struct sockaddr_in*)buffer->source;
if (bufferHeader.Status() != B_OK) { struct sockaddr_in& dst = *(struct sockaddr_in*)buffer->destination;
gBufferModule->free(buffer); src.sin_len = dst.sin_len = sizeof(sockaddr_in);
return bufferHeader.Status(); 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;
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;
} }
// We use a queue and the receive_data() hook instead of device_enqueue_buffer() // 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; status_t status = B_OK;
if (!device->is_tap) { if (!device->is_tap) {
// Ensure this is an IP frame. // Ensure this is an IP frame.
uint16 type; struct sockaddr_in& dst = *(struct sockaddr_in*)buffer->destination;
status = gBufferModule->read(buffer, offsetof(ether_header, type), if (dst.sin_family != AF_INET && dst.sin_family != AF_INET6)
&type, sizeof(type));
if (status != B_OK)
return status;
if (type != htons(ETHER_TYPE_IP) && type != htons(ETHER_TYPE_IPV6))
return B_BAD_DATA; return B_BAD_DATA;
} }

View File

@ -18,17 +18,14 @@
#include <string.h> #include <string.h>
#include <sys/sockio.h> #include <sys/sockio.h>
#include <ByteOrder.h>
#include <KernelExport.h> #include <KernelExport.h>
#include <net_datalink.h> #include <net_datalink.h>
#include <net_device.h> #include <net_device.h>
#include <NetBufferUtilities.h>
#include <NetUtilities.h> #include <NetUtilities.h>
#include "device_interfaces.h" #include "device_interfaces.h"
#include "domains.h" #include "domains.h"
#include "ethernet.h"
#include "interfaces.h" #include "interfaces.h"
#include "routes.h" #include "routes.h"
#include "stack_private.h" #include "stack_private.h"
@ -394,36 +391,8 @@ datalink_send_routed_data(struct net_route* route, net_buffer* buffer)
address->AcquireReference(); address->AcquireReference();
set_interface_address(buffer->interface_address, address); set_interface_address(buffer->interface_address, address);
if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0) { 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();
}
device_interface_monitor_receive(interface->DeviceInterface(), buffer); 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 // this one goes back to the domain directly
const size_t packetSize = buffer->size; const size_t packetSize = buffer->size;

View File

@ -56,10 +56,4 @@ status_t init_stack();
status_t uninit_stack(); status_t uninit_stack();
class StackNetBufferModuleGetter {
public:
static net_buffer_module_info *Get() { return &gNetBufferModule; }
};
#endif // STACK_PRIVATE_H #endif // STACK_PRIVATE_H