Cleaned up the net_stack_driver a little bit, so it is more usable.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15500 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -2,7 +2,7 @@ SubDir HAIKU_TOP src add-ons kernel drivers network stack ;
|
|||||||
|
|
||||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||||
|
|
||||||
if $(TARGET_PLATFORM) != haiku {
|
if ( $(TARGET_PLATFORM) != haiku ) {
|
||||||
UseHeaders [ FStandardOSHeaders ] : true ;
|
UseHeaders [ FStandardOSHeaders ] : true ;
|
||||||
# Needed for <drivers/Select.h> and maybe other stuff.
|
# Needed for <drivers/Select.h> and maybe other stuff.
|
||||||
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
|
UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ;
|
||||||
@@ -11,7 +11,6 @@ if $(TARGET_PLATFORM) != haiku {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UsePrivateHeaders net ;
|
UsePrivateHeaders net ;
|
||||||
UseHeaders [ FDirName $(HAIKU_TOP) src add-ons kernel network ppp shared libkernelppp headers ] ;
|
|
||||||
|
|
||||||
# a) Userland stack version:
|
# a) Userland stack version:
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
// Private includes
|
// Private includes
|
||||||
#include <net_stack_driver.h>
|
#include <net_stack_driver.h>
|
||||||
// #include <PPPControl.h> // for NET_STACK_CONTROL_NET_MODULE PPP support...
|
|
||||||
#include <userland_ipc.h>
|
#include <userland_ipc.h>
|
||||||
#include <sys/sockio.h>
|
#include <sys/sockio.h>
|
||||||
|
|
||||||
|
|||||||
@@ -8,124 +8,88 @@
|
|||||||
#error "This module MUST be built as a kernel driver!"
|
#error "This module MUST be built as a kernel driver!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Public/system includes
|
// public/system includes
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <drivers/Drivers.h>
|
#include <drivers/Drivers.h>
|
||||||
#include <drivers/KernelExport.h>
|
#include <drivers/KernelExport.h>
|
||||||
#include <drivers/driver_settings.h>
|
#include <drivers/driver_settings.h>
|
||||||
#include <drivers/module.h> // For get_module()/put_module()
|
#include <drivers/module.h> // for get_module()/put_module()
|
||||||
|
|
||||||
#include <netinet/in_var.h>
|
#include <netinet/in_var.h>
|
||||||
|
|
||||||
// Private includes
|
// private includes
|
||||||
#include <net_stack_driver.h>
|
#include <net_stack_driver.h>
|
||||||
#include <sys/protosw.h>
|
#include <sys/protosw.h>
|
||||||
#include <core_module.h>
|
#include <core_module.h>
|
||||||
|
|
||||||
// Trace support
|
|
||||||
#if defined(DEBUG)
|
// debugging macros
|
||||||
#define TRACE(x) dprintf x
|
#define LOGID "net_stack_driver: "
|
||||||
|
#define ERROR(format, args...) dprintf(LOGID "ERROR: " format, ## args)
|
||||||
|
#define WARN(format, args...) dprintf(LOGID "WARNING: " format, ## args)
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define TRACE(format, args...) dprintf(format, ## args)
|
||||||
#else
|
#else
|
||||||
#define TRACE(x) ;
|
#define TRACE(format, args...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Force the driver to stay loaded in memory
|
|
||||||
#define STAY_LOADED 0
|
|
||||||
|
|
||||||
/*
|
// Local definitions
|
||||||
* Local definitions
|
|
||||||
* -----------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DRIVER_NAME
|
|
||||||
#define DRIVER_NAME "net_stack_driver"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LOGID
|
|
||||||
#define LOGID DRIVER_NAME ": "
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef WARN
|
|
||||||
#define WARN "Warning: "
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ERR
|
|
||||||
#define ERR "ERROR: "
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef COMPILE_FOR_R5
|
|
||||||
typedef status_t (*notify_select_event_function)(selectsync * sync, uint32 ref);
|
|
||||||
#else
|
|
||||||
typedef status_t (*notify_select_event_function)(selectsync * sync, uint32 ref, uint8 event);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct socket; /* forward declaration */
|
|
||||||
|
|
||||||
// this struct will store one select() event to monitor per thread
|
// this struct will store one select() event to monitor per thread
|
||||||
typedef struct selecter {
|
typedef struct selecter {
|
||||||
struct selecter * next;
|
struct selecter *next;
|
||||||
thread_id thread;
|
thread_id thread;
|
||||||
uint32 event;
|
uint32 event;
|
||||||
selectsync * sync;
|
selectsync *sync;
|
||||||
uint32 ref;
|
uint32 ref;
|
||||||
notify_select_event_function notify;
|
|
||||||
} selecter;
|
} selecter;
|
||||||
|
|
||||||
// the cookie we attach to each file descriptor opened on our driver entry
|
// the cookie we attach to each file descriptor opened on our driver entry
|
||||||
typedef struct {
|
typedef struct net_stack_cookie {
|
||||||
struct socket * socket; // NULL before ioctl(fd, NET_STACK_SOCKET/_ACCEPT)
|
struct socket *socket; // NULL before ioctl(fd, NET_STACK_SOCKET/_ACCEPT)
|
||||||
uint32 open_flags; // the open() flags (mostly for storing O_NONBLOCK mode)
|
uint32 open_flags; // the open() flags (mostly for storing O_NONBLOCK mode)
|
||||||
sem_id selecters_lock; // protect the selecters linked-list
|
sem_id selecters_lock; // protect the selecters linked-list
|
||||||
selecter * selecters; // the select()'ers lists (thread-aware)
|
selecter *selecters; // the select()'ers lists (thread-aware)
|
||||||
notify_select_event_function notify;
|
|
||||||
} net_stack_cookie;
|
} net_stack_cookie;
|
||||||
|
|
||||||
#if STAY_LOADED
|
/* To unload this driver execute
|
||||||
/* to unload the driver, simply write UNLOAD_CMD to him:
|
* $ echo unload > /dev/net/stack
|
||||||
* $ echo stop > /dev/net/stack
|
* As soon as the last app stops using sockets the netstack will be unloaded.
|
||||||
* As soon as last app, via libnet.so, stop using it, it will unload,
|
*/
|
||||||
* and in turn stop the stack and unload all network kernel modules...
|
static const char *kUnloadCommand = "unload";
|
||||||
*/
|
|
||||||
#define UNLOAD_CMD "unload"
|
|
||||||
#endif
|
|
||||||
#define STOP_CMD "stop"
|
|
||||||
|
|
||||||
// Prototypes of device hooks functions
|
|
||||||
static status_t net_stack_open(const char * name, uint32 flags, void ** cookie);
|
// prototypes of device hooks functions
|
||||||
static status_t net_stack_close(void * cookie);
|
static status_t net_stack_open(const char *name, uint32 flags, void **cookie);
|
||||||
static status_t net_stack_free_cookie(void * cookie);
|
static status_t net_stack_close(void *cookie);
|
||||||
static status_t net_stack_control(void * cookie, uint32 msg,void * data, size_t datalen);
|
static status_t net_stack_free_cookie(void *cookie);
|
||||||
static status_t net_stack_read(void * cookie, off_t pos, void * data, size_t * datalen);
|
static status_t net_stack_control(void *cookie, uint32 msg, void *data, size_t datalen);
|
||||||
static status_t net_stack_write(void * cookie, off_t pos, const void * data, size_t * datalen);
|
static status_t net_stack_read(void *cookie, off_t pos, void *data, size_t *datalen);
|
||||||
|
static status_t net_stack_write(void *cookie, off_t pos, const void *data, size_t *datalen);
|
||||||
static status_t net_stack_select(void *cookie, uint8 event, uint32 ref, selectsync *sync);
|
static status_t net_stack_select(void *cookie, uint8 event, uint32 ref, selectsync *sync);
|
||||||
static status_t net_stack_deselect(void *cookie, uint8 event, selectsync *sync);
|
static status_t net_stack_deselect(void *cookie, uint8 event, selectsync *sync);
|
||||||
// static status_t net_stack_readv(void * cookie, off_t pos, const iovec * vec, size_t count, size_t * len);
|
// static status_t net_stack_readv(void *cookie, off_t pos, const iovec *vec, size_t count, size_t *len);
|
||||||
// static status_t net_stack_writev(void * cookie, off_t pos, const iovec * vec, size_t count, size_t * len);
|
// static status_t net_stack_writev(void *cookie, off_t pos, const iovec *vec, size_t count, size_t *len);
|
||||||
|
|
||||||
// Privates prototypes
|
// privates prototypes
|
||||||
static void on_socket_event(void * socket, uint32 event, void * cookie);
|
static void on_socket_event(void *socket, uint32 event, void *cookie);
|
||||||
static status_t r5_notify_select_event(selectsync * sync, uint32 ref, uint8 event);
|
|
||||||
|
|
||||||
#if STAY_LOADED
|
|
||||||
static status_t keep_driver_loaded();
|
static status_t keep_driver_loaded();
|
||||||
static status_t unload_driver();
|
static status_t unload_driver();
|
||||||
#endif
|
|
||||||
|
|
||||||
static const char * opcode_name(int op);
|
static const char *opcode_name(int op);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global variables
|
* Global variables
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const char * g_device_names_list[] = {
|
static const char *sDevices[] = { NET_STACK_DRIVER_DEV, NULL };
|
||||||
NET_STACK_DRIVER_DEV,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
device_hooks g_net_stack_driver_hooks =
|
static device_hooks sDeviceHooks =
|
||||||
{
|
{
|
||||||
net_stack_open, /* -> open entry point */
|
net_stack_open, /* -> open entry point */
|
||||||
net_stack_close, /* -> close entry point */
|
net_stack_close, /* -> close entry point */
|
||||||
@@ -135,15 +99,53 @@ device_hooks g_net_stack_driver_hooks =
|
|||||||
net_stack_write, /* -> write entry point */
|
net_stack_write, /* -> write entry point */
|
||||||
net_stack_select, /* -> select entry point */
|
net_stack_select, /* -> select entry point */
|
||||||
net_stack_deselect, /* -> deselect entry point */
|
net_stack_deselect, /* -> deselect entry point */
|
||||||
NULL, /* -> readv entry pint */
|
NULL, /* -> readv entry pint */
|
||||||
NULL /* ->writev entry point */
|
NULL /* ->writev entry point */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct core_module_info *g_core = NULL;
|
static struct core_module_info *sCore = NULL;
|
||||||
|
|
||||||
#if STAY_LOADED
|
static int sStayLoadedFD = -1;
|
||||||
int g_stay_loaded_fd = -1;
|
|
||||||
#endif
|
|
||||||
|
// internal functions
|
||||||
|
static status_t
|
||||||
|
keep_driver_loaded()
|
||||||
|
{
|
||||||
|
if (sStayLoadedFD != -1)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
/* force the driver to stay loaded by opening himself */
|
||||||
|
TRACE("keep_driver_loaded: opening " NET_STACK_DRIVER_PATH " to stay loaded...\n");
|
||||||
|
|
||||||
|
sStayLoadedFD = open(NET_STACK_DRIVER_PATH, 0);
|
||||||
|
|
||||||
|
if (sStayLoadedFD < 0)
|
||||||
|
ERROR("keep_driver_loaded: couldn't open(" NET_STACK_DRIVER_PATH ")!\n");
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
unload_driver()
|
||||||
|
{
|
||||||
|
if (sStayLoadedFD >= 0) {
|
||||||
|
int tmp_fd;
|
||||||
|
|
||||||
|
/* we need to set sStayLoadedFD to < 0 if we don't want
|
||||||
|
* the next close enter again in this case, and so on...
|
||||||
|
*/
|
||||||
|
TRACE("unload_driver: unload requested.\n");
|
||||||
|
|
||||||
|
tmp_fd = sStayLoadedFD;
|
||||||
|
sStayLoadedFD = -1;
|
||||||
|
|
||||||
|
close(tmp_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -162,7 +164,8 @@ _EXPORT int32 api_version = B_CUR_DRIVER_API_VERSION;
|
|||||||
* Also we'll turn on the serial debugger to aid in our debugging
|
* Also we'll turn on the serial debugger to aid in our debugging
|
||||||
* experience.
|
* experience.
|
||||||
*/
|
*/
|
||||||
_EXPORT status_t init_hardware(void)
|
_EXPORT status_t
|
||||||
|
init_hardware(void)
|
||||||
{
|
{
|
||||||
bool safemode = false;
|
bool safemode = false;
|
||||||
void *sfmptr;
|
void *sfmptr;
|
||||||
@@ -172,17 +175,18 @@ _EXPORT status_t init_hardware(void)
|
|||||||
|
|
||||||
// only use the pointer if it's valid
|
// only use the pointer if it's valid
|
||||||
if (sfmptr != NULL) {
|
if (sfmptr != NULL) {
|
||||||
// we got a pointer, now get setting...
|
// we got a pointer, now get settings...
|
||||||
safemode = get_driver_boolean_parameter(sfmptr, B_SAFEMODE_SAFE_MODE, false, false);
|
safemode = get_driver_boolean_parameter(sfmptr, B_SAFEMODE_SAFE_MODE, false, false);
|
||||||
// now get rid of settings
|
// now get rid of settings
|
||||||
unload_driver_settings(sfmptr);
|
unload_driver_settings(sfmptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (safemode) {
|
if (safemode) {
|
||||||
TRACE((LOGID WARN "init_hardware: declining offer to join the party.\n"));
|
WARN("init_hardware: declining offer to join the party.\n");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE((LOGID "init_hardware done.\n"));
|
TRACE("init_hardware done.\n");
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -191,63 +195,64 @@ _EXPORT status_t init_hardware(void)
|
|||||||
/* init_driver()
|
/* init_driver()
|
||||||
* called every time we're loaded.
|
* called every time we're loaded.
|
||||||
*/
|
*/
|
||||||
_EXPORT status_t init_driver(void)
|
_EXPORT status_t
|
||||||
|
init_driver(void)
|
||||||
{
|
{
|
||||||
// only get the core module if we don't have it loaded already
|
// only get the core module if we don't have it loaded already
|
||||||
if (!g_core) {
|
if (!sCore) {
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
rv = get_module(NET_CORE_MODULE_NAME, (module_info **) &g_core);
|
rv = get_module(NET_CORE_MODULE_NAME, (module_info **) &sCore);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
TRACE((LOGID ERR "init_driver: Argh, can't load " NET_CORE_MODULE_NAME " module: %d\n", rv));
|
ERROR("init_driver: Can't load " NET_CORE_MODULE_NAME " module: %d\n", rv);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE((LOGID "init_driver: built %s %s, core = %p\n", __DATE__, __TIME__, g_core));
|
TRACE("init_driver: built %s %s, core = %p\n", __DATE__, __TIME__, sCore);
|
||||||
|
|
||||||
// start the network stack!
|
// start the network stack
|
||||||
g_core->start();
|
sCore->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keep_driver_loaded();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* uninit_driver()
|
/* uninit_driver()
|
||||||
* called every time the driver is unloaded
|
* called every time the driver is unloaded
|
||||||
*/
|
*/
|
||||||
_EXPORT void uninit_driver(void)
|
_EXPORT void
|
||||||
|
uninit_driver(void)
|
||||||
{
|
{
|
||||||
TRACE((LOGID "uninit_driver\n"));
|
TRACE("uninit_driver\n");
|
||||||
|
|
||||||
if (g_core) {
|
if (sCore) {
|
||||||
// shutdown the network stack
|
// shutdown the network stack
|
||||||
g_core->stop();
|
sCore->stop();
|
||||||
|
|
||||||
put_module(NET_CORE_MODULE_NAME);
|
put_module(NET_CORE_MODULE_NAME);
|
||||||
g_core = NULL;
|
sCore = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* publish_devices()
|
/* publish_devices()
|
||||||
* called to publish our device.
|
* called to publish our device.
|
||||||
*/
|
*/
|
||||||
_EXPORT const char ** publish_devices()
|
_EXPORT const char**
|
||||||
|
publish_devices()
|
||||||
{
|
{
|
||||||
return g_device_names_list;
|
return sDevices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_EXPORT device_hooks*
|
||||||
_EXPORT device_hooks * find_device(const char* device_name)
|
find_device(const char* device_name)
|
||||||
{
|
{
|
||||||
return &g_net_stack_driver_hooks;
|
return &sDeviceHooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Device hooks
|
* Device hooks
|
||||||
@@ -255,7 +260,8 @@ _EXPORT device_hooks * find_device(const char* device_name)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// the network stack functions - mainly just pass throughs...
|
// the network stack functions - mainly just pass throughs...
|
||||||
static status_t net_stack_open(const char *name, uint32 flags, void **cookie)
|
static status_t
|
||||||
|
net_stack_open(const char *name, uint32 flags, void **cookie)
|
||||||
{
|
{
|
||||||
net_stack_cookie *nsc;
|
net_stack_cookie *nsc;
|
||||||
|
|
||||||
@@ -268,33 +274,33 @@ static status_t net_stack_open(const char *name, uint32 flags, void **cookie)
|
|||||||
nsc->open_flags = flags;
|
nsc->open_flags = flags;
|
||||||
nsc->selecters_lock = create_sem(1, "socket_selecters_lock");
|
nsc->selecters_lock = create_sem(1, "socket_selecters_lock");
|
||||||
nsc->selecters = NULL;
|
nsc->selecters = NULL;
|
||||||
nsc->notify = NULL;
|
|
||||||
|
|
||||||
// attach this new net_socket_cookie to file descriptor
|
// attach this new net_socket_cookie to file descriptor
|
||||||
*cookie = nsc;
|
*cookie = nsc;
|
||||||
|
|
||||||
TRACE((LOGID "net_stack_open(%s, %s%s) return this cookie: %p\n", name,
|
TRACE("net_stack_open(%s, %s%s) return this cookie: %p\n",
|
||||||
( ((flags & O_RWMASK) == O_RDONLY) ? "O_RDONLY" :
|
name,
|
||||||
((flags & O_RWMASK) == O_WRONLY) ? "O_WRONLY" : "O_RDWR"),
|
(((flags & O_RWMASK) == O_RDONLY) ? "O_RDONLY" :
|
||||||
(flags & O_NONBLOCK) ? " O_NONBLOCK" : "",
|
((flags & O_RWMASK) == O_WRONLY) ? "O_WRONLY" : "O_RDWR"),
|
||||||
*cookie));
|
(flags & O_NONBLOCK) ? " O_NONBLOCK" : "",
|
||||||
|
*cookie);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
static status_t net_stack_close(void *cookie)
|
net_stack_close(void *cookie)
|
||||||
{
|
{
|
||||||
net_stack_cookie *nsc = cookie;
|
net_stack_cookie *nsc = cookie;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
TRACE((LOGID "net_stack_close(%p)\n", nsc));
|
TRACE("net_stack_close(%p)\n", nsc);
|
||||||
|
|
||||||
rv = B_ERROR;
|
rv = B_ERROR;
|
||||||
if (nsc->socket) {
|
if (nsc->socket) {
|
||||||
// if a socket was opened on this fd, close it now.
|
// if a socket was opened on this fd, close it now.
|
||||||
rv = g_core->socket_close(nsc->socket);
|
rv = sCore->socket_close(nsc->socket);
|
||||||
nsc->socket = NULL;
|
nsc->socket = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,13 +308,13 @@ static status_t net_stack_close(void *cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
static status_t net_stack_free_cookie(void *cookie)
|
net_stack_free_cookie(void *cookie)
|
||||||
{
|
{
|
||||||
net_stack_cookie *nsc = cookie;
|
net_stack_cookie *nsc = cookie;
|
||||||
selecter *s;
|
selecter *s;
|
||||||
|
|
||||||
TRACE((LOGID "net_stack_free_cookie(%p)\n", cookie));
|
TRACE("net_stack_free_cookie(%p)\n", cookie);
|
||||||
|
|
||||||
// free the selecters list
|
// free the selecters list
|
||||||
delete_sem(nsc->selecters_lock);
|
delete_sem(nsc->selecters_lock);
|
||||||
@@ -317,7 +323,7 @@ static status_t net_stack_free_cookie(void *cookie)
|
|||||||
selecter *tmp = s;
|
selecter *tmp = s;
|
||||||
s = s->next;
|
s = s->next;
|
||||||
free(tmp);
|
free(tmp);
|
||||||
};
|
}
|
||||||
|
|
||||||
// free the cookie
|
// free the cookie
|
||||||
free(cookie);
|
free(cookie);
|
||||||
@@ -325,29 +331,30 @@ static status_t net_stack_free_cookie(void *cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t len)
|
net_stack_control(void *cookie, uint32 op, void *data, size_t len)
|
||||||
{
|
{
|
||||||
net_stack_cookie *nsc = cookie;
|
net_stack_cookie *nsc = cookie;
|
||||||
struct stack_driver_args *args = data;
|
struct stack_driver_args *args = data;
|
||||||
int err = B_OK;
|
int err = B_BAD_VALUE;
|
||||||
|
|
||||||
TRACE((LOGID "net_stack_control(%p, %s (0x%lX), %p, %ld)\n",
|
TRACE("net_stack_control(%p, %s (0x%lX), %p, %ld)\n",
|
||||||
cookie, opcode_name(op), op, data, len));
|
cookie, opcode_name(op), op, data, len);
|
||||||
|
|
||||||
#if STAY_LOADED
|
if (!nsc->socket) {
|
||||||
keep_driver_loaded();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (! nsc->socket) {
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NET_STACK_SOCKET: {
|
case NET_STACK_SOCKET: {
|
||||||
|
|
||||||
// okay, now try to open a real socket behind this fd/net_stack_cookie pair
|
// okay, now try to open a real socket behind this fd/net_stack_cookie pair
|
||||||
err = g_core->socket_init(&nsc->socket);
|
err = sCore->socket_init(&nsc->socket);
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
err = g_core->socket_create(nsc->socket, args->u.socket.family, args->u.socket.type, args->u.socket.proto);
|
err = sCore->socket_create(nsc->socket, args->u.socket.family,
|
||||||
// TODO: This is where the open flags need to be addressed
|
args->u.socket.type, args->u.socket.proto);
|
||||||
|
|
||||||
|
// TODO: handle some more open_flags
|
||||||
|
if(nsc->open_flags & O_NONBLOCK) {
|
||||||
|
int on = true;
|
||||||
|
return sCore->socket_ioctl(nsc->socket, FIONBIO, (caddr_t) &on);
|
||||||
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
case NET_STACK_GET_COOKIE: {
|
case NET_STACK_GET_COOKIE: {
|
||||||
@@ -360,24 +367,30 @@ static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t le
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
case NET_STACK_CONTROL_NET_MODULE: {
|
case NET_STACK_CONTROL_NET_MODULE: {
|
||||||
return g_core->control_net_module(args->u.control.name, args->u.control.op,
|
return sCore->control_net_module(args->u.control.name,
|
||||||
args->u.control.data, args->u.control.length);
|
args->u.control.op, args->u.control.data, args->u.control.length);
|
||||||
}
|
}
|
||||||
};
|
case NET_STACK_SYSCTL:
|
||||||
|
return sCore->net_sysctl(args->u.sysctl.name, args->u.sysctl.namelen,
|
||||||
|
args->u.sysctl.oldp, args->u.sysctl.oldlenp,
|
||||||
|
args->u.sysctl.newp, args->u.sysctl.newlen);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case NET_STACK_CONNECT:
|
case NET_STACK_CONNECT:
|
||||||
return g_core->socket_connect(nsc->socket, (caddr_t) args->u.sockaddr.addr, args->u.sockaddr.addrlen);
|
return sCore->socket_connect(nsc->socket,
|
||||||
|
(caddr_t) args->u.sockaddr.addr, args->u.sockaddr.addrlen);
|
||||||
|
|
||||||
case NET_STACK_SHUTDOWN:
|
case NET_STACK_SHUTDOWN:
|
||||||
return g_core->socket_shutdown(nsc->socket, args->u.integer);
|
return sCore->socket_shutdown(nsc->socket, args->u.integer);
|
||||||
|
|
||||||
case NET_STACK_BIND:
|
case NET_STACK_BIND:
|
||||||
return g_core->socket_bind(nsc->socket, (caddr_t) args->u.sockaddr.addr, args->u.sockaddr.addrlen);
|
return sCore->socket_bind(nsc->socket, (caddr_t) args->u.sockaddr.addr,
|
||||||
|
args->u.sockaddr.addrlen);
|
||||||
|
|
||||||
case NET_STACK_LISTEN:
|
case NET_STACK_LISTEN:
|
||||||
// backlog to set
|
// backlog to set
|
||||||
return g_core->socket_listen(nsc->socket, args->u.integer);
|
return sCore->socket_listen(nsc->socket, args->u.integer);
|
||||||
|
|
||||||
case NET_STACK_ACCEPT: {
|
case NET_STACK_ACCEPT: {
|
||||||
/* args->u.accept.cookie == net_stack_cookie of the already opened fd
|
/* args->u.accept.cookie == net_stack_cookie of the already opened fd
|
||||||
@@ -385,22 +398,25 @@ static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t le
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
net_stack_cookie *ansc = args->u.accept.cookie;
|
net_stack_cookie *ansc = args->u.accept.cookie;
|
||||||
return g_core->socket_accept(nsc->socket, &ansc->socket, (void *)args->u.accept.addr, &args->u.accept.addrlen);
|
return sCore->socket_accept(nsc->socket, &ansc->socket,
|
||||||
|
(void *)args->u.accept.addr, &args->u.accept.addrlen);
|
||||||
}
|
}
|
||||||
case NET_STACK_SEND:
|
case NET_STACK_SEND:
|
||||||
// TODO: flags gets ignored here...
|
// TODO: flags gets ignored here...
|
||||||
return net_stack_write(cookie, 0, args->u.transfer.data, &args->u.transfer.datalen);
|
return net_stack_write(cookie, 0, args->u.transfer.data,
|
||||||
|
&args->u.transfer.datalen);
|
||||||
|
|
||||||
case NET_STACK_RECV:
|
case NET_STACK_RECV:
|
||||||
// TODO: flags gets ignored here...
|
// TODO: flags gets ignored here...
|
||||||
return net_stack_read(cookie, 0, args->u.transfer.data, &args->u.transfer.datalen);
|
return net_stack_read(cookie, 0, args->u.transfer.data,
|
||||||
|
&args->u.transfer.datalen);
|
||||||
|
|
||||||
case NET_STACK_RECVFROM: {
|
case NET_STACK_RECVFROM: {
|
||||||
struct msghdr * mh = (struct msghdr *) data;
|
struct msghdr * mh = (struct msghdr *) data;
|
||||||
int retsize;
|
int retsize;
|
||||||
|
|
||||||
err = g_core->socket_recv(nsc->socket, mh, (caddr_t)&mh->msg_namelen,
|
err = sCore->socket_recv(nsc->socket, mh, (caddr_t)&mh->msg_namelen,
|
||||||
&retsize);
|
&retsize);
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
return retsize;
|
return retsize;
|
||||||
return err;
|
return err;
|
||||||
@@ -409,154 +425,116 @@ static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t le
|
|||||||
struct msghdr * mh = (struct msghdr *) data;
|
struct msghdr * mh = (struct msghdr *) data;
|
||||||
int retsize;
|
int retsize;
|
||||||
|
|
||||||
err = g_core->socket_send(nsc->socket, mh, mh->msg_flags,
|
err = sCore->socket_send(nsc->socket, mh, mh->msg_flags, &retsize);
|
||||||
&retsize);
|
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
return retsize;
|
return retsize;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
case NET_STACK_SYSCTL:
|
|
||||||
return g_core->net_sysctl(args->u.sysctl.name, args->u.sysctl.namelen,
|
|
||||||
args->u.sysctl.oldp, args->u.sysctl.oldlenp,
|
|
||||||
args->u.sysctl.newp, args->u.sysctl.newlen);
|
|
||||||
|
|
||||||
case NET_STACK_GETSOCKOPT:
|
case NET_STACK_GETSOCKOPT:
|
||||||
return g_core->socket_getsockopt(nsc->socket, args->u.sockopt.level, args->u.sockopt.option,
|
return sCore->socket_getsockopt(nsc->socket, args->u.sockopt.level,
|
||||||
args->u.sockopt.optval, (size_t *) &args->u.sockopt.optlen);
|
args->u.sockopt.option, args->u.sockopt.optval,
|
||||||
|
(size_t *) &args->u.sockopt.optlen);
|
||||||
|
|
||||||
case NET_STACK_SETSOCKOPT:
|
case NET_STACK_SETSOCKOPT:
|
||||||
return g_core->socket_setsockopt(nsc->socket, args->u.sockopt.level, args->u.sockopt.option,
|
return sCore->socket_setsockopt(nsc->socket, args->u.sockopt.level,
|
||||||
(const void *) args->u.sockopt.optval, args->u.sockopt.optlen);
|
args->u.sockopt.option, (const void *) args->u.sockopt.optval,
|
||||||
|
args->u.sockopt.optlen);
|
||||||
|
|
||||||
case NET_STACK_GETSOCKNAME:
|
case NET_STACK_GETSOCKNAME:
|
||||||
return g_core->socket_getsockname(nsc->socket, args->u.sockaddr.addr, &args->u.sockaddr.addrlen);
|
return sCore->socket_getsockname(nsc->socket, args->u.sockaddr.addr,
|
||||||
|
&args->u.sockaddr.addrlen);
|
||||||
|
|
||||||
case NET_STACK_GETPEERNAME:
|
case NET_STACK_GETPEERNAME:
|
||||||
return g_core->socket_getpeername(nsc->socket, args->u.sockaddr.addr, &args->u.sockaddr.addrlen);
|
return sCore->socket_getpeername(nsc->socket, args->u.sockaddr.addr,
|
||||||
|
&args->u.sockaddr.addrlen);
|
||||||
|
|
||||||
case NET_STACK_SOCKETPAIR: {
|
case NET_STACK_SOCKETPAIR: {
|
||||||
net_stack_cookie *ansc = args->u.socketpair.cookie;
|
net_stack_cookie *ansc = args->u.socketpair.cookie;
|
||||||
return g_core->socket_socketpair(nsc->socket, &ansc->socket);
|
return sCore->socket_socketpair(nsc->socket, &ansc->socket);
|
||||||
}
|
}
|
||||||
case B_SET_BLOCKING_IO: {
|
case B_SET_BLOCKING_IO: {
|
||||||
int off = false;
|
int off = false;
|
||||||
nsc->open_flags &= ~O_NONBLOCK;
|
nsc->open_flags &= ~O_NONBLOCK;
|
||||||
return g_core->socket_ioctl(nsc->socket, FIONBIO, (caddr_t) &off);
|
return sCore->socket_ioctl(nsc->socket, FIONBIO, (caddr_t) &off);
|
||||||
}
|
}
|
||||||
|
|
||||||
case B_SET_NONBLOCKING_IO: {
|
case B_SET_NONBLOCKING_IO: {
|
||||||
int on = true;
|
int on = true;
|
||||||
nsc->open_flags |= O_NONBLOCK;
|
nsc->open_flags |= O_NONBLOCK;
|
||||||
return g_core->socket_ioctl(nsc->socket, FIONBIO, (caddr_t) &on);
|
return sCore->socket_ioctl(nsc->socket, FIONBIO, (caddr_t) &on);
|
||||||
}
|
}
|
||||||
|
|
||||||
case NET_STACK_SELECT:
|
|
||||||
/* if we get this opcode, we are using the r5 kernel select() call,
|
|
||||||
* so we can't use his notify_select_event(), but our own implementation! */
|
|
||||||
nsc->notify = r5_notify_select_event;
|
|
||||||
return net_stack_select(cookie, (args->u.select.ref & 0x0F),
|
|
||||||
args->u.select.ref, args->u.select.sync);
|
|
||||||
case NET_STACK_DESELECT:
|
|
||||||
return net_stack_deselect(cookie, (args->u.select.ref & 0x0F), args->u.select.sync);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (nsc->socket)
|
return sCore->socket_ioctl(nsc->socket, op, data);
|
||||||
// pass any unhandled opcode to the stack
|
}
|
||||||
return g_core->socket_ioctl(nsc->socket, op, data);
|
}
|
||||||
return B_BAD_VALUE;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
static status_t net_stack_read(void *cookie,
|
net_stack_read(void *cookie, off_t position, void *buffer, size_t *readlen)
|
||||||
off_t position,
|
|
||||||
void *buffer,
|
|
||||||
size_t *readlen)
|
|
||||||
{
|
{
|
||||||
net_stack_cookie * nsc = (net_stack_cookie *) cookie;
|
net_stack_cookie *nsc = (net_stack_cookie *) cookie;
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
int error;
|
int error;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
TRACE((LOGID "net_stack_read(%p, %Ld, %p, %ld)\n", cookie, position, buffer, *readlen));
|
TRACE("net_stack_read(%p, %Ld, %p, %ld)\n", cookie, position, buffer, *readlen);
|
||||||
|
|
||||||
#if STAY_LOADED
|
if (!nsc->socket)
|
||||||
TRACE((LOGID "Calling keep_driver_loaded()...\n"));
|
|
||||||
keep_driver_loaded();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (! nsc->socket)
|
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
iov.iov_base = buffer;
|
iov.iov_base = buffer;
|
||||||
iov.iov_len = *readlen;
|
iov.iov_len = *readlen;
|
||||||
|
|
||||||
error = g_core->socket_readv(nsc->socket, &iov, &flags);
|
error = sCore->socket_readv(nsc->socket, &iov, &flags);
|
||||||
*readlen = error;
|
*readlen = error;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
static status_t net_stack_write(void *cookie,
|
net_stack_write(void *cookie, off_t position, const void *buffer, size_t *writelen)
|
||||||
off_t position,
|
|
||||||
const void *buffer,
|
|
||||||
size_t *writelen)
|
|
||||||
{
|
{
|
||||||
net_stack_cookie * nsc = (net_stack_cookie *) cookie;
|
net_stack_cookie *nsc = (net_stack_cookie *) cookie;
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
int error;
|
int error;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
|
||||||
TRACE((LOGID "net_stack_write(%p, %Ld, %p, %ld)\n", cookie, position, buffer, *writelen));
|
TRACE("net_stack_write(%p, %Ld, %p, %ld)\n", cookie, position, buffer, *writelen);
|
||||||
|
|
||||||
#if STAY_LOADED
|
|
||||||
keep_driver_loaded();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (! nsc->socket) {
|
if (! nsc->socket) {
|
||||||
#if STAY_LOADED
|
if (*writelen >= strlen(kUnloadCommand)
|
||||||
if (*writelen >= strlen(UNLOAD_CMD) &&
|
&& strncmp(buffer, kUnloadCommand, strlen(kUnloadCommand)) == 0)
|
||||||
strncmp(buffer, UNLOAD_CMD, strlen(UNLOAD_CMD)) == 0)
|
|
||||||
// someone write/send/tell us to unload this driver, so do it!
|
|
||||||
return unload_driver();
|
return unload_driver();
|
||||||
#endif
|
// we are told to unload this driver
|
||||||
if (*writelen >= strlen(STOP_CMD) &&
|
|
||||||
strncmp(buffer, STOP_CMD, strlen(STOP_CMD)) == 0)
|
|
||||||
return g_core->stop();
|
|
||||||
|
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
};
|
}
|
||||||
|
|
||||||
iov.iov_base = (void*)buffer;
|
iov.iov_base = (void*) buffer;
|
||||||
iov.iov_len = *writelen;
|
iov.iov_len = *writelen;
|
||||||
|
|
||||||
error = g_core->socket_writev(nsc->socket, &iov, flags);
|
error = sCore->socket_writev(nsc->socket, &iov, flags);
|
||||||
*writelen = error;
|
*writelen = error;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
static status_t net_stack_select(void *cookie, uint8 event, uint32 ref, selectsync *sync)
|
net_stack_select(void *cookie, uint8 event, uint32 ref, selectsync *sync)
|
||||||
{
|
{
|
||||||
net_stack_cookie * nsc = (net_stack_cookie *) cookie;
|
net_stack_cookie * nsc = (net_stack_cookie *) cookie;
|
||||||
selecter * s;
|
selecter *s;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
TRACE((LOGID "net_stack_select(%p, %d, %ld, %p)\n", cookie, event, ref, sync));
|
TRACE("net_stack_select(%p, %d, %ld, %p)\n", cookie, event, ref, sync);
|
||||||
|
|
||||||
if (! nsc->socket)
|
if (!nsc->socket)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
// set notification function if undefined
|
|
||||||
if(nsc->notify == NULL)
|
|
||||||
nsc->notify = notify_select_event;
|
|
||||||
|
|
||||||
s = (selecter *) malloc(sizeof(selecter));
|
s = (selecter *) malloc(sizeof(selecter));
|
||||||
if (! s)
|
if (! s)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
@@ -565,15 +543,13 @@ static status_t net_stack_select(void *cookie, uint8 event, uint32 ref, selectsy
|
|||||||
s->event = event;
|
s->event = event;
|
||||||
s->sync = sync;
|
s->sync = sync;
|
||||||
s->ref = ref;
|
s->ref = ref;
|
||||||
s->notify = nsc->notify;
|
|
||||||
nsc->notify = NULL;
|
|
||||||
|
|
||||||
// lock the selecters list
|
// lock the selecters list
|
||||||
status = acquire_sem(nsc->selecters_lock);
|
status = acquire_sem(nsc->selecters_lock);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
free(s);
|
free(s);
|
||||||
return status;
|
return status;
|
||||||
};
|
}
|
||||||
|
|
||||||
// add it to selecters list
|
// add it to selecters list
|
||||||
s->next = nsc->selecters;
|
s->next = nsc->selecters;
|
||||||
@@ -583,20 +559,20 @@ static status_t net_stack_select(void *cookie, uint8 event, uint32 ref, selectsy
|
|||||||
release_sem(nsc->selecters_lock);
|
release_sem(nsc->selecters_lock);
|
||||||
|
|
||||||
// start (or continue) to monitor for socket event
|
// start (or continue) to monitor for socket event
|
||||||
return g_core->socket_set_event_callback(nsc->socket, on_socket_event, nsc, event);
|
return sCore->socket_set_event_callback(nsc->socket, on_socket_event, nsc, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
static status_t net_stack_deselect(void *cookie, uint8 event, selectsync *sync)
|
net_stack_deselect(void *cookie, uint8 event, selectsync *sync)
|
||||||
{
|
{
|
||||||
net_stack_cookie *nsc = (net_stack_cookie *) cookie;
|
net_stack_cookie *nsc = (net_stack_cookie *) cookie;
|
||||||
selecter * previous;
|
selecter *previous;
|
||||||
selecter * s;
|
selecter *s;
|
||||||
thread_id current_thread;
|
thread_id current_thread;
|
||||||
status_t status;
|
status_t status;
|
||||||
|
|
||||||
TRACE((LOGID "net_stack_deselect(%p, %d, %p)\n", cookie, event, sync));
|
TRACE("net_stack_deselect(%p, %d, %p)\n", cookie, event, sync);
|
||||||
|
|
||||||
if (!nsc || !nsc->socket)
|
if (!nsc || !nsc->socket)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -618,7 +594,7 @@ static status_t net_stack_deselect(void *cookie, uint8 event, selectsync *sync)
|
|||||||
|
|
||||||
previous = s;
|
previous = s;
|
||||||
s = s->next;
|
s = s->next;
|
||||||
};
|
}
|
||||||
|
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
// remove it from selecters list
|
// remove it from selecters list
|
||||||
@@ -627,33 +603,33 @@ static status_t net_stack_deselect(void *cookie, uint8 event, selectsync *sync)
|
|||||||
else
|
else
|
||||||
nsc->selecters = s->next;
|
nsc->selecters = s->next;
|
||||||
free(s);
|
free(s);
|
||||||
};
|
}
|
||||||
|
|
||||||
if (nsc->selecters == NULL)
|
if (nsc->selecters == NULL)
|
||||||
// selecters list is empty: no need to monitor socket events anymore
|
// selecters list is empty: no need to monitor socket events anymore
|
||||||
g_core->socket_set_event_callback(nsc->socket, NULL, NULL, event);
|
sCore->socket_set_event_callback(nsc->socket, NULL, NULL, event);
|
||||||
|
|
||||||
// unlock the selecters list
|
// unlock the selecters list
|
||||||
return release_sem(nsc->selecters_lock);
|
return release_sem(nsc->selecters_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
static void
|
||||||
|
on_socket_event(void * socket, uint32 event, void *cookie)
|
||||||
static void on_socket_event(void * socket, uint32 event, void * cookie)
|
|
||||||
{
|
{
|
||||||
net_stack_cookie * nsc = (net_stack_cookie *) cookie;
|
net_stack_cookie *nsc = (net_stack_cookie *) cookie;
|
||||||
selecter * s;
|
selecter *s;
|
||||||
|
|
||||||
if (!nsc)
|
if (!nsc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (nsc->socket != socket) {
|
if (nsc->socket != socket) {
|
||||||
TRACE((LOGID ERR "on_socket_event(%p, %ld, %p): socket is higly suspect! Aborting.\n", socket, event, cookie));
|
ERROR("on_socket_event(%p, %ld, %p): socket is higly suspect! Aborting.\n",
|
||||||
|
socket, event, cookie);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE((LOGID "on_socket_event(%p, %ld, %p)\n", socket, event, cookie));
|
TRACE("on_socket_event(%p, %ld, %p)\n", socket, event, cookie);
|
||||||
|
|
||||||
// lock the selecters list
|
// lock the selecters list
|
||||||
if (acquire_sem(nsc->selecters_lock) != B_OK)
|
if (acquire_sem(nsc->selecters_lock) != B_OK)
|
||||||
@@ -664,115 +640,22 @@ static void on_socket_event(void * socket, uint32 event, void * cookie)
|
|||||||
if (s->event == event)
|
if (s->event == event)
|
||||||
// notify this selecter (thread/event pair)
|
// notify this selecter (thread/event pair)
|
||||||
#ifdef COMPILE_FOR_R5
|
#ifdef COMPILE_FOR_R5
|
||||||
s->notify(s->sync, s->ref);
|
notify_select_event(s->sync, s->ref);
|
||||||
#else
|
#else
|
||||||
s->notify(s->sync, s->ref, event);
|
notify_select_event(s->sync, s->ref, event);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
s = s->next;
|
s = s->next;
|
||||||
};
|
}
|
||||||
|
|
||||||
// unlock the selecters list
|
// unlock the selecters list
|
||||||
release_sem(nsc->selecters_lock);
|
release_sem(nsc->selecters_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Under vanilla R5, we can't use the kernel notify_select_event(),
|
|
||||||
as select() kernel implementation is too buggy to be usefull.
|
|
||||||
So, here is our own notify_select_event() implementation, the driver-side pair
|
|
||||||
of the our libnet.so select() implementation...
|
|
||||||
*/
|
|
||||||
static status_t r5_notify_select_event(selectsync * sync, uint32 ref, uint8 event)
|
|
||||||
{
|
|
||||||
area_id area;
|
|
||||||
struct r5_selectsync * rss;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
TRACE((LOGID "r5_notify_select_event(%p, %ld, %d)\n", sync, ref, event));
|
static const char*
|
||||||
|
opcode_name(int op)
|
||||||
rss = NULL;
|
|
||||||
area = clone_area("r5_selectsync_area (driver)", (void **) &rss,
|
|
||||||
B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA, (area_id) sync);
|
|
||||||
if (area < B_OK) {
|
|
||||||
TRACE((LOGID "r5_notify_select_event: clone_area(%d) failed -> %d!\n", (int) sync, (int) area));
|
|
||||||
return area;
|
|
||||||
};
|
|
||||||
|
|
||||||
TRACE((LOGID "r5_selectsync at %p (area %ld, clone from %ld):\n"
|
|
||||||
"lock %ld\n"
|
|
||||||
"wakeup %ld\n", rss, area, (area_id) sync, rss->lock, rss->wakeup));
|
|
||||||
|
|
||||||
if (acquire_sem(rss->lock) != B_OK)
|
|
||||||
// if we can't (anymore?) lock the shared r5_selectsync, select() party is done
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
fd = ref >> 8;
|
|
||||||
switch (ref & 0xFF) { // event == ref & 0xFF
|
|
||||||
case B_SELECT_READ:
|
|
||||||
FD_SET(fd, &rss->rbits);
|
|
||||||
break;
|
|
||||||
case B_SELECT_WRITE:
|
|
||||||
FD_SET(fd, &rss->wbits);
|
|
||||||
break;
|
|
||||||
case B_SELECT_ERROR:
|
|
||||||
FD_SET(fd, &rss->ebits);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
// wakeup select()
|
|
||||||
release_sem(rss->wakeup);
|
|
||||||
|
|
||||||
release_sem(rss->lock);
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
error:
|
|
||||||
delete_area(area);
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
#if STAY_LOADED
|
|
||||||
static status_t keep_driver_loaded()
|
|
||||||
{
|
|
||||||
if ( g_stay_loaded_fd != -1 )
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
/* force the driver to stay loaded by opening himself */
|
|
||||||
TRACE((LOGID "keep_driver_loaded: internaly opening " NET_STACK_DRIVER_PATH " to stay loaded in memory...\n"));
|
|
||||||
|
|
||||||
g_stay_loaded_fd = open(NET_STACK_DRIVER_PATH, 0);
|
|
||||||
|
|
||||||
if (g_stay_loaded_fd < 0)
|
|
||||||
TRACE((LOGID ERR "keep_driver_loaded: couldn't open(" NET_STACK_DRIVER_PATH ")!\n"));
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static status_t unload_driver()
|
|
||||||
{
|
|
||||||
if ( g_stay_loaded_fd >= 0 ) {
|
|
||||||
int tmp_fd;
|
|
||||||
|
|
||||||
/* we need to set g_stay_loaded_fd to < 0 if we don't want
|
|
||||||
* the next close enter again in this case, and so on...
|
|
||||||
*/
|
|
||||||
TRACE((LOGID "unload_driver: unload requested.\n"));
|
|
||||||
|
|
||||||
tmp_fd = g_stay_loaded_fd;
|
|
||||||
g_stay_loaded_fd = -1;
|
|
||||||
|
|
||||||
close(tmp_fd);
|
|
||||||
};
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
#endif /* STAY_LOADED */
|
|
||||||
|
|
||||||
|
|
||||||
static const char * opcode_name(int op)
|
|
||||||
{
|
{
|
||||||
#define C2N(op) { op, #op }
|
#define C2N(op) { op, #op }
|
||||||
// op-code to name
|
// op-code to name
|
||||||
@@ -798,7 +681,6 @@ static const char * opcode_name(int op)
|
|||||||
C2N(NET_STACK_SELECT),
|
C2N(NET_STACK_SELECT),
|
||||||
C2N(NET_STACK_DESELECT),
|
C2N(NET_STACK_DESELECT),
|
||||||
C2N(NET_STACK_GET_COOKIE),
|
C2N(NET_STACK_GET_COOKIE),
|
||||||
C2N(NET_STACK_STOP),
|
|
||||||
C2N(NET_STACK_NOTIFY_SOCKET_EVENT),
|
C2N(NET_STACK_NOTIFY_SOCKET_EVENT),
|
||||||
C2N(NET_STACK_CONTROL_NET_MODULE),
|
C2N(NET_STACK_CONTROL_NET_MODULE),
|
||||||
|
|
||||||
@@ -825,6 +707,3 @@ static const char * opcode_name(int op)
|
|||||||
|
|
||||||
return "???";
|
return "???";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user