diff --git a/headers/private/net/core_module.h b/headers/private/net/core_module.h index ea2fd72be1..b951e3a241 100644 --- a/headers/private/net/core_module.h +++ b/headers/private/net/core_module.h @@ -157,6 +157,7 @@ struct core_module_info { int (*socket_getsockopt) (struct socket *so, int, int, void *, size_t *); int (*socket_getpeername) (struct socket *so, struct sockaddr *, int *); int (*socket_getsockname) (struct socket *so, struct sockaddr *, int *); + int (*socket_socketpair) (struct socket *so, struct socket **nso); int (*socket_set_event_callback)(struct socket *so, socket_event_callback, void *, int); int (*socket_shutdown) (struct socket *so, int how); }; diff --git a/headers/private/net/net_socket.h b/headers/private/net/net_socket.h index 6fcdce6f30..7e6cefe0d5 100644 --- a/headers/private/net/net_socket.h +++ b/headers/private/net/net_socket.h @@ -30,6 +30,8 @@ int socket_ioctl (struct socket *so, int cmd, caddr_t data); int socket_getpeername (struct socket *so, struct sockaddr *, int *); int socket_getsockname (struct socket *so, struct sockaddr *, int *); +int socket_pair (struct socket *so, struct socket **nso); + int socket_set_event_callback(struct socket *so, socket_event_callback, void *, int); diff --git a/headers/private/net/net_stack_driver.h b/headers/private/net/net_stack_driver.h index c585280dd7..f218dcc8e9 100644 --- a/headers/private/net/net_stack_driver.h +++ b/headers/private/net/net_stack_driver.h @@ -37,6 +37,7 @@ enum { NET_STACK_SETSOCKOPT, // sockopt_args * NET_STACK_GETSOCKNAME, // sockaddr_args * NET_STACK_GETPEERNAME, // sockaddr_args * + NET_STACK_SOCKETPAIR, // NET_STACK_SYSCTL, // sysctl_args * NET_STACK_SELECT, // select_args * @@ -79,6 +80,10 @@ struct socket_args { // used by NET_STACK_SOCKET int proto; }; +struct socketpair_args { // used by NET_STACK_SOCKETPAIR + void *cookie; +}; + struct accept_args { // used by NET_STACK_ACCEPT void *cookie; struct sockaddr *addr; @@ -156,6 +161,7 @@ struct stack_driver_args { struct sysctl_args sysctl; struct select_args select; struct control_net_module_args control; + struct socketpair_args socketpair; } u; }; diff --git a/src/add-ons/kernel/drivers/network/stack/net_stack_driver.c b/src/add-ons/kernel/drivers/network/stack/net_stack_driver.c index acb39b4da2..560c19fa0d 100644 --- a/src/add-ons/kernel/drivers/network/stack/net_stack_driver.c +++ b/src/add-ons/kernel/drivers/network/stack/net_stack_driver.c @@ -433,7 +433,11 @@ static status_t net_stack_control(void *cookie, uint32 op, void *data, size_t le case NET_STACK_GETPEERNAME: return g_core->socket_getpeername(nsc->socket, args->u.sockaddr.addr, &args->u.sockaddr.addrlen); - + + case NET_STACK_SOCKETPAIR: { + net_stack_cookie *ansc = args->u.socketpair.cookie; + return g_core->socket_socketpair(nsc->socket, &ansc->socket); + } case B_SET_BLOCKING_IO: { int off = false; nsc->open_flags &= ~O_NONBLOCK; diff --git a/src/add-ons/kernel/network/core/core.c b/src/add-ons/kernel/network/core/core.c index 02200b8975..2d6740c265 100644 --- a/src/add-ons/kernel/network/core/core.c +++ b/src/add-ons/kernel/network/core/core.c @@ -207,6 +207,7 @@ struct core_module_info core_info = { socket_getsockopt, socket_getpeername, socket_getsockname, + socket_socketpair, socket_set_event_callback, socket_shutdown }; diff --git a/src/add-ons/kernel/network/core/socket.c b/src/add-ons/kernel/network/core/socket.c index c6e20c6a8f..8b0345113e 100644 --- a/src/add-ons/kernel/network/core/socket.c +++ b/src/add-ons/kernel/network/core/socket.c @@ -1565,3 +1565,12 @@ int socket_accept(struct socket *so, struct socket **nso, void *data, int *alen) *nso = so; return error; } + + +void +socket_socketpair(struct socket *so, struct socket **nso) +{ + // TODO : implement, eventually fill nso with a new cookie + return ENOIMPL; +} + diff --git a/src/kits/network/libsocket/socket.c b/src/kits/network/libsocket/socket.c index ad7292fd94..7dc2717f4d 100644 --- a/src/kits/network/libsocket/socket.c +++ b/src/kits/network/libsocket/socket.c @@ -282,6 +282,47 @@ _EXPORT int getsockname(int sock, struct sockaddr *addr, int *addrlen) return rv; } + +_EXPORT int socketpair(int family, int type, int protocol, int socket_vector[2]) +{ + struct stack_driver_args args; + int rv; + void *cookie; + + socket_vector[0] = socket(family, type, protocol); + if (socket_vector[0] < 0) { + return socket_vector[0]; + } + + socket_vector[1] = socket(family, type, protocol); + if (socket_vector[1] < 0) { + close(socket_vector[0]); + return socket_vector[1]; + } + + // The network stack driver will need to know to which net_stack_cookie to + // *bind* with the new accepted socket. He can't know himself find out + // the net_stack_cookie of our new_sock file descriptor, the just open() one... + // So, here, we ask him the net_stack_cookie value for our fd... :-) + rv = ioctl(socket_vector[1], NET_STACK_GET_COOKIE, &cookie); + if (rv < 0) { + close(socket_vector[0]); + close(socket_vector[1]); + return rv; + } + + args.u.socketpair.cookie = cookie; // this way driver can use the right fd/cookie! + + rv = ioctl(socket_vector[0], NET_STACK_SOCKETPAIR, &args, sizeof(args)); + if (rv < 0) { + close(socket_vector[0]); + close(socket_vector[1]); + return rv; + } + return rv; +} + + // #pragma mark -