summaryrefslogtreecommitdiffstats
path: root/src/vcl/vcom_socket.c
diff options
context:
space:
mode:
authorSteven <sluong@cisco.com>2017-10-24 16:03:58 -0700
committerDave Wallace <dwallacelf@gmail.com>2017-10-25 14:08:39 +0000
commitac1f96d7cdfb845c08400d27ec566b991e32e24b (patch)
treee7e82c1a91f5c7e391fafac915a8d5a5121dbc9f /src/vcl/vcom_socket.c
parent60f54822b78dea6b87cde5da82a4a135e7c2b960 (diff)
VCL/LDPRELOAD: Add support for getsockopt, sendto, and recvfrom
Add support for getsockopt, sendto, and recvfrom. Not all options for the system calls are supported yet. Only the options used by curl and wget are supported for now. Change-Id: I2e0ed7349a0273616b3831c201e7c117725ca287 Signed-off-by: Steven <sluong@cisco.com>
Diffstat (limited to 'src/vcl/vcom_socket.c')
-rw-r--r--src/vcl/vcom_socket.c98
1 files changed, 85 insertions, 13 deletions
diff --git a/src/vcl/vcom_socket.c b/src/vcl/vcom_socket.c
index 1ccb05451ad..304cebb8f9b 100644
--- a/src/vcl/vcom_socket.c
+++ b/src/vcl/vcom_socket.c
@@ -1513,9 +1513,29 @@ vcom_session_sendto (int __sid, void *__buf, size_t __n,
socklen_t __addr_len)
{
int rv = -1;
- /* TBD add new vpp api */
- /* TBD add flags parameter */
- rv = vppcom_session_write (__sid, (void *) __buf, (int) __n);
+ vppcom_endpt_t ep;
+
+ ep.vrf = VPPCOM_VRF_DEFAULT;
+ switch (__addr->sa_family)
+ {
+ case AF_INET:
+ ep.is_ip4 = VPPCOM_IS_IP4;
+ ep.ip = (uint8_t *) & ((const struct sockaddr_in *) __addr)->sin_addr;
+ ep.port = (uint16_t) ((const struct sockaddr_in *) __addr)->sin_port;
+ break;
+
+ case AF_INET6:
+ ep.is_ip4 = VPPCOM_IS_IP6;
+ ep.ip = (uint8_t *) & ((const struct sockaddr_in6 *) __addr)->sin6_addr;
+ ep.port = (uint16_t) ((const struct sockaddr_in6 *) __addr)->sin6_port;
+ break;
+
+ default:
+ return -1;
+ }
+
+ rv = vppcom_session_sendto (__sid, __buf, __n, __flags, &ep);
+
return rv;
}
@@ -1580,10 +1600,44 @@ vcom_session_recvfrom (int __sid, void *__restrict __buf, size_t __n,
int __flags, __SOCKADDR_ARG __addr,
socklen_t * __restrict __addr_len)
{
- int rv = -1;
+ int rv;
+ vppcom_endpt_t ep;
+
+ if (__addr)
+ {
+ ep.ip = (u8 *) & ((const struct sockaddr_in *) __addr)->sin_addr;
+ rv = vppcom_session_recvfrom (__sid, __buf, __n, __flags, &ep);
+
+ if (rv > 0)
+ {
+ if (ep.vrf == VPPCOM_VRF_DEFAULT)
+ {
+ __addr->sa_family =
+ ep.is_ip4 == VPPCOM_IS_IP4 ? AF_INET : AF_INET6;
+ switch (__addr->sa_family)
+ {
+ case AF_INET:
+ ((struct sockaddr_in *) __addr)->sin_port = ep.port;
+ *__addr_len = sizeof (struct sockaddr_in);
+ break;
+
+ case AF_INET6:
+ ((struct sockaddr_in6 *) __addr)->sin6_port = ep.port;
+ *__addr_len = sizeof (struct sockaddr_in6);
+ break;
+
+ default:
+ rv = -1;
+ break;
+ }
+ }
+ else
+ rv = -1;
+ }
+ }
+ else
+ rv = vppcom_session_recvfrom (__sid, __buf, __n, __flags, NULL);
- /* TBD add flags parameter */
- rv = vppcom_session_read (__sid, __buf, __n);
return rv;
}
@@ -1597,10 +1651,8 @@ vcom_socket_recvfrom (int __fd, void *__restrict __buf, size_t __n,
uword *p;
vcom_socket_t *vsock;
- if (!__buf || !__addr || !__addr_len)
- {
- return -EINVAL;
- }
+ if (__addr && !__addr_len)
+ return -EINVAL;
p = hash_get (vsm->sockidx_by_fd, __fd);
if (!p)
@@ -1737,9 +1789,26 @@ vcom_session_get_sockopt (int __sid, int __level, int __optname,
void *__restrict __optval,
socklen_t * __restrict __optlen)
{
+ int rv = 0;
+
/* 1. for socket level options that are NOT socket attributes
* and that has corresponding vpp options get from vppcom */
- return 0;
+ switch (__level)
+ {
+ case SOL_SOCKET:
+ switch (__optname)
+ {
+ case SO_ERROR:
+ *(int *) __optval = 0;
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ /* 2. unhandled options */
+ return rv;
}
int
@@ -1768,7 +1837,6 @@ vcom_socket_getsockopt (int __fd, int __level, int __optname,
switch (__level)
{
- /* handle options at socket level */
case SOL_SOCKET:
switch (__optname)
{
@@ -1791,7 +1859,6 @@ vcom_socket_getsockopt (int __fd, int __level, int __optname,
case SO_TYPE:
case SO_PROTOCOL:
case SO_DOMAIN:
- case SO_ERROR:
case SO_OOBINLINE:
case SO_NO_CHECK:
case SO_PRIORITY:
@@ -1835,6 +1902,11 @@ vcom_socket_getsockopt (int __fd, int __level, int __optname,
}
break;
+ case SO_ERROR:
+ rv = vcom_session_get_sockopt (vsock->sid, __level, __optname,
+ __optval, __optlen);
+ break;
+
default:
/* We implement the SO_SNDLOWAT etc to not be settable
* (1003.1g 7).