forked from enlightenment/efl
efl_net_*_udp: expose SO_DONTROUTE.
It's common to have protocols that are restricted to local network only, thus allow exposing SO_DONTROUTE to avoid mistakes.
This commit is contained in:
parent
5e54c3aa57
commit
26866ca2a8
|
@ -151,6 +151,7 @@ static const Ecore_Getopt options = {
|
|||
{
|
||||
ECORE_GETOPT_STORE_BOOL('r', "read-after-write", "Do a read after writes are done."),
|
||||
ECORE_GETOPT_STORE_BOOL('c', "cork", "use UDP_CORK around messages to generate a single datagram."),
|
||||
ECORE_GETOPT_STORE_BOOL('R', "dont-route", "Do not route packets via a gateway."),
|
||||
ECORE_GETOPT_STORE_DOUBLE('t', "connect-timeout", "timeout in seconds for the connection phase"),
|
||||
ECORE_GETOPT_VERSION('V', "version"),
|
||||
ECORE_GETOPT_COPYRIGHT('C', "copyright"),
|
||||
|
@ -168,11 +169,13 @@ main(int argc, char **argv)
|
|||
char *address = NULL;
|
||||
Eina_Bool cork = EINA_FALSE;
|
||||
Eina_Bool do_read = EINA_FALSE;
|
||||
Eina_Bool dont_route = EINA_FALSE;
|
||||
Eina_Bool quit_option = EINA_FALSE;
|
||||
double timeout_dial = 30.0;
|
||||
Ecore_Getopt_Value values[] = {
|
||||
ECORE_GETOPT_VALUE_BOOL(do_read),
|
||||
ECORE_GETOPT_VALUE_BOOL(cork),
|
||||
ECORE_GETOPT_VALUE_BOOL(dont_route),
|
||||
ECORE_GETOPT_VALUE_DOUBLE(timeout_dial),
|
||||
|
||||
/* standard block to provide version, copyright, license and help */
|
||||
|
@ -216,6 +219,7 @@ main(int argc, char **argv)
|
|||
dialer = efl_add(EFL_NET_DIALER_UDP_CLASS, loop,
|
||||
efl_name_set(efl_added, "dialer"),
|
||||
efl_net_socket_udp_cork_set(efl_added, cork),
|
||||
efl_net_socket_udp_dont_route_set(efl_added, dont_route),
|
||||
efl_net_dialer_timeout_dial_set(efl_added, timeout_dial),
|
||||
efl_event_callback_array_add(efl_added, dialer_cbs(), NULL));
|
||||
|
||||
|
|
|
@ -433,6 +433,23 @@ _server_serving(void *data EINA_UNUSED, const Efl_Event *event)
|
|||
{
|
||||
fprintf(stderr, "INFO: serving at %s\n",
|
||||
efl_net_server_address_get(event->object));
|
||||
|
||||
if (efl_class_get(event->object) == EFL_NET_SERVER_TCP_CLASS)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"TCP options:\n"
|
||||
" - IPv6 only: %u\n",
|
||||
efl_net_server_tcp_ipv6_only_get(event->object));
|
||||
}
|
||||
else if (efl_class_get(event->object) == EFL_NET_SERVER_UDP_CLASS)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"UDP options:\n"
|
||||
" - IPv6 only: %u\n"
|
||||
" - don't route: %u\n",
|
||||
efl_net_server_udp_ipv6_only_get(event->object),
|
||||
efl_net_server_udp_dont_route_get(event->object));
|
||||
}
|
||||
}
|
||||
|
||||
EFL_CALLBACKS_ARRAY_DEFINE(server_cbs,
|
||||
|
@ -476,12 +493,17 @@ static const Ecore_Getopt options = {
|
|||
ECORE_GETOPT_LICENSE('L', "license"),
|
||||
ECORE_GETOPT_HELP('h', "help"),
|
||||
|
||||
ECORE_GETOPT_CATEGORY("udp", "UDP options"),
|
||||
ECORE_GETOPT_STORE_BOOL(0, "udp-dont-route",
|
||||
"If true, datagrams won't be routed using a gateway, being restricted to the local network."),
|
||||
|
||||
ECORE_GETOPT_CHOICE_METAVAR(0, NULL, "The server protocol.", "protocol",
|
||||
protocols),
|
||||
ECORE_GETOPT_STORE_METAVAR_STR(0, NULL,
|
||||
"The server address to listen, such as "
|
||||
"IPv4:PORT, [IPv6]:PORT, Unix socket path...",
|
||||
"address"),
|
||||
|
||||
ECORE_GETOPT_SENTINEL
|
||||
}
|
||||
};
|
||||
|
@ -495,6 +517,7 @@ main(int argc, char **argv)
|
|||
unsigned int clients_limit = 0;
|
||||
Eina_Bool clients_reject_excess = EINA_FALSE;
|
||||
Eina_Bool ipv6_only = EINA_TRUE;
|
||||
Eina_Bool udp_dont_route = EINA_FALSE;
|
||||
Eina_Bool quit_option = EINA_FALSE;
|
||||
Ecore_Getopt_Value values[] = {
|
||||
ECORE_GETOPT_VALUE_BOOL(echo),
|
||||
|
@ -509,6 +532,9 @@ main(int argc, char **argv)
|
|||
ECORE_GETOPT_VALUE_BOOL(quit_option), /* -L/--license quits */
|
||||
ECORE_GETOPT_VALUE_BOOL(quit_option), /* -h/--help quits */
|
||||
|
||||
ECORE_GETOPT_VALUE_BOOL(quit_option), /* category: udp */
|
||||
ECORE_GETOPT_VALUE_BOOL(udp_dont_route),
|
||||
|
||||
/* positional argument */
|
||||
ECORE_GETOPT_VALUE_STR(protocol),
|
||||
ECORE_GETOPT_VALUE_STR(address),
|
||||
|
@ -540,6 +566,13 @@ main(int argc, char **argv)
|
|||
goto end;
|
||||
}
|
||||
|
||||
if (!protocol)
|
||||
{
|
||||
fputs("ERROR: missing protocol.\n", stderr);
|
||||
retval = EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (strcmp(protocol, "tcp") == 0) cls = EFL_NET_SERVER_TCP_CLASS;
|
||||
else if (strcmp(protocol, "udp") == 0) cls = EFL_NET_SERVER_UDP_CLASS;
|
||||
else
|
||||
|
@ -566,7 +599,10 @@ main(int argc, char **argv)
|
|||
if (cls == EFL_NET_SERVER_TCP_CLASS)
|
||||
efl_net_server_tcp_ipv6_only_set(server, ipv6_only);
|
||||
else if (cls == EFL_NET_SERVER_UDP_CLASS)
|
||||
efl_net_server_udp_ipv6_only_set(server, ipv6_only);
|
||||
{
|
||||
efl_net_server_udp_ipv6_only_set(server, ipv6_only);
|
||||
efl_net_server_udp_dont_route_set(server, udp_dont_route);
|
||||
}
|
||||
|
||||
/* an explicit call to efl_net_server_serve() after the object is
|
||||
* constructed allows for more complex setup, such as interacting
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef struct _Efl_Net_Server_Udp_Data
|
|||
Ecore_Thread *resolver;
|
||||
Eina_Hash *clients; /* addr (string) -> client (Efl.Net.Server.Udp.Client) */
|
||||
Eina_Bool ipv6_only;
|
||||
Eina_Bool dont_route;
|
||||
} Efl_Net_Server_Udp_Data;
|
||||
|
||||
EOLIAN Efl_Object *
|
||||
|
@ -96,6 +97,8 @@ _efl_net_server_udp_resolved_bind(Eo *o, Efl_Net_Server_Udp_Data *pd, const stru
|
|||
efl_net_server_udp_ipv6_only_set(o, pd->ipv6_only);
|
||||
}
|
||||
|
||||
efl_net_server_udp_dont_route_set(o, pd->dont_route);
|
||||
|
||||
r = bind(fd, addr->ai_addr, addrlen);
|
||||
if (r < 0)
|
||||
{
|
||||
|
@ -355,4 +358,59 @@ _efl_net_server_udp_ipv6_only_get(Eo *o EINA_UNUSED, Efl_Net_Server_Udp_Data *pd
|
|||
return pd->ipv6_only;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_net_server_udp_dont_route_set(Eo *o, Efl_Net_Server_Udp_Data *pd, Eina_Bool dont_route)
|
||||
{
|
||||
Eina_Bool old = pd->dont_route;
|
||||
int fd = efl_loop_fd_get(o);
|
||||
#ifdef _WIN32
|
||||
DWORD value = dont_route;
|
||||
#else
|
||||
int value = dont_route;
|
||||
#endif
|
||||
|
||||
pd->dont_route = dont_route;
|
||||
|
||||
if (fd < 0) return EINA_TRUE;
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &value, sizeof(value)) != 0)
|
||||
{
|
||||
Eina_Error err = efl_net_socket_error_get();
|
||||
ERR("setsockopt(%d, SOL_SOCKET, SO_DONTROUTE, %u): %s", fd, dont_route, eina_error_msg_get(err));
|
||||
pd->dont_route = old;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_net_server_udp_dont_route_get(Eo *o, Efl_Net_Server_Udp_Data *pd)
|
||||
{
|
||||
int fd = efl_loop_fd_get(o);
|
||||
#ifdef _WIN32
|
||||
DWORD value;
|
||||
#else
|
||||
int value;
|
||||
#endif
|
||||
socklen_t valuelen;
|
||||
|
||||
if (fd < 0) return pd->dont_route;
|
||||
|
||||
/* if there is a fd, always query it directly as it may be modified
|
||||
* elsewhere by nasty users.
|
||||
*/
|
||||
valuelen = sizeof(value);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &value, &valuelen) != 0)
|
||||
{
|
||||
Eina_Error err = efl_net_socket_error_get();
|
||||
ERR("getsockopt(%d, SOL_SOCKET, SO_DONTROUTE): %s", fd, eina_error_msg_get(err));
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
pd->dont_route = !!value; /* sync */
|
||||
return pd->dont_route;
|
||||
}
|
||||
|
||||
|
||||
#include "efl_net_server_udp.eo.c"
|
||||
|
|
|
@ -31,6 +31,23 @@ class Efl.Net.Server.Udp (Efl.Net.Server.Fd) {
|
|||
ipv6_only: bool;
|
||||
}
|
||||
}
|
||||
|
||||
@property dont_route {
|
||||
[[Avoid sent UDP packets being routed by a gateway, limiting them to the local network.
|
||||
|
||||
This will use SO_DONTROUTE option to avoid gateways
|
||||
routing sent packets to outside of local network. It's
|
||||
useful for some protocols that only want local area to
|
||||
be affected.
|
||||
]]
|
||||
get { }
|
||||
set {
|
||||
return: bool (false); [[$true on success]]
|
||||
}
|
||||
values {
|
||||
dont_route: bool;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
implements {
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
typedef struct _Efl_Net_Socket_Udp_Data
|
||||
{
|
||||
Eina_Bool cork;
|
||||
Eina_Bool dont_route;
|
||||
} Efl_Net_Socket_Udp_Data;
|
||||
|
||||
EOLIAN static void
|
||||
|
@ -53,6 +54,7 @@ _efl_net_socket_udp_efl_loop_fd_fd_set(Eo *o, Efl_Net_Socket_Udp_Data *pd EINA_U
|
|||
|
||||
/* apply postponed values */
|
||||
efl_net_socket_udp_cork_set(o, pd->cork);
|
||||
efl_net_socket_udp_dont_route_set(o, pd->dont_route);
|
||||
|
||||
family = efl_net_socket_fd_family_get(o);
|
||||
if (family == AF_UNSPEC) return;
|
||||
|
@ -152,4 +154,58 @@ _efl_net_socket_udp_cork_get(Eo *o, Efl_Net_Socket_Udp_Data *pd)
|
|||
return pd->cork;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_net_socket_udp_dont_route_set(Eo *o, Efl_Net_Socket_Udp_Data *pd, Eina_Bool dont_route)
|
||||
{
|
||||
Eina_Bool old = pd->dont_route;
|
||||
int fd = efl_loop_fd_get(o);
|
||||
#ifdef _WIN32
|
||||
DWORD value = dont_route;
|
||||
#else
|
||||
int value = dont_route;
|
||||
#endif
|
||||
|
||||
pd->dont_route = dont_route;
|
||||
|
||||
if (fd < 0) return EINA_TRUE;
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &value, sizeof(value)) != 0)
|
||||
{
|
||||
Eina_Error err = efl_net_socket_error_get();
|
||||
ERR("setsockopt(%d, SOL_SOCKET, SO_DONTROUTE, %u): %s", fd, dont_route, eina_error_msg_get(err));
|
||||
pd->dont_route = old;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_net_socket_udp_dont_route_get(Eo *o, Efl_Net_Socket_Udp_Data *pd)
|
||||
{
|
||||
int fd = efl_loop_fd_get(o);
|
||||
#ifdef _WIN32
|
||||
DWORD value;
|
||||
#else
|
||||
int value;
|
||||
#endif
|
||||
socklen_t valuelen;
|
||||
|
||||
if (fd < 0) return pd->dont_route;
|
||||
|
||||
/* if there is a fd, always query it directly as it may be modified
|
||||
* elsewhere by nasty users.
|
||||
*/
|
||||
valuelen = sizeof(value);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &value, &valuelen) != 0)
|
||||
{
|
||||
Eina_Error err = efl_net_socket_error_get();
|
||||
ERR("getsockopt(%d, SOL_SOCKET, SO_DONTROUTE): %s", fd, eina_error_msg_get(err));
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
pd->dont_route = !!value; /* sync */
|
||||
return pd->dont_route;
|
||||
}
|
||||
|
||||
#include "efl_net_socket_udp.eo.c"
|
||||
|
|
|
@ -22,6 +22,23 @@ class Efl.Net.Socket.Udp (Efl.Net.Socket.Fd) {
|
|||
cork: bool;
|
||||
}
|
||||
}
|
||||
|
||||
@property dont_route {
|
||||
[[Avoid sent UDP packets being routed by a gateway, limiting them to the local network.
|
||||
|
||||
This will use SO_DONTROUTE option to avoid gateways
|
||||
routing sent packets to outside of local network. It's
|
||||
useful for some protocols that only want local area to
|
||||
be affected.
|
||||
]]
|
||||
get { }
|
||||
set {
|
||||
return: bool (false); [[$true on success]]
|
||||
}
|
||||
values {
|
||||
dont_route: bool;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
implements {
|
||||
|
|
Loading…
Reference in New Issue