Moved ethernet and loopback "interface" module to new net_layer API.
Added an skeleton arp net layer. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3808 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,129 @@
|
|||||||
|
/* ethernet.c - ethernet devices interface module
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <Drivers.h>
|
||||||
|
|
||||||
|
#include "net_stack.h"
|
||||||
|
#include "net_layer.h"
|
||||||
|
|
||||||
|
status_t std_ops(int32 op, ...);
|
||||||
|
|
||||||
|
struct net_layer_module_info nlmi;
|
||||||
|
|
||||||
|
static struct net_stack_module_info *g_stack = NULL;
|
||||||
|
|
||||||
|
// -------------------
|
||||||
|
status_t init(void * params)
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
net_layer *layer1, *layer2;
|
||||||
|
|
||||||
|
layer2 = NULL;
|
||||||
|
status = B_NO_MEMORY;
|
||||||
|
|
||||||
|
layer1 = malloc(sizeof(*layer1));
|
||||||
|
if (!layer1)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
layer1->name = "ethernet/arp";
|
||||||
|
layer1->module = &nlmi;
|
||||||
|
|
||||||
|
layer2 = malloc(sizeof(*layer2));
|
||||||
|
if (!layer2)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
layer2->name = "arp/ethernet";
|
||||||
|
layer2->module = &nlmi;
|
||||||
|
|
||||||
|
status = g_stack->register_layer(layer1);
|
||||||
|
return g_stack->register_layer(layer2);
|
||||||
|
|
||||||
|
error:;
|
||||||
|
if (layer1)
|
||||||
|
free(layer1);
|
||||||
|
if (layer2)
|
||||||
|
free(layer2);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t uninit(net_layer *me)
|
||||||
|
{
|
||||||
|
printf("%s: uniniting layer\n", me->name);
|
||||||
|
|
||||||
|
free(me);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t enable(net_layer *me, bool enable)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t input_buffer(net_layer *me, net_buffer *buffer)
|
||||||
|
{
|
||||||
|
if (!buffer)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
// TODO!
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t output_buffer(net_layer *me, net_buffer *buffer)
|
||||||
|
{
|
||||||
|
if (!buffer)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
// TODO!
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
status_t std_ops(int32 op, ...)
|
||||||
|
{
|
||||||
|
switch(op) {
|
||||||
|
case B_MODULE_INIT:
|
||||||
|
printf("arp: B_MODULE_INIT\n");
|
||||||
|
return get_module(NET_STACK_MODULE_NAME, (module_info **) &g_stack);
|
||||||
|
|
||||||
|
case B_MODULE_UNINIT:
|
||||||
|
printf("arp: B_MODULE_UNINIT\n");
|
||||||
|
put_module(NET_STACK_MODULE_NAME);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct net_layer_module_info nlmi = {
|
||||||
|
{
|
||||||
|
NET_LAYER_MODULE_ROOT "protocols/arp/v0",
|
||||||
|
0,
|
||||||
|
std_ops
|
||||||
|
},
|
||||||
|
|
||||||
|
init,
|
||||||
|
uninit,
|
||||||
|
enable,
|
||||||
|
output_buffer,
|
||||||
|
input_buffer
|
||||||
|
};
|
||||||
|
|
||||||
|
_EXPORT module_info *modules[] = {
|
||||||
|
(module_info*) &nlmi, // net_layer_module_info
|
||||||
|
NULL
|
||||||
|
};
|
||||||
Binary file not shown.
@@ -5,14 +5,16 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <sys/dirent.h>
|
#include <sys/dirent.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
#include <Drivers.h>
|
#include <Drivers.h>
|
||||||
|
|
||||||
#include "net_stack.h"
|
#include "net_stack.h"
|
||||||
#include "net_interface.h"
|
#include "net_layer.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ETHER_GETADDR = B_DEVICE_OP_CODES_END,
|
ETHER_GETADDR = B_DEVICE_OP_CODES_END,
|
||||||
@@ -24,11 +26,12 @@ enum {
|
|||||||
ETHER_GETFRAMESIZE
|
ETHER_GETFRAMESIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ethernet_interface {
|
typedef struct ethernet_device_layer {
|
||||||
ifnet_t ifnet;
|
net_layer layer;
|
||||||
int fd;
|
int fd;
|
||||||
int max_frame_size;
|
int max_frame_size;
|
||||||
} ethernet_interface;
|
volatile thread_id reader_thread;
|
||||||
|
} ethernet_device_layer;
|
||||||
|
|
||||||
#define ETHER_ADDR_LEN 6 /* Ethernet address length */
|
#define ETHER_ADDR_LEN 6 /* Ethernet address length */
|
||||||
#define ETHER_TYPE_LEN 2 /* Ethernet type field length */
|
#define ETHER_TYPE_LEN 2 /* Ethernet type field length */
|
||||||
@@ -46,9 +49,10 @@ typedef struct ether_addr {
|
|||||||
|
|
||||||
status_t lookup_devices(char *root, void *cookie);
|
status_t lookup_devices(char *root, void *cookie);
|
||||||
status_t register_device(const char *path, void *cookie);
|
status_t register_device(const char *path, void *cookie);
|
||||||
|
status_t device_reader(void *args);
|
||||||
status_t std_ops(int32 op, ...);
|
status_t std_ops(int32 op, ...);
|
||||||
|
|
||||||
struct net_interface_module_info nimi;
|
struct net_layer_module_info nlmi;
|
||||||
|
|
||||||
static struct net_stack_module_info *g_stack = NULL;
|
static struct net_stack_module_info *g_stack = NULL;
|
||||||
|
|
||||||
@@ -59,92 +63,79 @@ status_t init(void * params)
|
|||||||
return lookup_devices("/dev/net", params);
|
return lookup_devices("/dev/net", params);
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t uninit(ifnet_t *iface)
|
status_t uninit(net_layer *me)
|
||||||
{
|
{
|
||||||
ethernet_interface *ei = (ethernet_interface *) iface;
|
ethernet_device_layer *edl = (ethernet_device_layer *) me;
|
||||||
|
|
||||||
printf("ethernet: uniniting %s interface\n", iface->if_name);
|
printf("%s: uniniting layer\n", me->name);
|
||||||
|
|
||||||
free(iface->if_name);
|
close(edl->fd);
|
||||||
close(ei->fd);
|
|
||||||
|
free(me->name);
|
||||||
|
free(me);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t up(ifnet_t *iface)
|
status_t enable(net_layer *me, bool enable)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
ethernet_device_layer *edl = (ethernet_device_layer *) me;
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
// enable this layer
|
||||||
|
thread_id tid;
|
||||||
|
char name[B_OS_NAME_LENGTH * 2];
|
||||||
|
|
||||||
|
if (edl->reader_thread != -1)
|
||||||
|
// already up
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
strncpy(name, me->name, sizeof(name));
|
||||||
|
strncat(name, " reader", sizeof(name));
|
||||||
|
tid = spawn_kernel_thread(device_reader, name, B_NORMAL_PRIORITY, me);
|
||||||
|
if (tid < 0) {
|
||||||
|
printf("%s: failed to start device reader thread -> %d [%s]\n",
|
||||||
|
me->name, (int) tid, strerror(tid));
|
||||||
|
return tid;
|
||||||
|
};
|
||||||
|
|
||||||
|
edl->reader_thread = tid;
|
||||||
|
return resume_thread(tid);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
status_t dummy;
|
||||||
|
|
||||||
|
// disable this layer
|
||||||
|
if (edl->reader_thread == -1)
|
||||||
|
// already down
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
send_signal_etc(edl->reader_thread, SIGTERM, 0);
|
||||||
|
wait_for_thread(edl->reader_thread, &dummy);
|
||||||
|
printf("%s: device reader stopped.\n", me->name);
|
||||||
|
edl->reader_thread = -1;
|
||||||
|
return B_OK;
|
||||||
|
};
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t down(ifnet_t *iface)
|
status_t output_buffer(net_layer *me, net_buffer *buffer)
|
||||||
{
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t send(ifnet_t *iface, net_buffer *buffer)
|
|
||||||
{
|
{
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
// TODO!
|
// TODO!
|
||||||
return B_OK;
|
printf("%s: output_buffer:\n", me->name);
|
||||||
}
|
g_stack->dump_buffer(buffer);
|
||||||
|
|
||||||
|
|
||||||
status_t receive(ifnet_t *iface, net_buffer **received_buffer)
|
|
||||||
{
|
|
||||||
ethernet_interface *ei = (ethernet_interface *) iface;
|
|
||||||
net_buffer *buffer;
|
|
||||||
void *frame;
|
|
||||||
size_t len;
|
|
||||||
ssize_t sz;
|
|
||||||
|
|
||||||
len = iface->if_mtu;
|
|
||||||
frame = malloc(len);
|
|
||||||
if (!frame)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
buffer = g_stack->new_buffer();
|
|
||||||
if (!buffer) {
|
|
||||||
free(frame);
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
};
|
|
||||||
|
|
||||||
sz = read(ei->fd, frame, len);
|
|
||||||
if (sz >= B_OK) {
|
|
||||||
g_stack->add_to_buffer(buffer, 0, frame, sz, (buffer_chunk_free_func) free);
|
|
||||||
*received_buffer = buffer;
|
|
||||||
return sz;
|
|
||||||
};
|
|
||||||
|
|
||||||
free(frame);
|
|
||||||
g_stack->delete_buffer(buffer, false);
|
g_stack->delete_buffer(buffer, false);
|
||||||
return sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t control(ifnet_t *iface, int opcode, void *arg) { return -1; }
|
|
||||||
|
|
||||||
status_t get_hardware_address(ifnet_t *iface, net_interface_hwaddr *hwaddr) { return -1; }
|
|
||||||
status_t get_multicast_addresses(ifnet_t *iface, net_interface_hwaddr **hwaddr, int nb_addresses) { return -1; }
|
|
||||||
status_t set_multicast_addresses(ifnet_t *iface, net_interface_hwaddr *hwaddr, int nb_addresses) { return -1; }
|
|
||||||
|
|
||||||
status_t set_mtu(ifnet_t *iface, uint32 mtu)
|
|
||||||
{
|
|
||||||
ethernet_interface *ei = (ethernet_interface *) iface;
|
|
||||||
|
|
||||||
if (mtu > ei->max_frame_size)
|
|
||||||
// hardware constraint always win!
|
|
||||||
mtu = ei->max_frame_size;
|
|
||||||
|
|
||||||
ei->ifnet.if_mtu = mtu;
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t set_promiscuous(ifnet_t *iface, bool enable) { return -1; }
|
|
||||||
status_t set_media(ifnet_t *iface, uint32 media) { return -1; }
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
@@ -178,8 +169,9 @@ status_t lookup_devices(char *root, void *cookie)
|
|||||||
if (S_ISDIR(st.st_mode))
|
if (S_ISDIR(st.st_mode))
|
||||||
status = lookup_devices(path, cookie);
|
status = lookup_devices(path, cookie);
|
||||||
else if (S_ISCHR(st.st_mode)) { // char device = driver!
|
else if (S_ISCHR(st.st_mode)) { // char device = driver!
|
||||||
if (strcmp(de->d_name, "stack") == 0 || // OBOS stack driver
|
if (strcmp(de->d_name, "stack") == 0 || // OBOS stack driver
|
||||||
strcmp(de->d_name, "api") == 0) // BONE stack driver
|
strcmp(de->d_name, "server") == 0 || // OBOS server driver
|
||||||
|
strcmp(de->d_name, "api") == 0) // BONE stack driver
|
||||||
continue; // skip pseudo-entries
|
continue; // skip pseudo-entries
|
||||||
|
|
||||||
status = register_device(path, cookie);
|
status = register_device(path, cookie);
|
||||||
@@ -194,16 +186,16 @@ status_t lookup_devices(char *root, void *cookie)
|
|||||||
|
|
||||||
status_t register_device(const char *path, void *cookie)
|
status_t register_device(const char *path, void *cookie)
|
||||||
{
|
{
|
||||||
ifnet_t *iface;
|
ethernet_device_layer *edl;
|
||||||
ethernet_interface *ei;
|
|
||||||
int frame_size;
|
int frame_size;
|
||||||
ether_addr_t mac_address;
|
ether_addr_t mac_address;
|
||||||
int fd;
|
int fd;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
char *name;
|
||||||
|
|
||||||
fd = open(path, O_RDWR);
|
fd = open(path, O_RDWR);
|
||||||
if (fd < B_OK) {
|
if (fd < B_OK) {
|
||||||
printf("ethernet: Unable to open(%s) -> %d [%s]. Skipping...\n", path,
|
printf("ethernet: Unable to open %s device -> %d [%s]. Skipping...\n", path,
|
||||||
fd, strerror(fd));
|
fd, strerror(fd));
|
||||||
return fd;
|
return fd;
|
||||||
};
|
};
|
||||||
@@ -211,7 +203,7 @@ status_t register_device(const char *path, void *cookie)
|
|||||||
// Init the network card
|
// Init the network card
|
||||||
status = ioctl(fd, ETHER_INIT, NULL, 0);
|
status = ioctl(fd, ETHER_INIT, NULL, 0);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
printf("ethernet: Failed to init %s: %ld [%s]. Skipping...\n", path,
|
printf("ethernet: Failed to init %s device -> %ld [%s]. Skipping...\n", path,
|
||||||
status, strerror(status));
|
status, strerror(status));
|
||||||
close(fd);
|
close(fd);
|
||||||
return status;
|
return status;
|
||||||
@@ -220,7 +212,7 @@ status_t register_device(const char *path, void *cookie)
|
|||||||
// get the MAC address...
|
// get the MAC address...
|
||||||
status = ioctl(fd, ETHER_GETADDR, &mac_address, 6);
|
status = ioctl(fd, ETHER_GETADDR, &mac_address, 6);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
printf("ethernet: Failed to get %s MAC address: %ld [%s]. Skipping...\n",
|
printf("ethernet: Failed to get %s device MAC address -> %ld [%s]. Skipping...\n",
|
||||||
path, status, strerror(status));
|
path, status, strerror(status));
|
||||||
close(fd);
|
close(fd);
|
||||||
return status;
|
return status;
|
||||||
@@ -230,37 +222,79 @@ status_t register_device(const char *path, void *cookie)
|
|||||||
status = ioctl(fd, ETHER_GETFRAMESIZE, &frame_size, sizeof(frame_size));
|
status = ioctl(fd, ETHER_GETFRAMESIZE, &frame_size, sizeof(frame_size));
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
frame_size = ETHERMTU;
|
frame_size = ETHERMTU;
|
||||||
printf("ethernet: %s device don't support IF_GETFRAMESIZE; defaulting to %d\n",
|
printf("ethernet: %s device don't support ETHER_GETFRAMESIZE; defaulting to %d\n",
|
||||||
path, frame_size);
|
path, frame_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
printf("ethernet: interface '%s':\n"
|
printf("ethernet: Found device '%s': MAC address: %02x:%02x:%02x:%02x:%02x:%02x, MTU: %d bytes\n",
|
||||||
"\tMAC address: %02x:%02x:%02x:%02x:%02x:%02x\n"
|
|
||||||
"\tMTU: %d bytes\n",
|
|
||||||
path,
|
path,
|
||||||
mac_address.byte[0], mac_address.byte[1],
|
mac_address.byte[0], mac_address.byte[1],
|
||||||
mac_address.byte[2], mac_address.byte[3],
|
mac_address.byte[2], mac_address.byte[3],
|
||||||
mac_address.byte[4], mac_address.byte[5], frame_size);
|
mac_address.byte[4], mac_address.byte[5], frame_size);
|
||||||
|
|
||||||
ei = (ethernet_interface *) malloc(sizeof(*ei));
|
edl = malloc(sizeof(*edl));
|
||||||
if (!ei) {
|
if (!edl) {
|
||||||
close(fd);
|
close(fd);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
};
|
};
|
||||||
|
|
||||||
ei->fd = fd;
|
edl->fd = fd;
|
||||||
ei->max_frame_size = frame_size;
|
edl->max_frame_size = frame_size;
|
||||||
|
edl->reader_thread = -1;
|
||||||
|
|
||||||
iface = &ei->ifnet;
|
name = malloc(strlen("ethernet/") + strlen(path));
|
||||||
|
strcpy(name, "ethernet/");
|
||||||
|
strcat(name, path + strlen("/dev/net/"));
|
||||||
|
|
||||||
iface->if_name = strdup(path);
|
edl->layer.name = name;
|
||||||
iface->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
|
edl->layer.module = &nlmi;
|
||||||
iface->if_type = 0x20; // IFT_ETHER;
|
|
||||||
iface->if_mtu = frame_size;
|
|
||||||
|
|
||||||
iface->module = &nimi;
|
return g_stack->register_layer(&edl->layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------
|
||||||
|
status_t device_reader(void *args)
|
||||||
|
{
|
||||||
|
net_layer *me = args;
|
||||||
|
ethernet_device_layer *edl = (ethernet_device_layer *) me;
|
||||||
|
net_buffer *buffer;
|
||||||
|
status_t status;
|
||||||
|
void *frame;
|
||||||
|
ssize_t sz;
|
||||||
|
|
||||||
|
printf("%s: device reader started.\n", me->name);
|
||||||
|
|
||||||
|
status = B_OK;
|
||||||
|
while(1) {
|
||||||
|
frame = malloc(edl->max_frame_size);
|
||||||
|
if (!frame) {
|
||||||
|
status = B_NO_MEMORY;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
// read on frame at time
|
||||||
|
sz = read(edl->fd, frame, edl->max_frame_size);
|
||||||
|
if (sz >= B_OK) {
|
||||||
|
buffer = g_stack->new_buffer();
|
||||||
|
if (!buffer) {
|
||||||
|
free(frame);
|
||||||
|
status = B_NO_MEMORY;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
g_stack->add_to_buffer(buffer, 0, frame, sz, (buffer_chunk_free_func) free);
|
||||||
|
|
||||||
return g_stack->register_interface(iface);
|
printf("%s: input buffer:\n", me->name);
|
||||||
|
g_stack->dump_buffer(buffer);
|
||||||
|
|
||||||
|
if (g_stack->push_buffer_up(me, buffer) != B_OK)
|
||||||
|
// nobody above us *eat* this buffer, so we drop it ourself :-(
|
||||||
|
g_stack->delete_buffer(buffer, false);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
edl->reader_thread = -1;
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
@@ -283,29 +317,21 @@ status_t std_ops(int32 op, ...)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct net_interface_module_info nimi = {
|
struct net_layer_module_info nlmi = {
|
||||||
{
|
{
|
||||||
NET_INTERFACE_MODULE_ROOT "ethernet/v0",
|
NET_LAYER_MODULE_ROOT "interfaces/ethernet",
|
||||||
0,
|
0,
|
||||||
std_ops
|
std_ops
|
||||||
},
|
},
|
||||||
|
|
||||||
init,
|
init,
|
||||||
uninit,
|
uninit,
|
||||||
up,
|
enable,
|
||||||
down,
|
output_buffer,
|
||||||
send,
|
NULL // interface layer: no input_buffer
|
||||||
receive,
|
|
||||||
control,
|
|
||||||
get_hardware_address,
|
|
||||||
get_multicast_addresses,
|
|
||||||
set_multicast_addresses,
|
|
||||||
set_mtu,
|
|
||||||
set_promiscuous,
|
|
||||||
set_media
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_EXPORT module_info *modules[] = {
|
_EXPORT module_info *modules[] = {
|
||||||
(module_info*) &nimi, // net_interface_module_info
|
(module_info*) &nlmi, // net_layer_module_info
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
Binary file not shown.
@@ -1,102 +1,63 @@
|
|||||||
/* loopback.c - loopback device
|
/* loopback.c - loopback interface module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <Drivers.h>
|
||||||
|
|
||||||
#include "net_stack.h"
|
#include "net_stack.h"
|
||||||
#include "net_interface.h"
|
#include "net_layer.h"
|
||||||
|
|
||||||
#define LOOPBACK_MTU 16384 // can be as large as we want
|
status_t std_ops(int32 op, ...);
|
||||||
|
|
||||||
|
struct net_layer_module_info nlmi;
|
||||||
|
|
||||||
|
static struct net_stack_module_info *g_stack = NULL;
|
||||||
|
|
||||||
|
|
||||||
typedef struct loopback_interface {
|
// -------------------
|
||||||
ifnet_t ifnet;
|
|
||||||
net_buffer_queue *queue;
|
|
||||||
} loopback_interface;
|
|
||||||
|
|
||||||
|
|
||||||
status_t std_ops(int32 op, ...);
|
|
||||||
|
|
||||||
struct net_interface_module_info nimi;
|
|
||||||
|
|
||||||
struct net_stack_module_info *g_stack = NULL;
|
|
||||||
|
|
||||||
status_t init(void * params)
|
status_t init(void * params)
|
||||||
{
|
{
|
||||||
ifnet_t * iface;
|
net_layer *layer;
|
||||||
loopback_interface *li;
|
|
||||||
|
|
||||||
li = (loopback_interface *) malloc(sizeof(*li));
|
|
||||||
if (!li)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
// create loopback fifo queue, to keep packets *sent*
|
layer = malloc(sizeof(*layer));
|
||||||
li->queue = g_stack->new_buffer_queue(64*LOOPBACK_MTU);
|
if (!layer)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
layer->name = "*/loopback";
|
||||||
iface = &li->ifnet;
|
layer->module = &nlmi;
|
||||||
iface->if_name = "loopback";
|
|
||||||
iface->if_flags = (IFF_LOOPBACK | IFF_NOARP);
|
|
||||||
iface->if_type = 0x10; //IFT_LOOP
|
|
||||||
iface->if_mtu = LOOPBACK_MTU;
|
|
||||||
|
|
||||||
// never forget to store a pointer to us, otherwise datalink layer can't call us
|
return g_stack->register_layer(layer);
|
||||||
iface->module = &nimi;
|
|
||||||
|
|
||||||
return g_stack->register_interface(iface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t uninit(ifnet_t *iface)
|
status_t uninit(net_layer *me)
|
||||||
{
|
{
|
||||||
loopback_interface *li = (loopback_interface *) iface;
|
printf("%s: uniniting layer\n", me->name);
|
||||||
|
free(me);
|
||||||
printf("loopback: uniniting %s interface\n", iface->if_name);
|
return B_OK;
|
||||||
return g_stack->delete_buffer_queue(li->queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t up(ifnet_t *iface)
|
|
||||||
{
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t down(ifnet_t *iface)
|
status_t enable(net_layer *me, bool enable)
|
||||||
{
|
{
|
||||||
return B_ERROR;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t send(ifnet_t *iface, net_buffer *buffer)
|
status_t output_buffer(net_layer *me, net_buffer *buffer)
|
||||||
{
|
{
|
||||||
loopback_interface *li = (loopback_interface *) iface;
|
|
||||||
|
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
return g_stack->enqueue_buffer(li->queue, buffer);
|
return g_stack->push_buffer_up(me, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t receive(ifnet_t *iface, net_buffer **buffer)
|
|
||||||
{
|
|
||||||
loopback_interface *li = (loopback_interface *) iface;
|
|
||||||
|
|
||||||
return g_stack->dequeue_buffer(li->queue, buffer, B_INFINITE_TIMEOUT, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t control(ifnet_t *iface, int opcode, void *arg) { return -1; }
|
|
||||||
|
|
||||||
status_t get_hardware_address(ifnet_t *iface, net_interface_hwaddr *hwaddr) { return -1; }
|
|
||||||
status_t get_multicast_addresses(ifnet_t *iface, net_interface_hwaddr **hwaddr, int nb_addresses) { return -1; }
|
|
||||||
status_t set_multicast_addresses(ifnet_t *iface, net_interface_hwaddr *hwaddr, int nb_addresses) { return -1; }
|
|
||||||
|
|
||||||
status_t set_mtu(ifnet_t *iface, uint32 mtu) { return -1; }
|
|
||||||
status_t set_promiscuous(ifnet_t *iface, bool enable) { return -1; }
|
|
||||||
status_t set_media(ifnet_t *iface, uint32 media) { return -1; }
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
status_t std_ops(int32 op, ...)
|
status_t std_ops(int32 op, ...)
|
||||||
@@ -117,29 +78,21 @@ status_t std_ops(int32 op, ...)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct net_interface_module_info nimi = {
|
struct net_layer_module_info nlmi = {
|
||||||
{
|
{
|
||||||
NET_INTERFACE_MODULE_ROOT "loopback",
|
NET_LAYER_MODULE_ROOT "interfaces/loopback",
|
||||||
0,
|
0,
|
||||||
std_ops
|
std_ops
|
||||||
},
|
},
|
||||||
|
|
||||||
init,
|
init,
|
||||||
uninit,
|
uninit,
|
||||||
up,
|
enable,
|
||||||
down,
|
output_buffer,
|
||||||
send,
|
NULL // interface layer: no input_buffer
|
||||||
receive,
|
|
||||||
control,
|
|
||||||
get_hardware_address,
|
|
||||||
get_multicast_addresses,
|
|
||||||
set_multicast_addresses,
|
|
||||||
set_mtu,
|
|
||||||
set_promiscuous,
|
|
||||||
set_media
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_EXPORT module_info *modules[] = {
|
_EXPORT module_info *modules[] = {
|
||||||
(module_info*) &nimi, // net_interface_module_info
|
(module_info*) &nlmi, // net_layer_module_info
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user