* Changed the way the socket functions work:

- The net_stack driver is no longer used. Instead we have a kernel
    module which is directly used by syscall implementations in the
    kernel. I.e. we no longer tunnel those functions through ioctls, but
    have normal syscalls.
  - Removed the superfluous net starter module.
  - Implemented the FDTYPE_SOCKET type file_descriptors, that is sockets
    are no longer vnode based.
  - Adjusted libnetwork (the socket function implementations)
    accordingly.
  - Adjusted netstat accordingly.
* Socket module:
  - Implemented socketpair().
  - Added "kernel" parameter to the control hook. Quite a few more hooks
    would actually need the parameter, but I didn't change those yet,
    since that would probably also require changes to the protocol
    module interface.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24908 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-04-11 04:12:23 +00:00
parent 446d50a652
commit df50f7a9b4
17 changed files with 1831 additions and 280 deletions
+1 -1
View File
@@ -125,7 +125,7 @@ BEOS_ADD_ONS_DRIVERS_GRAPHICS = $(X86_ONLY)radeon $(X86_ONLY)nvidia
;
BEOS_ADD_ONS_DRIVERS_MIDI = emuxki ;
BEOS_ADD_ONS_DRIVERS_NET = $(X86_ONLY)3com etherpci $(X86_ONLY)ipro1000
$(X86_ONLY)rtl8139 rtl8169 sis900 $(X86_ONLY)via_rhine wb840 net_stack
$(X86_ONLY)rtl8139 rtl8169 sis900 $(X86_ONLY)via_rhine wb840
$(X86_ONLY)ipro100 $(X86_ONLY)nforce #vlance
$(X86_ONLY)marvell_yukon $(X86_ONLY)syskonnect
$(GPL_ONLY)bcm440x $(GPL_ONLY)bcm570x
+40
View File
@@ -12,6 +12,7 @@
#include <DiskDeviceDefs.h>
#include <signal.h>
#include <sys/socket.h>
#ifdef __cplusplus
@@ -23,6 +24,7 @@ struct fd_info;
struct fd_set;
struct fs_info;
struct iovec;
struct net_stat;
struct pollfd;
struct rlimit;
struct sigaction;
@@ -222,6 +224,44 @@ extern status_t _kern_unlock_node(int fd);
extern status_t _kern_get_next_fd_info(team_id team, uint32 *_cookie,
struct fd_info *info, size_t infoSize);
// socket functions
extern int _kern_socket(int family, int type, int protocol);
extern status_t _kern_bind(int socket, const struct sockaddr *address,
socklen_t addressLength);
extern status_t _kern_shutdown_socket(int socket, int how);
extern status_t _kern_connect(int socket, const struct sockaddr *address,
socklen_t addressLength);
extern status_t _kern_listen(int socket, int backlog);
extern int _kern_accept(int socket, struct sockaddr *address,
socklen_t *_addressLength);
extern ssize_t _kern_recv(int socket, void *data, size_t length,
int flags);
extern ssize_t _kern_recvfrom(int socket, void *data, size_t length,
int flags, struct sockaddr *address,
socklen_t *_addressLength);
extern ssize_t _kern_recvmsg(int socket, struct msghdr *message,
int flags);
extern ssize_t _kern_send(int socket, const void *data, size_t length,
int flags);
extern ssize_t _kern_sendto(int socket, const void *data, size_t length,
int flags, const struct sockaddr *address,
socklen_t addressLength);
extern ssize_t _kern_sendmsg(int socket, const struct msghdr *message,
int flags);
extern status_t _kern_getsockopt(int socket, int level, int option,
void *value, socklen_t *_length);
extern status_t _kern_setsockopt(int socket, int level, int option,
const void *value, socklen_t length);
extern status_t _kern_getpeername(int socket, struct sockaddr *address,
socklen_t *_addressLength);
extern status_t _kern_getsockname(int socket, struct sockaddr *address,
socklen_t *_addressLength);
extern int _kern_sockatmark(int socket);
extern status_t _kern_socketpair(int family, int type, int protocol,
int *socketVector);
extern status_t _kern_get_next_socket_stat(int family, uint32 *cookie,
struct net_stat *stat);
// node monitor functions
extern status_t _kern_stop_notifying(port_id port, uint32 token);
extern status_t _kern_start_watching(dev_t device, ino_t node, uint32 flags,
+44 -4
View File
@@ -17,6 +17,7 @@
#include <dirent.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/select.h>
@@ -28,12 +29,13 @@
#define B_UNMOUNT_BUSY_PARTITION 0x80000000
struct kernel_args;
struct vm_cache;
struct file_descriptor;
struct kernel_args;
struct net_stat;
struct pollfd;
struct selectsync;
struct select_info;
struct pollfd;
struct vm_cache;
struct vnode;
@@ -197,7 +199,7 @@ status_t _user_change_root(const char *path);
int _user_open_query(dev_t device, const char *query, size_t queryLength, uint32 flags,
port_id port, int32 token);
/* fd user prototypes (implementation located in fd.c) */
/* fd user prototypes (implementation located in fd.cpp) */
extern ssize_t _user_read(int fd, off_t pos, void *buffer, size_t bufferSize);
extern ssize_t _user_readv(int fd, off_t pos, const iovec *vecs, size_t count);
extern ssize_t _user_write(int fd, off_t pos, const void *buffer, size_t bufferSize);
@@ -211,6 +213,44 @@ extern int _user_dup2(int ofd, int nfd);
extern status_t _user_lock_node(int fd);
extern status_t _user_unlock_node(int fd);
/* socket user prototypes (implementation in socket.cpp) */
extern int _user_socket(int family, int type, int protocol);
extern status_t _user_bind(int socket, const struct sockaddr *address,
socklen_t addressLength);
extern status_t _user_shutdown_socket(int socket, int how);
extern status_t _user_connect(int socket, const struct sockaddr *address,
socklen_t addressLength);
extern status_t _user_listen(int socket, int backlog);
extern int _user_accept(int socket, struct sockaddr *address,
socklen_t *_addressLength);
extern ssize_t _user_recv(int socket, void *data, size_t length,
int flags);
extern ssize_t _user_recvfrom(int socket, void *data, size_t length,
int flags, struct sockaddr *address,
socklen_t *_addressLength);
extern ssize_t _user_recvmsg(int socket, struct msghdr *message,
int flags);
extern ssize_t _user_send(int socket, const void *data, size_t length,
int flags);
extern ssize_t _user_sendto(int socket, const void *data, size_t length,
int flags, const struct sockaddr *address,
socklen_t addressLength);
extern ssize_t _user_sendmsg(int socket, const struct msghdr *message,
int flags);
extern status_t _user_getsockopt(int socket, int level, int option,
void *value, socklen_t *_length);
extern status_t _user_setsockopt(int socket, int level, int option,
const void *value, socklen_t length);
extern status_t _user_getpeername(int socket, struct sockaddr *address,
socklen_t *_addressLength);
extern status_t _user_getsockname(int socket, struct sockaddr *address,
socklen_t *_addressLength);
extern int _user_sockatmark(int socket);
extern status_t _user_socketpair(int family, int type, int protocol,
int *socketVector);
extern status_t _user_get_next_socket_stat(int family, uint32 *cookie,
struct net_stat *stat);
/* vfs entry points... */
#ifdef __cplusplus
+4 -2
View File
@@ -53,7 +53,7 @@ struct net_socket_module_info {
status_t (*writev)(net_socket *socket, const iovec *vecs,
size_t vecCount, size_t *_length);
status_t (*control)(net_socket *socket, int32 op, void *data,
size_t length);
size_t length, bool kernel);
ssize_t (*read_avail)(net_socket *socket);
ssize_t (*send_avail)(net_socket *socket);
@@ -81,7 +81,7 @@ struct net_socket_module_info {
// notifications
status_t (*request_notification)(net_socket *socket, uint8 event,
uint32 ref, struct selectsync *sync);
struct selectsync *sync);
status_t (*cancel_notification)(net_socket *socket, uint8 event,
struct selectsync *sync);
status_t (*notify)(net_socket *socket, uint8 event, int32 value);
@@ -107,6 +107,8 @@ struct net_socket_module_info {
int (*setsockopt)(net_socket *socket, int level, int option,
const void *optionValue, int optionLength);
int (*shutdown)(net_socket *socket, int direction);
status_t (*socketpair)(int family, int type, int protocol,
net_socket* _sockets[2]);
};
#endif // NET_SOCKET_H
+83
View File
@@ -0,0 +1,83 @@
/*
* Copyright 2008, Haiku, Inc. All Rights Reserved.
* This file may be used under the terms of the MIT License.
*/
#ifndef NET_STACK_INTERFACE_H
#define NET_STACK_INTERFACE_H
#include <sys/socket.h>
// name of the kernel stack interface
#define NET_STACK_INTERFACE_MODULE_NAME "network/stack/kernel_interface/v1"
// name of the userland stack interface
#define NET_STACK_USERLAND_INTERFACE_MODULE_NAME \
"network/stack/userland_interface/v1"
struct net_socket;
struct net_stat;
struct net_stack_interface_module_info {
module_info info;
status_t (*open)(int family, int type, int protocol, net_socket** _socket);
status_t (*close)(net_socket* socket);
status_t (*free)(net_socket* socket);
status_t (*bind)(net_socket* socket, const struct sockaddr* address,
socklen_t addressLength, bool kernel);
status_t (*shutdown)(net_socket* socket, int how);
status_t (*connect)(net_socket* socket, const struct sockaddr* address,
socklen_t addressLength, bool kernel);
status_t (*listen)(net_socket* socket, int backlog);
status_t (*accept)(net_socket* socket, struct sockaddr* address,
socklen_t* _addressLength, net_socket** _acceptedSocket);
ssize_t (*recv)(net_socket* socket, void* data, size_t length, int flags,
bool kernel);
ssize_t (*recvfrom)(net_socket* socket, void* data, size_t length,
int flags, struct sockaddr* address,
socklen_t* _addressLength, bool kernel);
ssize_t (*recvmsg)(net_socket* socket, struct msghdr* message, int flags,
bool kernel);
ssize_t (*send)(net_socket* socket, const void* data, size_t length,
int flags, bool kernel);
ssize_t (*sendto)(net_socket* socket, const void* data, size_t length,
int flags, const struct sockaddr* address,
socklen_t addressLength, bool kernel);
ssize_t (*sendmsg)(net_socket* socket, const struct msghdr* message,
int flags, bool kernel);
status_t (*getsockopt)(net_socket* socket, int level, int option,
void* value, socklen_t* _length);
status_t (*setsockopt)(net_socket* socket, int level, int option,
const void* value, socklen_t length);
status_t (*getpeername)(net_socket* socket, struct sockaddr* address,
socklen_t* _addressLength);
status_t (*getsockname)(net_socket* socket, struct sockaddr* address,
socklen_t* _addressLength);
int (*sockatmark)(net_socket* socket);
status_t (*socketpair)(int family, int type, int protocol,
net_socket* _sockets[2]);
status_t (*ioctl)(net_socket* socket, uint32 op, void *buffer,
size_t length, bool kernel);
status_t (*select)(net_socket* socket, uint8 event,
struct selectsync *sync);
status_t (*deselect)(net_socket* socket, uint8 event,
struct selectsync *sync);
status_t (*get_next_socket_stat)(int family, uint32 *cookie,
struct net_stat *stat);
};
#endif // NET_STACK_INTERFACE_H
+1
View File
@@ -24,6 +24,7 @@ KernelAddon stack :
radix.c
routes.cpp
stack.cpp
stack_interface.cpp
utility.cpp
;
@@ -270,7 +270,7 @@ create_interface(net_domain *domain, const char *name, const char *baseName,
// Grab a reference to the networking stack, to make sure it won't be
// unloaded as long as an interface exists
module_info *module;
get_module(NET_STARTER_MODULE_NAME, &module);
get_module(gNetStackInterfaceModule.info.name, &module);
*_interface = interface;
return B_OK;
@@ -320,7 +320,7 @@ delete_interface(net_interface_private *interface)
// Release reference of the stack - at this point, our stack may be unloaded
// if no other interfaces or sockets are left
put_module(NET_STARTER_MODULE_NAME);
put_module(gNetStackInterfaceModule.info.name);
}
+100 -11
View File
@@ -9,21 +9,26 @@
#include "stack_private.h"
#include <net_protocol.h>
#include <net_stack.h>
#include <net_stat.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <new>
#include <Drivers.h>
#include <KernelExport.h>
#include <Select.h>
#include <team.h>
#include <util/AutoLock.h>
#include <util/list.h>
#include <fs/select_sync_pool.h>
#include <new>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <fs/select_sync_pool.h>
#include <kernel.h>
#include <net_protocol.h>
#include <net_stack.h>
#include <net_stat.h>
struct net_socket_private : net_socket {
@@ -42,6 +47,8 @@ struct net_socket_private : net_socket {
void socket_delete(net_socket *socket);
int socket_bind(net_socket *socket, const struct sockaddr *address,
socklen_t addressLength);
int socket_setsockopt(net_socket *socket, int level, int option,
const void *value, int length);
struct list sSocketList;
@@ -236,8 +243,37 @@ socket_writev(net_socket *socket, const iovec *vecs, size_t vecCount,
status_t
socket_control(net_socket *socket, int32 op, void *data, size_t length)
socket_control(net_socket *socket, int32 op, void *data, size_t length,
bool kernel)
{
switch (op) {
case FIONBIO:
{
if (data == NULL)
return B_BAD_VALUE;
int value;
if (kernel) {
value = *(int*)data;
} else {
if (!IS_USER_ADDRESS(data)
|| user_memcpy(&value, data, sizeof(int)) != B_OK) {
return B_BAD_ADDRESS;
}
}
return socket_setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &value,
sizeof(int));
}
case B_SET_BLOCKING_IO:
case B_SET_NONBLOCKING_IO:
{
int value = op == B_SET_NONBLOCKING_IO;
return socket_setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &value,
sizeof(int));
}
}
return socket->first_info->control(socket->first_protocol,
LEVEL_DRIVER_IOCTL, op, data, &length);
}
@@ -499,8 +535,7 @@ socket_connected(net_socket *socket)
status_t
socket_request_notification(net_socket *_socket, uint8 event, uint32 ref,
selectsync *sync)
socket_request_notification(net_socket *_socket, uint8 event, selectsync *sync)
{
net_socket_private *socket = (net_socket_private *)_socket;
@@ -1177,6 +1212,59 @@ socket_shutdown(net_socket *socket, int direction)
}
status_t
socket_socketpair(int family, int type, int protocol, net_socket* sockets[2])
{
sockets[0] = NULL;
sockets[1] = NULL;
// create sockets
status_t error = socket_open(family, type, protocol, &sockets[0]);
if (error != B_OK)
return error;
if (error == B_OK)
error = socket_open(family, type, protocol, &sockets[1]);
// bind one
if (error == B_OK)
error = socket_bind(sockets[0], NULL, 0);
// start listening
if (error == B_OK)
error = socket_listen(sockets[0], 1);
// connect them
if (error == B_OK) {
error = socket_connect(sockets[1], (sockaddr*)&sockets[0]->address,
sockets[0]->address.ss_len);
}
// accept a socket
net_socket* acceptedSocket = NULL;
if (error == B_OK)
error = socket_accept(sockets[0], NULL, NULL, &acceptedSocket);
if (error == B_OK) {
// everything worked: close the listener socket
socket_close(sockets[0]);
socket_free(sockets[0]);
sockets[0] = acceptedSocket;
} else {
// close sockets on error
for (int i = 0; i < 2; i++) {
if (sockets[i] != NULL) {
socket_close(sockets[i]);
socket_free(sockets[i]);
sockets[i] = NULL;
}
}
}
return error;
}
// #pragma mark -
@@ -1254,5 +1342,6 @@ net_socket_module_info gNetSocketModule = {
socket_send,
socket_setsockopt,
socket_shutdown,
socket_socketpair
};
+2 -23
View File
@@ -737,7 +737,7 @@ scan_modules(const char *path)
}
static status_t
status_t
init_stack()
{
status_t status = init_domains();
@@ -858,21 +858,6 @@ uninit_stack()
}
static status_t
starter_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
return init_stack();
case B_MODULE_UNINIT:
return uninit_stack();
default:
return B_ERROR;
}
}
static status_t
stack_std_ops(int32 op, ...)
{
@@ -938,18 +923,12 @@ net_stack_module_info gNetStackModule = {
restore_syscall_restart_timeout,
};
static module_info sNetStarterModule = {
NET_STARTER_MODULE_NAME,
0,
starter_std_ops
};
module_info *modules[] = {
(module_info *)&gNetStackModule,
(module_info *)&sNetStarterModule,
(module_info *)&gNetBufferModule,
(module_info *)&gNetSocketModule,
(module_info *)&gNetDatalinkModule,
(module_info *)&gLinkModule,
(module_info *)&gNetStackInterfaceModule,
NULL
};
@@ -0,0 +1,306 @@
#include "stack_private.h"
/* Interface module providing networking to the kernel.
*/
static status_t
stack_interface_open(int family, int type, int protocol, net_socket** _socket)
{
return gNetSocketModule.open_socket(family, type, protocol, _socket);
}
static status_t
stack_interface_close(net_socket* socket)
{
return gNetSocketModule.close(socket);
}
static status_t
stack_interface_free(net_socket* socket)
{
return gNetSocketModule.free(socket);
}
static status_t
stack_interface_bind(net_socket* socket, const struct sockaddr* address,
socklen_t addressLength, bool kernel)
{
// TODO: Pass kernel flag!
return gNetSocketModule.bind(socket, address, addressLength);
}
static status_t
stack_interface_shutdown(net_socket* socket, int how)
{
return gNetSocketModule.shutdown(socket, how);
}
static status_t
stack_interface_connect(net_socket* socket, const struct sockaddr* address,
socklen_t addressLength, bool kernel)
{
// TODO: Pass kernel flag!
return gNetSocketModule.connect(socket, address, addressLength);
}
static status_t
stack_interface_listen(net_socket* socket, int backlog)
{
return gNetSocketModule.listen(socket, backlog);
}
static status_t
stack_interface_accept(net_socket* socket, struct sockaddr* address,
socklen_t* _addressLength, net_socket** _acceptedSocket)
{
return gNetSocketModule.accept(socket, address, _addressLength,
_acceptedSocket);
}
static ssize_t
stack_interface_recv(net_socket* socket, void* data, size_t length, int flags,
bool kernel)
{
// TODO: Pass kernel flag!
return gNetSocketModule.receive(socket, NULL, data, length, flags);
}
static ssize_t
stack_interface_recvfrom(net_socket* socket, void* data, size_t length,
int flags, struct sockaddr* address, socklen_t* _addressLength, bool kernel)
{
msghdr message;
iovec vecs[1] = { { data, length } };
message.msg_name = address;
message.msg_namelen = *_addressLength;
message.msg_iov = vecs;
message.msg_iovlen = 1;
message.msg_control = NULL;
message.msg_controllen = 0;
message.msg_flags = 0;
// TODO: Pass kernel flag!
status_t error = gNetSocketModule.receive(socket, &message, data, length,
flags);
if (error != B_OK)
return error;
*_addressLength = message.msg_namelen;
return B_OK;
}
static ssize_t
stack_interface_recvmsg(net_socket* socket, struct msghdr* message, int flags,
bool kernel)
{
void* buffer = NULL;
size_t len = 0;
if (message->msg_iovlen > 0) {
buffer = message->msg_iov[0].iov_base;
len = message->msg_iov[0].iov_len;
}
// TODO: Pass kernel flag!
return gNetSocketModule.receive(socket, message, buffer, len, flags);
}
static ssize_t
stack_interface_send(net_socket* socket, const void* data, size_t length,
int flags, bool kernel)
{
// TODO: Pass kernel flag!
return gNetSocketModule.send(socket, NULL, data, length, flags);
}
static ssize_t
stack_interface_sendto(net_socket* socket, const void* data, size_t length,
int flags, const struct sockaddr* address, socklen_t addressLength,
bool kernel)
{
msghdr message;
iovec vecs[1] = { { (void*)data, length } };
message.msg_name = (void*)address;
message.msg_namelen = addressLength;
message.msg_iov = vecs;
message.msg_iovlen = 1;
message.msg_control = NULL;
message.msg_controllen = 0;
message.msg_flags = 0;
// TODO: Pass kernel flag!
return gNetSocketModule.send(socket, &message, data, length, flags);
}
static ssize_t
stack_interface_sendmsg(net_socket* socket, const struct msghdr* message,
int flags, bool kernel)
{
void* buffer = NULL;
size_t len = 0;
if (message->msg_iovlen > 0) {
buffer = message->msg_iov[0].iov_base;
len = message->msg_iov[0].iov_len;
}
// TODO: Pass kernel flag!
return gNetSocketModule.send(socket, (msghdr*)message, buffer, len, flags);
}
static status_t
stack_interface_getsockopt(net_socket* socket, int level, int option,
void* value, socklen_t* _length)
{
int length = *_length;
status_t error = gNetSocketModule.getsockopt(socket, level, option, value,
&length);
*_length = length;
return error;
}
static status_t
stack_interface_setsockopt(net_socket* socket, int level, int option,
const void* value, socklen_t length)
{
return gNetSocketModule.setsockopt(socket, level, option, value, length);
}
static status_t
stack_interface_getpeername(net_socket* socket, struct sockaddr* address,
socklen_t* _addressLength)
{
return gNetSocketModule.getpeername(socket, address, _addressLength);
}
static status_t
stack_interface_getsockname(net_socket* socket, struct sockaddr* address,
socklen_t* _addressLength)
{
return gNetSocketModule.getsockname(socket, address, _addressLength);
}
static int
stack_interface_sockatmark(net_socket* socket)
{
// TODO:...
return B_UNSUPPORTED;
}
static status_t
stack_interface_socketpair(int family, int type, int protocol,
net_socket* _sockets[2])
{
return gNetSocketModule.socketpair(family, type, protocol, _sockets);
}
static status_t
stack_interface_ioctl(net_socket* socket, uint32 op, void *buffer,
size_t length, bool kernel)
{
return gNetSocketModule.control(socket, op, buffer, length, kernel);
}
static status_t
stack_interface_select(net_socket* socket, uint8 event, struct selectsync *sync)
{
return gNetSocketModule.request_notification(socket, event, sync);
}
static status_t
stack_interface_deselect(net_socket* socket, uint8 event,
struct selectsync *sync)
{
return gNetSocketModule.cancel_notification(socket, event, sync);
}
status_t
stack_interface_get_next_socket_stat(int family, uint32 *cookie,
struct net_stat *stat)
{
return gNetSocketModule.get_next_stat(cookie, family, stat);
}
static status_t
stack_interface_std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
return init_stack();
case B_MODULE_UNINIT:
return uninit_stack();
default:
return B_ERROR;
}
}
net_stack_interface_module_info gNetStackInterfaceModule = {
{
NET_STACK_INTERFACE_MODULE_NAME,
0,
stack_interface_std_ops
},
&stack_interface_open,
&stack_interface_close,
&stack_interface_free,
&stack_interface_bind,
&stack_interface_shutdown,
&stack_interface_connect,
&stack_interface_listen,
&stack_interface_accept,
&stack_interface_recv,
&stack_interface_recvfrom,
&stack_interface_recvmsg,
&stack_interface_send,
&stack_interface_sendto,
&stack_interface_sendmsg,
&stack_interface_getsockopt,
&stack_interface_setsockopt,
&stack_interface_getpeername,
&stack_interface_getsockname,
&stack_interface_sockatmark,
&stack_interface_socketpair,
&stack_interface_ioctl,
&stack_interface_select,
&stack_interface_deselect,
&stack_interface_get_next_socket_stat
};
@@ -15,15 +15,15 @@
#include <net_protocol.h>
#include <net_socket.h>
#include <net_stack.h>
#include <net_stack_interface.h>
#define NET_STARTER_MODULE_NAME "network/stack/starter/v1"
extern net_stack_module_info gNetStackModule;
extern net_buffer_module_info gNetBufferModule;
extern net_socket_module_info gNetSocketModule;
extern net_datalink_module_info gNetDatalinkModule;
extern net_datalink_protocol_module_info gDatalinkInterfaceProtocolModule;
extern net_stack_interface_module_info gNetStackInterfaceModule;
// stack.cpp
status_t register_domain_datalink_protocols(int family, int type, ...);
@@ -33,4 +33,7 @@ status_t put_domain_protocols(net_socket *socket);
status_t get_domain_datalink_protocols(net_interface *interface);
status_t put_domain_datalink_protocols(net_interface *interface);
status_t init_stack();
status_t uninit_stack();
#endif // STACK_PRIVATE_H
+1
View File
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src bin network netstat ;
UsePrivateHeaders net ;
UsePrivateKernelHeaders ; # for syscalls.h
BinCommand netstat :
netstat.cpp
+10 -36
View File
@@ -7,23 +7,21 @@
* James Woodcock
*/
#include <SupportDefs.h>
#include <net_stack_driver.h>
#include <net_stat.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in.h>
#include <errno.h>
#include <getopt.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <SupportDefs.h>
#include <net_stat.h>
#include <syscalls.h>
extern const char* __progname;
@@ -110,22 +108,6 @@ usage(int status)
}
status_t
get_next_stat(int stack, uint32& cookie, int family, net_stat& stat)
{
get_next_stat_args args;
args.cookie = cookie;
args.family = family;
if (ioctl(stack, NET_STACK_GET_NEXT_STAT, &args, sizeof(args)) < 0)
return errno;
cookie = args.cookie;
memcpy(&stat, &args.stat, sizeof(net_stat));
return B_OK;
}
bool
get_address_family(const char* argument, int32& familyIndex)
{
@@ -177,13 +159,6 @@ main(int argc, char** argv)
}
} while (opt != -1);
int stack = open(NET_STACK_DRIVER_PATH, O_RDWR);
if (stack < 0) {
fprintf(stderr, "%s: The networking stack doesn't seem to be "
"available.\n", kProgramName);
return -1;
}
bool printProgram = true;
// TODO: add some more program options... :-)
@@ -193,7 +168,7 @@ main(int argc, char** argv)
uint32 cookie = 0;
int family = -1;
net_stat stat;
while (get_next_stat(stack, cookie, family, stat) == B_OK) {
while (_kern_get_next_socket_stat(family, &cookie, &stat) == B_OK) {
protoent* proto = getprotobynumber(stat.protocol);
if (proto != NULL)
printf("%-6s ", proto->p_name);
@@ -226,7 +201,6 @@ main(int argc, char** argv)
printf("%ld\n", stat.owner);
}
close(stack);
return 0;
}
+2 -1
View File
@@ -1,6 +1,7 @@
SubDir HAIKU_TOP src kits network ;
UsePrivateHeaders libroot net ;
UsePrivateHeaders libroot net shared ;
UsePrivateKernelHeaders ;
local services = [ FGristFiles services ] ;
SEARCH on $(services) = [ FDirName $(SUBDIR) dns defaults ] ;
+79 -197
View File
@@ -18,19 +18,9 @@
#include <sys/ioctl.h>
#include <unistd.h>
#include <syscall_utils.h>
// TODO: this is meant for debugging purposes only, and should be disabled later
static char *
stack_driver_path(void)
{
// user-defined stack driver path?
char *path = getenv("NET_STACK_DRIVER_PATH");
if (path != NULL)
return path;
// use the default stack driver path
return NET_STACK_DRIVER_PATH;
}
#include <syscalls.h>
static inline bool
@@ -171,24 +161,10 @@ convert_from_r5_sockopt(int& level, int& option)
extern "C" int
socket(int family, int type, int protocol)
{
int socket = open(stack_driver_path(), O_RDWR);
if (socket < 0)
return -1;
if (check_r5_compatibility())
convert_from_r5_socket(family, type, protocol);
socket_args args;
args.family = family;
args.type = type;
args.protocol = protocol;
if (ioctl(socket, NET_STACK_SOCKET, &args, sizeof(args)) < 0) {
close(socket);
return -1;
}
return socket;
RETURN_AND_SET_ERRNO(_kern_socket(family, type, protocol));
}
@@ -203,18 +179,14 @@ bind(int socket, const struct sockaddr *address, socklen_t addressLength)
addressLength = sizeof(struct sockaddr_in);
}
sockaddr_args args;
args.address = const_cast<struct sockaddr *>(address);
args.address_length = addressLength;
return ioctl(socket, NET_STACK_BIND, &args, sizeof(args));
RETURN_AND_SET_ERRNO(_kern_bind(socket, address, addressLength));
}
extern "C" int
shutdown(int socket, int how)
{
return ioctl(socket, NET_STACK_SHUTDOWN, (void *)how, 0);
RETURN_AND_SET_ERRNO(_kern_shutdown_socket(socket, how));
}
@@ -229,53 +201,46 @@ connect(int socket, const struct sockaddr *address, socklen_t addressLength)
addressLength = sizeof(struct sockaddr_in);
}
sockaddr_args args;
args.address = const_cast<struct sockaddr *>(address);
args.address_length = addressLength;
return ioctl(socket, NET_STACK_CONNECT, &args, sizeof(args));
RETURN_AND_SET_ERRNO(_kern_connect(socket, address, addressLength));
}
extern "C" int
listen(int socket, int backlog)
{
return ioctl(socket, NET_STACK_LISTEN, (void *)backlog, 0);
RETURN_AND_SET_ERRNO(_kern_listen(socket, backlog));
}
extern "C" int
accept(int socket, struct sockaddr *address, socklen_t *_addressLength)
accept(int socket, struct sockaddr *_address, socklen_t *_addressLength)
{
int acceptSocket = open(stack_driver_path(), O_RDWR);
if (acceptSocket < 0)
return -1;
bool r5compatible = check_r5_compatibility();
struct sockaddr r5addr;
accept_args args;
args.accept_socket = acceptSocket;
sockaddr* address;
socklen_t addressLength;
if (r5compatible && address != NULL) {
args.address = &r5addr;
args.address_length = sizeof(r5addr);
if (r5compatible && _address != NULL) {
address = &r5addr;
addressLength = sizeof(r5addr);
} else {
args.address = address;
args.address_length = _addressLength ? *_addressLength : 0;
address = _address;
addressLength = _addressLength ? *_addressLength : 0;
}
if (ioctl(socket, NET_STACK_ACCEPT, &args, sizeof(args)) < 0) {
close(acceptSocket);
int acceptSocket = _kern_accept(socket, address, &addressLength);
if (acceptSocket < 0) {
errno = acceptSocket;
return -1;
}
if (r5compatible && address != NULL) {
convert_to_r5_sockaddr(address, &r5addr);
if (r5compatible && _address != NULL) {
convert_to_r5_sockaddr(_address, &r5addr);
if (_addressLength != NULL)
*_addressLength = sizeof(struct r5_sockaddr_in);
} else if (_addressLength != NULL)
*_addressLength = args.address_length;
*_addressLength = addressLength;
return acceptSocket;
}
@@ -284,50 +249,41 @@ accept(int socket, struct sockaddr *address, socklen_t *_addressLength)
extern "C" ssize_t
recv(int socket, void *data, size_t length, int flags)
{
message_args args;
args.data = data;
args.length = length;
args.flags = flags;
args.header = NULL;
return ioctl(socket, NET_STACK_RECEIVE, &args, sizeof(args));
RETURN_AND_SET_ERRNO(_kern_recv(socket, data, length, flags));
}
extern "C" ssize_t
recvfrom(int socket, void *data, size_t length, int flags,
struct sockaddr *address, socklen_t *_addressLength)
struct sockaddr *_address, socklen_t *_addressLength)
{
bool r5compatible = check_r5_compatibility();
struct sockaddr r5addr;
message_args args;
args.data = data;
args.length = length;
args.flags = flags;
sockaddr* address;
socklen_t addressLength;
msghdr header;
memset(&header, 0, sizeof(header));
args.header = &header;
if (r5compatible) {
header.msg_name = (char *)&r5addr;
header.msg_namelen = sizeof(r5addr);
if (r5compatible && _address != NULL) {
address = &r5addr;
addressLength = sizeof(r5addr);
} else {
header.msg_name = (char *)address;
header.msg_namelen = _addressLength ? *_addressLength : 0;
address = _address;
addressLength = _addressLength ? *_addressLength : 0;
}
ssize_t bytesReceived = ioctl(socket, NET_STACK_RECEIVE, &args, sizeof(args));
if (bytesReceived < 0)
ssize_t bytesReceived = _kern_recvfrom(socket, data, length, flags,
address, &addressLength);
if (bytesReceived < 0) {
errno = bytesReceived;
return -1;
}
if (r5compatible) {
convert_to_r5_sockaddr(address, &r5addr);
convert_to_r5_sockaddr(_address, &r5addr);
if (_addressLength != NULL)
*_addressLength = sizeof(struct r5_sockaddr_in);
} else if (_addressLength != NULL)
*_addressLength = header.msg_namelen;
*_addressLength = addressLength;
return bytesReceived;
}
@@ -336,36 +292,14 @@ recvfrom(int socket, void *data, size_t length, int flags,
extern "C" ssize_t
recvmsg(int socket, struct msghdr *message, int flags)
{
message_args args;
if (message == NULL || (message->msg_iovlen > 0 && message->msg_iov == NULL))
return B_BAD_VALUE;
args.header = message;
args.flags = flags;
if (message->msg_iovlen > 0) {
args.data = message->msg_iov[0].iov_base;
args.length = message->msg_iov[0].iov_len;
} else {
args.data = NULL;
args.length = 0;
}
return ioctl(socket, NET_STACK_RECEIVE, &args, sizeof(args));
RETURN_AND_SET_ERRNO(_kern_recvmsg(socket, message, flags));
}
extern "C" ssize_t
send(int socket, const void *data, size_t length, int flags)
{
message_args args;
args.data = const_cast<void *>(data);
args.length = length;
args.flags = flags;
args.header = NULL;
return ioctl(socket, NET_STACK_SEND, &args, sizeof(args));
RETURN_AND_SET_ERRNO(_kern_send(socket, data, length, flags));
}
@@ -381,41 +315,15 @@ sendto(int socket, const void *data, size_t length, int flags,
addressLength = sizeof(struct sockaddr_in);
}
message_args args;
msghdr header;
memset(&header, 0, sizeof(header));
args.header = &header;
args.data = const_cast<void *>(data);
args.length = length;
args.flags = flags;
header.msg_name = (char *)const_cast<sockaddr *>(address);
header.msg_namelen = addressLength;
return ioctl(socket, NET_STACK_SEND, &args, sizeof(args));
RETURN_AND_SET_ERRNO(_kern_sendto(socket, data, length, flags, address,
addressLength));
}
extern "C" ssize_t
sendmsg(int socket, const struct msghdr *message, int flags)
{
message_args args;
if (message == NULL || (message->msg_iovlen > 0 && message->msg_iov == NULL))
return B_BAD_VALUE;
args.header = const_cast<msghdr *>(message);
args.flags = flags;
if (message->msg_iovlen > 0) {
args.data = message->msg_iov[0].iov_base;
args.length = message->msg_iov[0].iov_len;
} else {
args.data = NULL;
args.length = 0;
}
return ioctl(socket, NET_STACK_SEND, &args, sizeof(args));
RETURN_AND_SET_ERRNO(_kern_sendmsg(socket, message, flags));
}
@@ -432,19 +340,8 @@ getsockopt(int socket, int level, int option, void *value, socklen_t *_length)
convert_from_r5_sockopt(level, option);
}
sockopt_args args;
args.level = level;
args.option = option;
args.value = value;
args.length = _length ? *_length : 0;
if (ioctl(socket, NET_STACK_GETSOCKOPT, &args, sizeof(args)) < 0)
return -1;
if (_length)
*_length = args.length;
return 0;
RETURN_AND_SET_ERRNO(_kern_getsockopt(socket, level, option, value,
_length));
}
@@ -455,69 +352,74 @@ setsockopt(int socket, int level, int option, const void *value,
if (check_r5_compatibility())
convert_from_r5_sockopt(level, option);
sockopt_args args;
args.level = level;
args.option = option;
args.value = const_cast<void *>(value);
args.length = length;
return ioctl(socket, NET_STACK_SETSOCKOPT, &args, sizeof(args));
RETURN_AND_SET_ERRNO(_kern_setsockopt(socket, level, option, value,
length));
}
extern "C" int
getpeername(int socket, struct sockaddr *address, socklen_t *_addressLength)
getpeername(int socket, struct sockaddr *_address, socklen_t *_addressLength)
{
bool r5compatible = check_r5_compatibility();
struct sockaddr r5addr;
sockaddr_args args;
if (r5compatible) {
args.address = &r5addr;
args.address_length = sizeof(r5addr);
sockaddr* address;
socklen_t addressLength;
if (r5compatible && _address != NULL) {
address = &r5addr;
addressLength = sizeof(r5addr);
} else {
args.address = address;
args.address_length = _addressLength ? *_addressLength : 0;
address = _address;
addressLength = _addressLength ? *_addressLength : 0;
}
if (ioctl(socket, NET_STACK_GETPEERNAME, &args, sizeof(args)) < 0)
status_t error = _kern_getpeername(socket, address, &addressLength);
if (error != B_OK) {
errno = error;
return -1;
}
if (r5compatible) {
convert_to_r5_sockaddr(address, &r5addr);
convert_to_r5_sockaddr(_address, &r5addr);
if (_addressLength != NULL)
*_addressLength = sizeof(struct r5_sockaddr_in);
} else if (_addressLength != NULL)
*_addressLength = args.address_length;
*_addressLength = addressLength;
return 0;
}
extern "C" int
getsockname(int socket, struct sockaddr *address, socklen_t *_addressLength)
getsockname(int socket, struct sockaddr *_address, socklen_t *_addressLength)
{
bool r5compatible = check_r5_compatibility();
struct sockaddr r5addr;
sockaddr_args args;
if (r5compatible) {
args.address = &r5addr;
args.address_length = sizeof(r5addr);
sockaddr* address;
socklen_t addressLength;
if (r5compatible && _address != NULL) {
address = &r5addr;
addressLength = sizeof(r5addr);
} else {
args.address = address;
args.address_length = _addressLength ? *_addressLength : 0;
address = _address;
addressLength = _addressLength ? *_addressLength : 0;
}
if (ioctl(socket, NET_STACK_GETSOCKNAME, &args, sizeof(args)) < 0)
status_t error = _kern_getsockname(socket, address, &addressLength);
if (error != B_OK) {
errno = error;
return -1;
}
if (r5compatible) {
convert_to_r5_sockaddr(address, &r5addr);
convert_to_r5_sockaddr(_address, &r5addr);
if (_addressLength != NULL)
*_addressLength = sizeof(struct r5_sockaddr_in);
} else if (_addressLength != NULL)
*_addressLength = args.address_length;
*_addressLength = addressLength;
return 0;
}
@@ -526,33 +428,13 @@ getsockname(int socket, struct sockaddr *address, socklen_t *_addressLength)
extern "C" int
sockatmark(int socket)
{
// TODO: implement me!
return -1;
RETURN_AND_SET_ERRNO(_kern_sockatmark(socket));
}
extern "C" int
socketpair(int family, int type, int protocol, int socketVector[2])
{
socketVector[0] = socket(family, type, protocol);
if (socketVector[0] < 0)
return -1;
socketVector[1] = socket(family, type, protocol);
if (socketVector[1] < 0)
goto err1;
socketpair_args args;
args.second_socket = socketVector[1];
if (ioctl(socketVector[0], NET_STACK_SOCKETPAIR, &args, sizeof(args)) < 0)
goto err2;
return 0;
err2:
close(socketVector[1]);
err1:
close(socketVector[0]);
return -1;
RETURN_AND_SET_ERRNO(_kern_socketpair(family, type, protocol,
socketVector));
}
+2 -1
View File
@@ -3,7 +3,7 @@ SubDir HAIKU_TOP src system kernel fs ;
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
UsePrivateHeaders [ FDirName kernel fs ] ;
UsePrivateHeaders [ FDirName kernel util ] ;
UsePrivateHeaders shared storage ;
UsePrivateHeaders net shared storage ;
KernelMergeObject kernel_fs.o :
devfs.cpp
@@ -13,6 +13,7 @@ KernelMergeObject kernel_fs.o :
KPath.cpp
node_monitor.cpp
rootfs.cpp
socket.cpp
vfs.cpp
vfs_boot.cpp
vfs_net_boot.cpp
File diff suppressed because it is too large Load Diff