* Added a link from libnet.so to libnetwork.so for R5 compatibility.
* Fixed R5 socket definitions to match their actual definitions. * libnetwork.so now detects at runtime wether or not R5 compatibility should be enabled or not. * All socket functions should now be R5 net_server compatible. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19012 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -136,6 +136,7 @@ AddFilesToHaikuImage beos system : kernel_$(TARGET_ARCH) ;
|
||||
AddFilesToHaikuImage beos system lib : $(BEOS_SYSTEM_LIB) ;
|
||||
AddSymlinkToHaikuImage beos system lib : libnetwork.so : libsocket.so ;
|
||||
AddSymlinkToHaikuImage beos system lib : libnetwork.so : libbind.so ;
|
||||
AddSymlinkToHaikuImage beos system lib : libnetwork.so : libnet.so ;
|
||||
|
||||
# servers
|
||||
AddFilesToHaikuImage beos system servers : $(BEOS_SYSTEM_SERVERS) ;
|
||||
|
||||
@@ -5,11 +5,39 @@
|
||||
#ifndef NET_R5_COMPATIBILITY_H
|
||||
#define NET_R5_COMPATIBILITY_H
|
||||
|
||||
// TODO: judging from R5 headers, this is all wrong, though (this has been taken from
|
||||
// our old socket header) - we'll need to test this later on!
|
||||
// Also, more problematic is that IPPROTO_* constants also don't seem to be compatible, too
|
||||
#define R5_SOCK_DGRAM 10
|
||||
#define R5_SOCK_STREAM 11
|
||||
#define R5_SOCK_RAW 12
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
#define R5_SOCK_DGRAM 1
|
||||
#define R5_SOCK_STREAM 2
|
||||
|
||||
#define R5_AF_INET 1
|
||||
|
||||
#define R5_IPPROTO_UDP 1
|
||||
#define R5_IPPROTO_TCP 2
|
||||
#define R5_IPPROTO_ICMP 3
|
||||
|
||||
// setsockopt() defines
|
||||
|
||||
#define R5_SOL_SOCKET 1
|
||||
|
||||
#define R5_SO_DEBUG 1
|
||||
#define R5_SO_REUSEADDR 2
|
||||
#define R5_SO_NONBLOCK 3
|
||||
#define R5_SO_REUSEPORT 4
|
||||
#define R5_SO_FIONREAD 5
|
||||
|
||||
#define R5_MSG_OOB 0x01
|
||||
|
||||
|
||||
struct r5_sockaddr_in {
|
||||
uint16 sin_family;
|
||||
uint16 sin_port;
|
||||
uint32 sin_addr;
|
||||
char sin_zero[4];
|
||||
};
|
||||
|
||||
extern bool __gR5Compatibility;
|
||||
|
||||
#endif // NET_R5_COMPATIBILITY_H
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
SubDir HAIKU_TOP src kits network ;
|
||||
|
||||
UsePrivateHeaders net ;
|
||||
UsePrivateHeaders libroot net ;
|
||||
|
||||
SharedLibrary libnetwork.so :
|
||||
init.cpp
|
||||
interfaces.cpp
|
||||
socket.cpp
|
||||
:
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2006, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#include <libroot_private.h>
|
||||
|
||||
#include <OS.h>
|
||||
#include <image.h>
|
||||
|
||||
|
||||
bool __gR5Compatibility = false;
|
||||
|
||||
|
||||
extern "C" void
|
||||
initialize_before()
|
||||
{
|
||||
// determine if we have to run in R5 compatibility mode
|
||||
|
||||
// get image of executable
|
||||
image_info info;
|
||||
uint32 cookie = 0;
|
||||
if (get_next_image_info(B_CURRENT_TEAM, (int32 *)&cookie, &info) != B_OK)
|
||||
return;
|
||||
|
||||
if (get_image_symbol(info.id, "__gHaikuStartupCode", B_SYMBOL_TYPE_DATA,
|
||||
NULL) == B_OK) {
|
||||
// we were linked on/for Haiku
|
||||
return;
|
||||
}
|
||||
|
||||
// We're using the BeOS startup code, check if BONE libraries are in
|
||||
// use, and if not, enable the R5 compatibility layer.
|
||||
|
||||
const char *name;
|
||||
cookie = 0;
|
||||
int enable = 0;
|
||||
|
||||
while (__get_next_image_dependency(info.id, &cookie, &name) == B_OK) {
|
||||
if (!strcmp(name, "libbind.so")
|
||||
|| !strcmp(name, "libsocket.so")
|
||||
|| !strcmp(name, "libnetwork.so")
|
||||
enable -= 2;
|
||||
else if (!strcmp(name, "libnet.so"))
|
||||
enable++;
|
||||
}
|
||||
|
||||
if (enable > 0) {
|
||||
__gR5Compatibility = true;
|
||||
debug_printf("libnetwork.so running in R5 compatibility mode.\n");
|
||||
}
|
||||
}
|
||||
+204
-13
@@ -9,10 +9,14 @@
|
||||
*/
|
||||
|
||||
#include <net_stack_driver.h>
|
||||
#include <r5_compatibility.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
// TODO: this is meant for debugging purposes only, and should be disabled later
|
||||
@@ -29,6 +33,106 @@ stack_driver_path(void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
convert_from_r5_sockaddr(struct sockaddr *_to, const struct sockaddr *_from)
|
||||
{
|
||||
const r5_sockaddr_in *from = (r5_sockaddr_in *)_from;
|
||||
sockaddr_in *to = (sockaddr_in *)_to;
|
||||
|
||||
memset(to, 0, sizeof(*to));
|
||||
to->sin_len = sizeof(*to);
|
||||
|
||||
if (from->sin_family == R5_AF_INET)
|
||||
to->sin_family = AF_INET;
|
||||
else
|
||||
to->sin_family = from->sin_family;
|
||||
|
||||
to->sin_port = from->sin_port;
|
||||
to->sin_addr.s_addr = from->sin_addr;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
convert_to_r5_sockaddr(struct sockaddr *_to, const struct sockaddr *_from)
|
||||
{
|
||||
const sockaddr_in *from = (sockaddr_in *)_from;
|
||||
r5_sockaddr_in *to = (r5_sockaddr_in *)_to;
|
||||
|
||||
memset(to, 0, sizeof(*to));
|
||||
if (from->sin_family == AF_INET)
|
||||
to->sin_family = R5_AF_INET;
|
||||
else
|
||||
to->sin_family = from->sin_family;
|
||||
|
||||
to->sin_port = from->sin_port;
|
||||
to->sin_addr = from->sin_addr.s_addr;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
convert_from_r5_socket(int& family, int& type, int& protocol)
|
||||
{
|
||||
switch (family) {
|
||||
case R5_AF_INET:
|
||||
family = AF_INET;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case R5_SOCK_DGRAM:
|
||||
type = SOCK_DGRAM;
|
||||
break;
|
||||
case R5_SOCK_STREAM:
|
||||
type = SOCK_STREAM;
|
||||
break;
|
||||
#if 0
|
||||
case R5_SOCK_RAW:
|
||||
type = SOCK_RAW;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (protocol) {
|
||||
case R5_IPPROTO_UDP:
|
||||
protocol = IPPROTO_UDP;
|
||||
break;
|
||||
case R5_IPPROTO_TCP:
|
||||
protocol = R5_IPPROTO_TCP;
|
||||
break;
|
||||
case R5_IPPROTO_ICMP:
|
||||
protocol = R5_IPPROTO_ICMP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
convert_from_r5_sockopt(int& level, int& option)
|
||||
{
|
||||
if (level == R5_SOL_SOCKET)
|
||||
level = SOL_SOCKET;
|
||||
|
||||
switch (option) {
|
||||
case R5_SO_DEBUG:
|
||||
option = SO_DEBUG;
|
||||
break;
|
||||
case R5_SO_REUSEADDR:
|
||||
option = SO_REUSEADDR;
|
||||
break;
|
||||
case R5_SO_NONBLOCK:
|
||||
option = SO_NONBLOCK;
|
||||
break;
|
||||
case R5_SO_REUSEPORT:
|
||||
option = SO_REUSEPORT;
|
||||
break;
|
||||
case R5_SO_FIONREAD:
|
||||
// there is no SO_FIONREAD
|
||||
option = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
@@ -39,6 +143,9 @@ socket(int family, int type, int protocol)
|
||||
if (socket < 0)
|
||||
return -1;
|
||||
|
||||
if (__gR5Compatibility)
|
||||
convert_from_r5_socket(family, type, protocol);
|
||||
|
||||
socket_args args;
|
||||
args.family = family;
|
||||
args.type = type;
|
||||
@@ -56,6 +163,14 @@ socket(int family, int type, int protocol)
|
||||
extern "C" int
|
||||
bind(int socket, const struct sockaddr *address, socklen_t addressLength)
|
||||
{
|
||||
struct sockaddr r5addr;
|
||||
|
||||
if (__gR5Compatibility) {
|
||||
convert_from_r5_sockaddr(&r5addr, address);
|
||||
address = &r5addr;
|
||||
addressLength = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
sockaddr_args args;
|
||||
args.address = const_cast<struct sockaddr *>(address);
|
||||
args.address_length = addressLength;
|
||||
@@ -74,6 +189,14 @@ shutdown(int socket, int how)
|
||||
extern "C" int
|
||||
connect(int socket, const struct sockaddr *address, socklen_t addressLength)
|
||||
{
|
||||
struct sockaddr r5addr;
|
||||
|
||||
if (__gR5Compatibility) {
|
||||
convert_from_r5_sockaddr(&r5addr, address);
|
||||
address = &r5addr;
|
||||
addressLength = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
sockaddr_args args;
|
||||
args.address = const_cast<struct sockaddr *>(address);
|
||||
args.address_length = addressLength;
|
||||
@@ -106,17 +229,30 @@ accept(int socket, struct sockaddr *address, socklen_t *_addressLength)
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr r5addr;
|
||||
accept_args args;
|
||||
|
||||
args.cookie = cookie;
|
||||
args.address = address;
|
||||
args.address_length = _addressLength ? *_addressLength : 0;
|
||||
|
||||
if (__gR5Compatibility) {
|
||||
args.address = &r5addr;
|
||||
args.address_length = sizeof(r5addr);
|
||||
} else {
|
||||
args.address = address;
|
||||
args.address_length = _addressLength ? *_addressLength : 0;
|
||||
}
|
||||
|
||||
if (ioctl(socket, NET_STACK_ACCEPT, &args, sizeof(args)) < 0) {
|
||||
close(acceptSocket);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*_addressLength = args.address_length;
|
||||
if (__gR5Compatibility) {
|
||||
convert_to_r5_sockaddr(address, &r5addr);
|
||||
if (_addressLength != NULL)
|
||||
*_addressLength = sizeof(struct r5_sockaddr_in);
|
||||
} else if (_addressLength != NULL)
|
||||
*_addressLength = args.address_length;
|
||||
|
||||
return acceptSocket;
|
||||
}
|
||||
@@ -140,18 +276,30 @@ extern "C" ssize_t
|
||||
recvfrom(int socket, void *data, size_t length, int flags,
|
||||
struct sockaddr *address, socklen_t *_addressLength)
|
||||
{
|
||||
struct sockaddr r5addr;
|
||||
|
||||
transfer_args args;
|
||||
args.data = data;
|
||||
args.data_length = length;
|
||||
args.flags = flags;
|
||||
args.address = address;
|
||||
args.address_length = _addressLength ? *_addressLength : 0;
|
||||
|
||||
if (__gR5Compatibility) {
|
||||
args.address = &r5addr;
|
||||
args.address_length = sizeof(r5addr);
|
||||
} else {
|
||||
args.address = address;
|
||||
args.address_length = _addressLength ? *_addressLength : 0;
|
||||
}
|
||||
|
||||
ssize_t bytesReceived = ioctl(socket, NET_STACK_RECVFROM, &args, sizeof(args));
|
||||
if (bytesReceived < 0)
|
||||
return -1;
|
||||
|
||||
if (_addressLength)
|
||||
if (__gR5Compatibility) {
|
||||
convert_to_r5_sockaddr(address, &r5addr);
|
||||
if (_addressLength != NULL)
|
||||
*_addressLength = sizeof(struct r5_sockaddr_in);
|
||||
} else if (_addressLength != NULL)
|
||||
*_addressLength = args.address_length;
|
||||
|
||||
return bytesReceived;
|
||||
@@ -184,6 +332,14 @@ extern "C" ssize_t
|
||||
sendto(int socket, const void *data, size_t length, int flags,
|
||||
const struct sockaddr *address, socklen_t addressLength)
|
||||
{
|
||||
struct sockaddr r5addr;
|
||||
|
||||
if (__gR5Compatibility) {
|
||||
convert_from_r5_sockaddr(&r5addr, address);
|
||||
address = &r5addr;
|
||||
addressLength = sizeof(struct sockaddr_in);
|
||||
}
|
||||
|
||||
transfer_args args;
|
||||
args.data = const_cast<void *>(data);
|
||||
args.data_length = length;
|
||||
@@ -206,6 +362,16 @@ sendmsg(int socket, const struct msghdr *message, int flags)
|
||||
extern "C" int
|
||||
getsockopt(int socket, int level, int option, void *value, size_t *_length)
|
||||
{
|
||||
if (__gR5Compatibility) {
|
||||
if (option == R5_SO_FIONREAD) {
|
||||
// there is no SO_FIONREAD in our stack; we're using FIONREAD instead
|
||||
*_length = sizeof(int);
|
||||
return ioctl(socket, FIONREAD, &value);
|
||||
}
|
||||
|
||||
convert_from_r5_sockopt(level, option);
|
||||
}
|
||||
|
||||
sockopt_args args;
|
||||
args.level = level;
|
||||
args.option = option;
|
||||
@@ -225,6 +391,9 @@ getsockopt(int socket, int level, int option, void *value, size_t *_length)
|
||||
extern "C" int
|
||||
setsockopt(int socket, int level, int option, const void *value, size_t length)
|
||||
{
|
||||
if (__gR5Compatibility)
|
||||
convert_from_r5_sockopt(level, option);
|
||||
|
||||
sockopt_args args;
|
||||
args.level = level;
|
||||
args.option = option;
|
||||
@@ -238,14 +407,25 @@ setsockopt(int socket, int level, int option, const void *value, size_t length)
|
||||
extern "C" int
|
||||
getpeername(int socket, struct sockaddr *address, socklen_t *_addressLength)
|
||||
{
|
||||
struct sockaddr r5addr;
|
||||
|
||||
sockaddr_args args;
|
||||
args.address = address;
|
||||
args.address_length = _addressLength ? *_addressLength : 0;
|
||||
if (__gR5Compatibility) {
|
||||
args.address = &r5addr;
|
||||
args.address_length = sizeof(r5addr);
|
||||
} else {
|
||||
args.address = address;
|
||||
args.address_length = _addressLength ? *_addressLength : 0;
|
||||
}
|
||||
|
||||
if (ioctl(socket, NET_STACK_GETPEERNAME, &args, sizeof(args)) < 0)
|
||||
return -1;
|
||||
|
||||
if (_addressLength)
|
||||
if (__gR5Compatibility) {
|
||||
convert_to_r5_sockaddr(address, &r5addr);
|
||||
if (_addressLength != NULL)
|
||||
*_addressLength = sizeof(struct r5_sockaddr_in);
|
||||
} else if (_addressLength != NULL)
|
||||
*_addressLength = args.address_length;
|
||||
|
||||
return 0;
|
||||
@@ -255,14 +435,25 @@ getpeername(int socket, struct sockaddr *address, socklen_t *_addressLength)
|
||||
extern "C" int
|
||||
getsockname(int socket, struct sockaddr *address, socklen_t *_addressLength)
|
||||
{
|
||||
struct sockaddr r5addr;
|
||||
|
||||
sockaddr_args args;
|
||||
args.address = address;
|
||||
args.address_length = _addressLength ? *_addressLength : 0;
|
||||
if (__gR5Compatibility) {
|
||||
args.address = &r5addr;
|
||||
args.address_length = sizeof(r5addr);
|
||||
} else {
|
||||
args.address = address;
|
||||
args.address_length = _addressLength ? *_addressLength : 0;
|
||||
}
|
||||
|
||||
if (ioctl(socket, NET_STACK_GETSOCKNAME, &args, sizeof(args)) < 0)
|
||||
return -1;
|
||||
|
||||
if (_addressLength)
|
||||
if (__gR5Compatibility) {
|
||||
convert_to_r5_sockaddr(address, &r5addr);
|
||||
if (_addressLength != NULL)
|
||||
*_addressLength = sizeof(struct r5_sockaddr_in);
|
||||
} else if (_addressLength != NULL)
|
||||
*_addressLength = args.address_length;
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user