* 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:
Axel Dörfler
2006-10-06 13:07:05 +00:00
parent 3cf73255de
commit 153b2845d2
5 changed files with 297 additions and 20 deletions
+1
View File
@@ -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) ;
+34 -6
View File
@@ -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
+2 -1
View File
@@ -1,8 +1,9 @@
SubDir HAIKU_TOP src kits network ;
UsePrivateHeaders net ;
UsePrivateHeaders libroot net ;
SharedLibrary libnetwork.so :
init.cpp
interfaces.cpp
socket.cpp
:
+56
View File
@@ -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
View File
@@ -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;