api: Add FreeBSD specific mechanisms for unix sockets

FreeBSD doesn't support SCM_CREDENTIALS, but has an equivalent mechanism
called SCM_CRED. This is documented in unix(4), use SCM_CREDS on
FreeBSD.

Type: improvement
Change-Id: Iaf4ec0d68445239c06fa0eef6c25db7e3328e989
Signed-off-by: Tom Jones <thj@freebsd.org>
diff --git a/src/vlibmemory/socket_client.c b/src/vlibmemory/socket_client.c
index 5fa19c6..ad28136 100644
--- a/src/vlibmemory/socket_client.c
+++ b/src/vlibmemory/socket_client.c
@@ -22,6 +22,14 @@
 #define _GNU_SOURCE
 #include <sys/socket.h>
 
+#ifdef __FreeBSD__
+#define _WANT_UCRED
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/un.h>
+#endif /* __FreeBSD__ */
+
 #include <svm/ssvm.h>
 #include <vlibmemory/socket_client.h>
 #include <vlibmemory/memory_client.h>
@@ -278,7 +286,11 @@
   struct msghdr mh = { 0 };
   struct iovec iov[1];
   ssize_t size = 0;
+#ifdef __linux__
   struct ucred *cr = 0;
+#elif __FreeBSD__
+  struct cmsgcred *cr = 0;
+#endif /* __linux__ */
   struct cmsghdr *cmsg;
   pid_t pid __attribute__ ((unused));
   uid_t uid __attribute__ ((unused));
@@ -318,6 +330,7 @@
     {
       if (cmsg->cmsg_level == SOL_SOCKET)
 	{
+#ifdef __linux__
 	  if (cmsg->cmsg_type == SCM_CREDENTIALS)
 	    {
 	      cr = (struct ucred *) CMSG_DATA (cmsg);
@@ -325,6 +338,15 @@
 	      gid = cr->gid;
 	      pid = cr->pid;
 	    }
+#elif __FreeBSD__
+	  if (cmsg->cmsg_type == SCM_CREDS)
+	    {
+	      cr = (struct cmsgcred *) CMSG_DATA (cmsg);
+	      uid = cr->cmcred_uid;
+	      gid = cr->cmcred_gid;
+	      pid = cr->cmcred_pid;
+	    }
+#endif /* __linux__ */
 	  else if (cmsg->cmsg_type == SCM_RIGHTS)
 	    {
 	      clib_memcpy_fast (fds, CMSG_DATA (cmsg), sizeof (int) * n_fds);