For Windows platform, there are different ways to get error numbers
for differnt situations. For C library functions, errno is set like the way
they are set for Linux. For Windows API functions, it has to be gotten from
GetLastError().  For winsock2, errno has to be obtained from WSAGetLastError().

The new functions will have the first users in an upcoming commit.

Signed-off-by: Gurucharan Shetty <[email protected]>
---
 lib/socket-util.c |   39 +++++++++++++++++++++++++++++++++++++++
 lib/socket-util.h |    7 +++++++
 lib/util.c        |    7 +++++++
 lib/util.h        |    4 ++++
 4 files changed, 57 insertions(+)

diff --git a/lib/socket-util.c b/lib/socket-util.c
index 24fc6fe..7b01ed7 100644
--- a/lib/socket-util.c
+++ b/lib/socket-util.c
@@ -1226,3 +1226,42 @@ af_inet_ifreq_ioctl(const char *name, struct ifreq *ifr, 
unsigned long int cmd,
     return error;
 }
 
+/* In Windows platform, errno is not set for socket calls.
+ * The last error has to be gotten from WSAGetLastError(). */
+int
+sock_errno()
+{
+#ifdef _WIN32
+    int error = WSAGetLastError();
+
+    /* In case of non-blocking sockets, EAGAIN is an error that is checked to
+     * retry. To prevent multiple #ifdef's across the code base, set the error
+     * as EAGAIN when it is WSAEWOULDBLOCK. */
+    if (error == WSAEWOULDBLOCK) {
+        error = EAGAIN;
+    }
+    return error;
+#else
+    return errno;
+#endif
+}
+
+/* Convert socket error number to a string.
+ * The caller should call LocalFree() on the returned buffer. */
+char *
+sock_strerror(int error)
+{
+#ifdef _WIN32
+    char *buffer;
+    /* For socket errors, EAGAIN should be WSAEWOULDBLOCK. */
+    if (error == EAGAIN) {
+        error = WSAEWOULDBLOCK;
+    }
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
+                  | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, 0,
+                  (char *)&buffer, 0, NULL);
+    return buffer;
+#else
+    return (char *)ovs_strerror(error);
+#endif
+}
diff --git a/lib/socket-util.h b/lib/socket-util.h
index d5b44b0..4703134 100644
--- a/lib/socket-util.h
+++ b/lib/socket-util.h
@@ -79,4 +79,11 @@ int af_inet_ioctl(unsigned long int command, const void 
*arg);
 int af_inet_ifreq_ioctl(const char *name, struct ifreq *,
                         unsigned long int cmd, const char *cmd_name);
 
+/* Functions to get errno and its corresponding string definition across both
+ * Linux and Windows. In Windows, for socket related functions, errno is not
+ * set. One has to get the errno using WSAGetLastError() and its string
+ * equivalent through FormatMessage(). */
+int sock_errno(void);
+char *sock_strerror(int error);
+
 #endif /* socket-util.h */
diff --git a/lib/util.c b/lib/util.c
index 845f86c..b48919c 100644
--- a/lib/util.c
+++ b/lib/util.c
@@ -1653,6 +1653,13 @@ exit:
     return ok;
 }
 
+#ifndef _WIN32
+void
+LocalFree(char *buffer OVS_UNUSED)
+{
+}
+#endif
+
 #ifdef _WIN32
 
 /* Calls FormatMessage() with GetLastError() as an argument. Returns
diff --git a/lib/util.h b/lib/util.h
index 2e3d1da..cf84f34 100644
--- a/lib/util.h
+++ b/lib/util.h
@@ -490,6 +490,10 @@ void bitwise_put(uint64_t value,
 uint64_t bitwise_get(const void *src, unsigned int src_len,
                      unsigned int src_ofs, unsigned int n_bits);
 
+#ifndef _WIN32
+void LocalFree(char *buffer);
+#endif
+
 #ifdef _WIN32
 
 char *ovs_lasterror_to_string(void);
-- 
1.7.9.5

_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to