vcl: fix ldp fcntl64
[vpp.git] / src / vcl / ldp.c
index e3e6dfa..cda4425 100644 (file)
@@ -478,17 +478,11 @@ writev (int fd, const struct iovec * iov, int iovcnt)
   return size;
 }
 
-int
-fcntl (int fd, int cmd, ...)
+static int
+fcntl_internal (int fd, int cmd, va_list ap)
 {
   vls_handle_t vlsh;
   int rv = 0;
-  va_list ap;
-
-  if ((errno = -ldp_init ()))
-    return -1;
-
-  va_start (ap, cmd);
 
   vlsh = ldp_fd_to_vlsh (fd);
   LDBG (0, "fd %u vlsh %d, cmd %u", fd, vlsh, cmd);
@@ -534,6 +528,20 @@ fcntl (int fd, int cmd, ...)
 #endif
     }
 
+  return rv;
+}
+
+int
+fcntl (int fd, int cmd, ...)
+{
+  va_list ap;
+  int rv;
+
+  if ((errno = -ldp_init ()))
+    return -1;
+
+  va_start (ap, cmd);
+  rv = fcntl_internal (fd, cmd, ap);
   va_end (ap);
 
   return rv;
@@ -545,8 +553,11 @@ fcntl64 (int fd, int cmd, ...)
   va_list ap;
   int rv;
 
+  if ((errno = -ldp_init ()))
+    return -1;
+
   va_start (ap, cmd);
-  rv = fcntl (fd, cmd, ap);
+  rv = fcntl_internal (fd, cmd, ap);
   va_end (ap);
   return rv;
 }
@@ -1525,6 +1536,69 @@ recv (int fd, void *buf, size_t n, int flags)
   return size;
 }
 
+static int
+ldp_vls_sendo (vls_handle_t vlsh, const void *buf, size_t n, int flags,
+              __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
+{
+  vppcom_endpt_t *ep = 0;
+  vppcom_endpt_t _ep;
+
+  if (addr)
+    {
+      ep = &_ep;
+      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 EAFNOSUPPORT;
+       }
+    }
+
+  return vls_sendto (vlsh, (void *) buf, n, flags, ep);
+}
+
+static int
+ldp_vls_recvfrom (vls_handle_t vlsh, void *__restrict buf, size_t n,
+                 int flags, __SOCKADDR_ARG addr,
+                 socklen_t * __restrict addr_len)
+{
+  u8 src_addr[sizeof (struct sockaddr_in6)];
+  vppcom_endpt_t ep;
+  ssize_t size;
+  int rv;
+
+  if (addr)
+    {
+      ep.ip = src_addr;
+      size = vls_recvfrom (vlsh, buf, n, flags, &ep);
+
+      if (size > 0)
+       {
+         rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
+         if (rv < 0)
+           size = rv;
+       }
+    }
+  else
+    size = vls_recvfrom (vlsh, buf, n, flags, NULL);
+
+  return size;
+}
+
 ssize_t
 sendto (int fd, const void *buf, size_t n, int flags,
        __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
@@ -1538,38 +1612,7 @@ sendto (int fd, const void *buf, size_t n, int flags,
   vlsh = ldp_fd_to_vlsh (fd);
   if (vlsh != INVALID_SESSION_ID)
     {
-      vppcom_endpt_t *ep = 0;
-      vppcom_endpt_t _ep;
-
-      if (addr)
-       {
-         ep = &_ep;
-         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:
-             errno = EAFNOSUPPORT;
-             size = -1;
-             goto done;
-           }
-       }
-
-      size = vls_sendto (vlsh, (void *) buf, n, flags, ep);
+      size = ldp_vls_sendo (vlsh, buf, n, flags, addr, addr_len);
       if (size < 0)
        {
          errno = -size;
@@ -1581,7 +1624,6 @@ sendto (int fd, const void *buf, size_t n, int flags,
       size = libc_sendto (fd, buf, n, flags, addr, addr_len);
     }
 
-done:
   return size;
 }
 
@@ -1589,33 +1631,16 @@ ssize_t
 recvfrom (int fd, void *__restrict buf, size_t n, int flags,
          __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
 {
-  vls_handle_t sid;
-  ssize_t size, rv;
+  vls_handle_t vlsh;
+  ssize_t size;
 
   if ((errno = -ldp_init ()))
     return -1;
 
-  sid = ldp_fd_to_vlsh (fd);
-  if (sid != VLS_INVALID_HANDLE)
+  vlsh = ldp_fd_to_vlsh (fd);
+  if (vlsh != VLS_INVALID_HANDLE)
     {
-      vppcom_endpt_t ep;
-      u8 src_addr[sizeof (struct sockaddr_in6)];
-
-      if (addr)
-       {
-         ep.ip = src_addr;
-         size = vls_recvfrom (sid, buf, n, flags, &ep);
-
-         if (size > 0)
-           {
-             rv = ldp_copy_ep_to_sockaddr (addr, addr_len, &ep);
-             if (rv < 0)
-               size = rv;
-           }
-       }
-      else
-       size = vls_recvfrom (sid, buf, n, flags, NULL);
-
+      size = ldp_vls_recvfrom (vlsh, buf, n, flags, addr, addr_len);
       if (size < 0)
        {
          errno = -size;
@@ -1631,7 +1656,7 @@ recvfrom (int fd, void *__restrict buf, size_t n, int flags,
 }
 
 ssize_t
-sendmsg (int fd, const struct msghdr * message, int flags)
+sendmsg (int fd, const struct msghdr * msg, int flags)
 {
   vls_handle_t vlsh;
   ssize_t size;
@@ -1642,13 +1667,35 @@ sendmsg (int fd, const struct msghdr * message, int flags)
   vlsh = ldp_fd_to_vlsh (fd);
   if (vlsh != VLS_INVALID_HANDLE)
     {
-      LDBG (0, "LDP-TBD");
-      errno = ENOSYS;
-      size = -1;
+      struct iovec *iov = msg->msg_iov;
+      ssize_t total = 0;
+      int i, rv;
+
+      for (i = 0; i < msg->msg_iovlen; ++i)
+       {
+         rv = ldp_vls_sendo (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
+                             msg->msg_name, msg->msg_namelen);
+         if (rv < 0)
+           break;
+         else
+           {
+             total += rv;
+             if (rv < iov[i].iov_len)
+               break;
+           }
+       }
+
+      if (rv < 0 && total == 0)
+       {
+         errno = -rv;
+         size = -1;
+       }
+      else
+       size = total;
     }
   else
     {
-      size = libc_sendmsg (fd, message, flags);
+      size = libc_sendmsg (fd, msg, flags);
     }
 
   return size;
@@ -1703,7 +1750,7 @@ sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
 #endif
 
 ssize_t
-recvmsg (int fd, struct msghdr * message, int flags)
+recvmsg (int fd, struct msghdr * msg, int flags)
 {
   vls_handle_t vlsh;
   ssize_t size;
@@ -1714,13 +1761,42 @@ recvmsg (int fd, struct msghdr * message, int flags)
   vlsh = ldp_fd_to_vlsh (fd);
   if (vlsh != VLS_INVALID_HANDLE)
     {
-      LDBG (0, "LDP-TBD");
-      errno = ENOSYS;
-      size = -1;
+      struct iovec *iov = msg->msg_iov;
+      ssize_t max_deq, total = 0;
+      int i, rv;
+
+      max_deq = vls_attr (vlsh, VPPCOM_ATTR_GET_NREAD, 0, 0);
+      if (!max_deq)
+       return 0;
+
+      for (i = 0; i < msg->msg_iovlen; i++)
+       {
+         rv = ldp_vls_recvfrom (vlsh, iov[i].iov_base, iov[i].iov_len, flags,
+                                (i == 0 ? msg->msg_name : NULL),
+                                (i == 0 ? &msg->msg_namelen : NULL));
+         if (rv <= 0)
+           break;
+         else
+           {
+             total += rv;
+             if (rv < iov[i].iov_len)
+               break;
+           }
+         if (total >= max_deq)
+           break;
+       }
+
+      if (rv < 0 && total == 0)
+       {
+         errno = -rv;
+         size = -1;
+       }
+      else
+       size = total;
     }
   else
     {
-      size = libc_recvmsg (fd, message, flags);
+      size = libc_recvmsg (fd, msg, flags);
     }
 
   return size;