Chip Davis : iphlpapi: Implement GetUdp6Table() for Mac OS and FreeBSD.

Alexandre Julliard julliard at winehq.org
Mon Apr 6 15:53:21 CDT 2020


Module: wine
Branch: master
Commit: 73ad2954a3913743fa734f71774527dc6f879aa3
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=73ad2954a3913743fa734f71774527dc6f879aa3

Author: Chip Davis <cdavis at codeweavers.com>
Date:   Sun Apr  5 17:29:02 2020 -0500

iphlpapi: Implement GetUdp6Table() for Mac OS and FreeBSD.

Signed-off-by: Chip Davis <cdavis at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/iphlpapi/ipstats.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 99 insertions(+)

diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c
index ae6ccafbf4..efb4d64c90 100644
--- a/dlls/iphlpapi/ipstats.c
+++ b/dlls/iphlpapi/ipstats.c
@@ -3070,6 +3070,105 @@ DWORD build_udp6_table( UDP_TABLE_CLASS class, void **tablep, BOOL order, HANDLE
         }
         else ret = ERROR_NOT_SUPPORTED;
     }
+#elif defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_STRUCT_XINPGEN)
+    {
+        static const char zero[sizeof(IN6_ADDR)] = {0};
+
+        size_t len = 0;
+        char *buf = NULL;
+        struct xinpgen *xig, *orig_xig;
+        struct pid_map *map = NULL;
+        unsigned num_entries;
+        struct ipv6_addr_scope *addr_scopes = NULL;
+        unsigned int addr_scopes_size = 0;
+
+        if (sysctlbyname( "net.inet.udp.pcblist", NULL, &len, NULL, 0 ) < 0)
+        {
+            ERR( "Failure to read net.inet.udp.pcblist via sysctlbyname!\n" );
+            ret = ERROR_NOT_SUPPORTED;
+            goto done;
+        }
+
+        buf = HeapAlloc( GetProcessHeap(), 0, len );
+        if (!buf)
+        {
+            ret = ERROR_OUTOFMEMORY;
+            goto done;
+        }
+
+        if (sysctlbyname( "net.inet.udp.pcblist", buf, &len, NULL, 0 ) < 0)
+        {
+            ERR ("Failure to read net.inet.udp.pcblist via sysctlbyname!\n");
+            ret = ERROR_NOT_SUPPORTED;
+            goto done;
+        }
+
+        addr_scopes = get_ipv6_addr_scope_table( &addr_scopes_size );
+        if (!addr_scopes)
+        {
+            ret = ERROR_OUTOFMEMORY;
+            goto done;
+        }
+
+        if (class >= UDP_TABLE_OWNER_PID) map = get_pid_map( &num_entries );
+
+        /* Might be nothing here; first entry is just a header it seems */
+        if (len <= sizeof (struct xinpgen)) goto done;
+
+        orig_xig = (struct xinpgen *)buf;
+        xig = orig_xig;
+
+        for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
+             xig->xig_len > sizeof (struct xinpgen);
+             xig = (struct xinpgen *)((char *)xig + xig->xig_len))
+        {
+#if __FreeBSD_version >= 1200026
+            struct xinpcb *in = (struct xinpcb *)xig;
+            struct xsocket *sock = &in->xi_socket;
+#else
+            struct inpcb *in = &((struct xinpcb *)xig)->xi_inp;
+            struct xsocket *sock = &((struct xinpcb *)xig)->xi_socket;
+#endif
+
+            /* Ignore sockets for other protocols */
+            if (sock->xso_protocol != IPPROTO_UDP)
+                continue;
+
+            /* Ignore PCBs that were freed while generating the data */
+            if (in->inp_gencnt > orig_xig->xig_gen)
+                continue;
+
+            /* we're only interested in IPv6 addresses */
+            if (!(in->inp_vflag & INP_IPV6) ||
+                (in->inp_vflag & INP_IPV4))
+                continue;
+
+            /* If all 0's, skip it */
+            if (!memcmp( &in->in6p_laddr.s6_addr, zero, sizeof(zero) ) && !in->inp_lport)
+                continue;
+
+            /* Fill in structure details */
+            memcpy(row.ucLocalAddr, &in->in6p_laddr.s6_addr, sizeof(row.ucLocalAddr));
+            row.dwLocalPort = in->inp_lport;
+            row.dwLocalScopeId = find_ipv6_addr_scope((const IN6_ADDR *)&row.ucLocalAddr, addr_scopes, addr_scopes_size);
+            if (class >= UDP_TABLE_OWNER_PID)
+                row.dwOwningPid = find_owning_pid( map, num_entries, (UINT_PTR)sock->so_pcb );
+            if (class >= UDP_TABLE_OWNER_MODULE)
+            {
+                row.liCreateTimestamp.QuadPart = 0; /* FIXME */
+                row.u.dwFlags = 0;
+                row.u.SpecificPortBind = !(in->inp_flags & INP_ANONPORT);
+                memset( &row.OwningModuleInfo, 0, sizeof(row.OwningModuleInfo) );
+            }
+            if (!(table = append_table_row( heap, flags, table, &table_size, &count, &row, row_size )))
+                break;
+        }
+
+    done:
+        HeapFree( GetProcessHeap(), 0, map );
+        HeapFree( GetProcessHeap(), 0, buf );
+        HeapFree( GetProcessHeap(), 0, addr_scopes );
+    }
 #else
     FIXME( "not implemented\n" );
     ret = ERROR_NOT_SUPPORTED;




More information about the wine-cvs mailing list