Index: /trunk/docs/Changelog
===================================================================
--- /trunk/docs/Changelog	(revision 194)
+++ /trunk/docs/Changelog	(revision 195)
@@ -1,3 +1,5 @@
 2.5.1:
+	* report process/user for open ports on FreeBSD (code
+	  lifted from FreeBSD sockstat.c)
 	* fix for config reload issue with stealth mode (reported by
 	  siim)
Index: /trunk/src/sh_port2proc.c
===================================================================
--- /trunk/src/sh_port2proc.c	(revision 194)
+++ /trunk/src/sh_port2proc.c	(revision 195)
@@ -60,4 +60,75 @@
 #define FIL__  _("sh_port2proc.c")
 
+struct sock_store {
+  unsigned long sock;
+  size_t        pid;
+  char *        path;
+  char *        user;
+  struct sock_store * next;
+};
+
+/* /proc: 
+ *        linux:     /proc/pid/exe
+ *        freebsd:   /proc/pid/file
+ *        solaris10: /proc/pid/path/a.out
+ */
+static void get_user_and_path (struct sock_store * add)
+{
+  extern char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
+
+  char        path[128];
+  char *      buf;
+  struct stat sbuf;
+  int         len;
+  char *      tmp;
+
+  sl_snprintf (path, sizeof(path), "/proc/%ld/exe", (unsigned long) add->pid);
+
+  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
+    {
+      goto linkread;
+    }
+
+  sl_snprintf (path, sizeof(path), "/proc/%ld/file", (unsigned long) add->pid);
+
+  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
+    {
+      goto linkread;
+    }
+
+  sl_snprintf (path, sizeof(path), "/proc/%ld/path/a.out", (unsigned long) add->pid);
+
+  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
+    {
+      goto linkread;
+    }
+
+  return;
+
+ linkread:
+
+  buf = SH_ALLOC(PATH_MAX);
+  len = readlink(path, buf, PATH_MAX);   /* flawfinder: ignore */
+  len = (len >= PATH_MAX) ? (PATH_MAX-1) : len;
+
+  if (len > 0)
+    { 
+      buf[len] = '\0';
+      add->path = buf;
+    }
+  else
+    {
+      SH_FREE(buf);
+    }
+
+  add->user = SH_ALLOC(USER_MAX);
+  tmp  = sh_unix_getUIDname (SH_ERR_ALL, sbuf.st_uid, add->user, USER_MAX);
+
+  if (!tmp)
+    sl_snprintf (add->user, USER_MAX, "%ld", (unsigned long) sbuf.st_uid);
+
+  return;
+}
+
 #endif
 
@@ -92,67 +163,4 @@
   struct sock_store * next;
 };
-
-/* /proc: 
- *        linux:     /proc/pid/exe
- *        freebsd:   /proc/pid/file
- *        solaris10: /proc/pid/path/a.out
- */
-static void get_user_and_path (struct sock_store * add)
-{
-  extern char *  sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
-
-  char        path[128];
-  char *      buf;
-  struct stat sbuf;
-  int         len;
-  char *      tmp;
-
-  sl_snprintf (path, sizeof(path), "/proc/%ld/exe", (unsigned long) add->pid);
-
-  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
-    {
-      goto linkread;
-    }
-
-  sl_snprintf (path, sizeof(path), "/proc/%ld/file", (unsigned long) add->pid);
-
-  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
-    {
-      goto linkread;
-    }
-
-  sl_snprintf (path, sizeof(path), "/proc/%ld/path/a.out", (unsigned long) add->pid);
-
-  if (0 == retry_lstat(FIL__, __LINE__, path, &sbuf) && S_ISLNK(sbuf.st_mode))
-    {
-      goto linkread;
-    }
-
-  return;
-
- linkread:
-
-  buf = SH_ALLOC(PATH_MAX);
-  len = readlink(path, buf, PATH_MAX);   /* flawfinder: ignore */
-  len = (len >= PATH_MAX) ? (PATH_MAX-1) : len;
-
-  if (len > 0)
-    { 
-      buf[len] = '\0';
-      add->path = buf;
-    }
-  else
-    {
-      SH_FREE(buf);
-    }
-
-  add->user = SH_ALLOC(USER_MAX);
-  tmp  = sh_unix_getUIDname (SH_ERR_ALL, sbuf.st_uid, add->user, USER_MAX);
-
-  if (!tmp)
-    sl_snprintf (add->user, USER_MAX, "%ld", (unsigned long) sbuf.st_uid);
-
-  return;
-}
 
 #if defined(__linux__)
@@ -441,5 +449,4 @@
 static int       opt_c = 0;         /* Show connected sockets */
 static int       opt_l = 1;         /* Show listening sockets */
-static int       opt_u = 0;         /* Show Unix domain sockets */
 static int       opt_v = 0;         /* Verbose mode */
 
@@ -467,7 +474,13 @@
   if (len > 0)
     {
-      void xbuf = SH_ALLOC(len);
-      memcpy(xbuf, buf, len0);
-      SH_FREE(buf);
+      void * xbuf = SH_ALLOC(len);
+      if (buf)
+	{
+	  if (len0 <= len)
+	    memcpy(xbuf, buf, len0);
+	  else
+	    memset(xbuf, '\0', len);
+	  SH_FREE(buf);
+	}
       return xbuf;
     }
@@ -542,5 +555,5 @@
 
         buf = NULL;
-        bufsize  = 8192;
+        bufsize  = 1000;
 	bufsize0 = bufsize;
         retry = 5;
@@ -552,13 +565,15 @@
                         if (sysctlbyname(varname, buf, &len, NULL, 0) == 0)
                                 break;
-                        if (errno == ENOENT)
+		        if (errno == ENOENT)
                                 goto out;
                         if (errno != ENOMEM)
 			  {
 			    SH_MUTEX_LOCK(mutex_thread_nolog);
-			    sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN, 
+			    sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 
+					    0, MSG_E_SUBGEN, 
 					    _("sysctlbyname()"), 
 					    _("gather_inet"));
 			    SH_MUTEX_UNLOCK(mutex_thread_nolog);
+			    SH_FREE(buf);
 			    return;
 			  }
@@ -674,5 +689,6 @@
         }
 out:
-        free(buf);
+	if (buf)
+	  SH_FREE(buf);
 }
 
@@ -689,4 +705,5 @@
                 if (errno != ENOMEM)
 		  {
+		    volatile int status = errno;
 		    SH_MUTEX_LOCK(mutex_thread_nolog);
 		    sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
@@ -702,4 +719,5 @@
                 if (errno != ENOMEM)
 		  {
+		    volatile int status = errno;
 		    SH_MUTEX_LOCK(mutex_thread_nolog);
 		    sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_SUBGEN,
@@ -727,4 +745,5 @@
                 if (errno != ESRCH)
 		  {
+		    volatile int status = errno;
 		    SH_MUTEX_LOCK(mutex_thread_nolog);
 		    sh_error_handle(SH_ERR_WARN, FIL__, __LINE__, status, MSG_E_SUBGEN,
@@ -741,6 +760,8 @@
 			  char * user, size_t userlen)
 {
+  int n, hash;
   struct xfile *xf;
   struct in_addr * haddr;
+  struct sock * s;
   
   for (xf = xfiles, n = 0; n < nxfiles; ++n, ++xf) {
@@ -756,4 +777,13 @@
 	break;
     
+    if (!s)
+      continue;
+
+    /* fprintf(stderr, "FIXME: %d %d, %d %d, %d %d, %d, %d\n", s->proto, proto,
+       s->family, AF_INET,
+       sport, ntohs(((struct sockaddr_in *)(&s->laddr))->sin_port),
+       (int) xf->xf_uid, (int)xf->xf_pid);
+    */
+
     if (s->proto != proto)
       continue;
@@ -762,16 +792,39 @@
       continue;
 
-    if (sport != ntohs(((struct sockaddr_in *)s)->sin_port))
+    if (sport != ntohs(((struct sockaddr_in *)(&s->laddr))->sin_port))
       continue;
 
-    haddr = &((struct sockaddr_in *)s)->sin_addr;
-    if (haddr.s_addr == saddr->s_addr)
+    haddr = &((struct sockaddr_in *)(&s->laddr))->sin_addr;
+
+    /* fprintf(stderr, "FIXME: %s\n", inet_ntoa(*haddr)); */
+    /* fprintf(stderr, "FIXME: %s\n", inet_ntoa(*saddr)); */
+
+    if (haddr->s_addr == saddr->s_addr || inet_lnaof(*saddr) == INADDR_ANY || inet_lnaof(*haddr) == INADDR_ANY)
       {
-	char * tmp  = sh_unix_getUIDname (SH_ERR_ALL, xf->xf_uid, user, userlen);
-	if (!tmp)
-	  sl_snprintf (user, userlen, "%ld", (unsigned long) xf->xf_uid);
-	return sh_util_strdup(getprocname(xf->xf_pid));
+	struct sock_store try;
+	
+	try.pid  = xf->xf_pid;
+	try.path = NULL;
+	try.user = NULL;
+	get_user_and_path (&try); /* Try to get info from /proc */
+
+	if (try.path == NULL)
+	  {
+	    extern char * sh_unix_getUIDname (int level, uid_t uid, char * out, size_t len);
+	    char * tmp  = sh_unix_getUIDname (SH_ERR_ALL, xf->xf_uid, user, userlen);
+	    if (!tmp)
+	      sl_snprintf (user, userlen, "%ld", (unsigned long) xf->xf_uid);
+	    return sh_util_strdup(getprocname(xf->xf_pid));
+	  }
+	else
+	  {
+	    sl_strlcpy(user, try.user, userlen);
+	    SH_FREE(try.user);
+	    return try.path;
+	  }
       }
   }
+  sl_strlcpy(user, "-", userlen);
+  return sh_util_strdup("-");
 }
 
@@ -798,5 +851,8 @@
 
   for (i = 0; i < HASHSIZE; ++i)
-    sockdel(sockhash[i]);
+    {
+      sockdel(sockhash[i]);
+      sockhash[i] = NULL;
+    }
 
   /* Inet connections
