2 * nsiproxy.sys tcp module
4 * Copyright 2003, 2006, 2011 Juan Lang
5 * Copyright 2007 TransGaming Technologies Inc.
6 * Copyright 2021 Huw Davies
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include <sys/types.h>
29 #include <sys/socket.h>
33 #ifdef HAVE_SYS_PARAM_H
34 #include <sys/param.h>
37 #ifdef HAVE_SYS_SOCKETVAR_H
38 #include <sys/socketvar.h>
41 #ifdef HAVE_NETINET_IN_H
42 #include <netinet/in.h>
45 #ifdef HAVE_NETINET_IN_PCB_H
46 #include <netinet/in_pcb.h>
49 #ifdef HAVE_NETINET_IP_VAR_H
50 #include <netinet/ip_var.h>
53 #ifdef HAVE_SYS_QUEUE_H
54 #include <sys/queue.h>
57 #ifdef HAVE_NETINET_TCP_VAR_H
58 #include <netinet/tcp_var.h>
61 #ifdef HAVE_NETINET_TCP_FSM_H
62 #include <netinet/tcp_fsm.h>
65 #ifdef HAVE_SYS_SYSCTL_H
66 #include <sys/sysctl.h>
73 #ifdef HAVE_LIBPROCSTAT_H
74 #include <libprocstat.h>
82 #define WIN32_NO_STATUS
93 #include "wine/debug.h"
94 #include "wine/server.h"
96 #include "unix_private.h"
98 #ifndef HAVE_NETINET_TCP_FSM_H
99 #define TCPS_ESTABLISHED 1
100 #define TCPS_SYN_SENT 2
101 #define TCPS_SYN_RECEIVED 3
102 #define TCPS_FIN_WAIT_1 4
103 #define TCPS_FIN_WAIT_2 5
104 #define TCPS_TIME_WAIT 6
105 #define TCPS_CLOSED 7
106 #define TCPS_CLOSE_WAIT 8
107 #define TCPS_LAST_ACK 9
108 #define TCPS_LISTEN 10
109 #define TCPS_CLOSING 11
112 WINE_DEFAULT_DEBUG_CHANNEL(nsi
);
114 static NTSTATUS
tcp_stats_get_all_parameters( const void *key
, UINT key_size
, void *rw_data
, UINT rw_size
,
115 void *dynamic_data
, UINT dynamic_size
, void *static_data
, UINT static_size
)
117 struct nsi_tcp_stats_dynamic dyn
;
118 struct nsi_tcp_stats_static stat
;
119 const USHORT
*family
= key
;
121 TRACE( "%p %d %p %d %p %d %p %d\n", key
, key_size
, rw_data
, rw_size
, dynamic_data
, dynamic_size
,
122 static_data
, static_size
);
124 if (*family
!= WS_AF_INET
&& *family
!= WS_AF_INET6
) return STATUS_NOT_SUPPORTED
;
126 memset( &dyn
, 0, sizeof(dyn
) );
127 memset( &stat
, 0, sizeof(stat
) );
131 NTSTATUS status
= STATUS_NOT_SUPPORTED
;
132 static const char hdr
[] = "Tcp:";
136 /* linux merges tcp4 and tcp6 stats, so simply supply that for either family */
137 if (!(fp
= fopen( "/proc/net/snmp", "r" ))) return STATUS_NOT_SUPPORTED
;
139 while ((ptr
= fgets( buf
, sizeof(buf
), fp
)))
141 if (ascii_strncasecmp( buf
, hdr
, sizeof(hdr
) - 1 )) continue;
142 /* last line was a header, get another */
143 if (!(ptr
= fgets( buf
, sizeof(buf
), fp
))) break;
144 if (!ascii_strncasecmp( buf
, hdr
, sizeof(hdr
) - 1 ))
146 UINT in_segs
, out_segs
;
148 sscanf( ptr
, "%u %u %u %u %u %u %u %u %u %u %u %u %u %u",
163 dyn
.in_segs
= in_segs
;
164 dyn
.out_segs
= out_segs
;
165 if (dynamic_data
) *(struct nsi_tcp_stats_dynamic
*)dynamic_data
= dyn
;
166 if (static_data
) *(struct nsi_tcp_stats_static
*)static_data
= stat
;
167 status
= STATUS_SUCCESS
;
174 #elif defined(HAVE_SYS_SYSCTL_H) && defined(TCPCTL_STATS) && (defined(HAVE_STRUCT_TCPSTAT_TCPS_CONNATTEMPT) || defined(HAVE_STRUCT_TCP_STATS_TCPS_CONNATTEMPT))
176 #ifndef TCPTV_MIN /* got removed in Mac OS X for some reason */
178 #define TCPTV_REXMTMAX 128
180 int mib
[] = { CTL_NET
, PF_INET
, IPPROTO_TCP
, TCPCTL_STATS
};
182 #if defined(HAVE_STRUCT_TCPSTAT_TCPS_CONNATTEMPT)
183 struct tcpstat tcp_stat
;
184 #elif defined(HAVE_STRUCT_TCP_STATS_TCPS_CONNATTEMPT)
185 struct tcp_stats tcp_stat
;
187 size_t needed
= sizeof(tcp_stat
);
189 if (sysctl( mib
, ARRAY_SIZE(mib
), &tcp_stat
, &needed
, NULL
, 0 ) == -1) return STATUS_NOT_SUPPORTED
;
191 stat
.rto_algo
= MIB_TCP_RTO_VANJ
;
192 stat
.rto_min
= TCPTV_MIN
;
193 stat
.rto_max
= TCPTV_REXMTMAX
;
195 dyn
.active_opens
= tcp_stat
.tcps_connattempt
;
196 dyn
.passive_opens
= tcp_stat
.tcps_accepts
;
197 dyn
.attempt_fails
= tcp_stat
.tcps_conndrops
;
198 dyn
.est_rsts
= tcp_stat
.tcps_drops
;
201 dyn
.in_segs
= tcp_stat
.tcps_rcvtotal
;
202 dyn
.out_segs
= tcp_stat
.tcps_sndtotal
- tcp_stat
.tcps_sndrexmitpack
;
203 dyn
.retrans_segs
= tcp_stat
.tcps_sndrexmitpack
;
204 dyn
.out_rsts
= tcp_stat
.tcps_sndctrl
- tcp_stat
.tcps_closed
;
205 dyn
.in_errs
= tcp_stat
.tcps_rcvbadsum
+ tcp_stat
.tcps_rcvbadoff
+ tcp_stat
.tcps_rcvmemdrop
+ tcp_stat
.tcps_rcvshort
;
206 dyn
.num_conns
= tcp_stat
.tcps_connects
;
207 if (dynamic_data
) *(struct nsi_tcp_stats_dynamic
*)dynamic_data
= dyn
;
208 if (static_data
) *(struct nsi_tcp_stats_static
*)static_data
= stat
;
209 return STATUS_SUCCESS
;
212 FIXME( "not implemented\n" );
213 return STATUS_NOT_IMPLEMENTED
;
217 static inline MIB_TCP_STATE
tcp_state_to_mib_state( int state
)
221 case TCPS_ESTABLISHED
: return MIB_TCP_STATE_ESTAB
;
222 case TCPS_SYN_SENT
: return MIB_TCP_STATE_SYN_SENT
;
223 case TCPS_SYN_RECEIVED
: return MIB_TCP_STATE_SYN_RCVD
;
224 case TCPS_FIN_WAIT_1
: return MIB_TCP_STATE_FIN_WAIT1
;
225 case TCPS_FIN_WAIT_2
: return MIB_TCP_STATE_FIN_WAIT2
;
226 case TCPS_TIME_WAIT
: return MIB_TCP_STATE_TIME_WAIT
;
227 case TCPS_CLOSE_WAIT
: return MIB_TCP_STATE_CLOSE_WAIT
;
228 case TCPS_LAST_ACK
: return MIB_TCP_STATE_LAST_ACK
;
229 case TCPS_LISTEN
: return MIB_TCP_STATE_LISTEN
;
230 case TCPS_CLOSING
: return MIB_TCP_STATE_CLOSING
;
232 case TCPS_CLOSED
: return MIB_TCP_STATE_CLOSED
;
236 struct ipv6_addr_scope
*get_ipv6_addr_scope_table( unsigned int *size
)
238 struct ipv6_addr_scope
*table
= NULL
, *new_table
;
239 unsigned int table_size
= 0, num
= 0;
246 if (!(fp
= fopen( "/proc/net/if_inet6", "r" ))) goto failed
;
248 while ((ptr
= fgets( buf
, sizeof(buf
), fp
)))
252 struct ipv6_addr_scope
*entry
;
255 if (sscanf( ptr
, "%4hx%4hx%4hx%4hx%4hx%4hx%4hx%4hx %*s %*s %x",
256 a
, a
+ 1, a
+ 2, a
+ 3, a
+ 4, a
+ 5, a
+ 6, a
+ 7, &scope
) != 9)
259 if (++num
> table_size
)
261 if (!table_size
) table_size
= 4;
262 else table_size
*= 2;
263 if (!(new_table
= realloc( table
, table_size
* sizeof(table
[0]) )))
271 entry
= table
+ num
- 1;
272 for (i
= 0; i
< 8; i
++)
273 entry
->addr
.u
.Word
[i
] = htons( a
[i
] );
274 entry
->scope
= htons( scope
);
279 #elif defined(HAVE_GETIFADDRS)
281 struct ifaddrs
*addrs
, *cur
;
283 if (getifaddrs( &addrs
) == -1) goto failed
;
285 for (cur
= addrs
; cur
; cur
= cur
->ifa_next
)
287 struct sockaddr_in6
*sin6
;
288 struct ipv6_addr_scope
*entry
;
290 if (cur
->ifa_addr
->sa_family
!= AF_INET6
) continue;
292 if (++num
> table_size
)
294 if (!table_size
) table_size
= 4;
295 else table_size
*= 2;
296 if (!(new_table
= realloc( table
, table_size
* sizeof(table
[0]) )))
298 freeifaddrs( addrs
);
304 sin6
= (struct sockaddr_in6
*)cur
->ifa_addr
;
305 entry
= table
+ num
- 1;
306 memcpy( &entry
->addr
, &sin6
->sin6_addr
, sizeof(entry
->addr
) );
307 entry
->scope
= sin6
->sin6_scope_id
;
310 freeifaddrs( addrs
);
313 FIXME( "not implemented\n" );
325 UINT
find_ipv6_addr_scope( const IN6_ADDR
*addr
, const struct ipv6_addr_scope
*table
, unsigned int size
)
327 const BYTE multicast_scope_mask
= 0x0F;
328 const BYTE multicast_scope_shift
= 0;
331 if (WS_IN6_IS_ADDR_UNSPECIFIED( addr
)) return 0;
333 if (WS_IN6_IS_ADDR_MULTICAST( addr
))
334 return htons( (addr
->u
.Byte
[1] & multicast_scope_mask
) >> multicast_scope_shift
);
336 if (!table
) return -1;
338 for (i
= 0; i
< size
; i
++)
339 if (!memcmp( &table
[i
].addr
, addr
, sizeof(table
[i
].addr
) ))
340 return table
[i
].scope
;
345 struct pid_map
*get_pid_map( unsigned int *num_entries
)
348 unsigned int i
= 0, buffer_len
= 4096, process_count
, pos
= 0;
350 char *buffer
= NULL
, *new_buffer
;
352 if (!(buffer
= malloc( buffer_len
))) return NULL
;
356 SERVER_START_REQ( list_processes
)
358 wine_server_set_reply( req
, buffer
, buffer_len
);
359 ret
= wine_server_call( req
);
360 buffer_len
= reply
->info_size
;
361 process_count
= reply
->process_count
;
365 if (ret
!= STATUS_INFO_LENGTH_MISMATCH
) break;
367 if (!(new_buffer
= realloc( buffer
, buffer_len
)))
375 if (!(map
= malloc( process_count
* sizeof(*map
) )))
381 for (i
= 0; i
< process_count
; ++i
)
383 const struct process_info
*process
;
385 pos
= (pos
+ 7) & ~7;
386 process
= (const struct process_info
*)(buffer
+ pos
);
388 map
[i
].pid
= process
->pid
;
389 map
[i
].unix_pid
= process
->unix_pid
;
391 pos
+= sizeof(struct process_info
) + process
->name_len
;
392 pos
= (pos
+ 7) & ~7;
393 pos
+= process
->thread_count
* sizeof(struct thread_info
);
397 *num_entries
= process_count
;
401 unsigned int find_owning_pid( struct pid_map
*map
, unsigned int num_entries
, UINT_PTR inode
)
404 unsigned int i
, len_socket
;
407 sprintf( socket
, "socket:[%zu]", inode
);
408 len_socket
= strlen( socket
);
409 for (i
= 0; i
< num_entries
; i
++)
412 struct dirent
*dirent
;
415 sprintf( dir
, "/proc/%u/fd", map
[i
].unix_pid
);
416 if ((dirfd
= opendir( dir
)))
418 while ((dirent
= readdir( dirfd
)))
420 char link
[sizeof(dirent
->d_name
) + 32], name
[32];
423 sprintf( link
, "/proc/%u/fd/%s", map
[i
].unix_pid
, dirent
->d_name
);
424 if ((len
= readlink( link
, name
, sizeof(name
) - 1 )) > 0) name
[len
] = 0;
425 if (len
== len_socket
&& !strcmp( socket
, name
))
435 #elif defined(HAVE_LIBPROCSTAT)
436 struct procstat
*pstat
;
437 struct kinfo_proc
*proc
;
438 struct filestat_list
*fds
;
440 struct sockstat sock
;
441 unsigned int i
, proc_count
;
443 pstat
= procstat_open_sysctl();
444 if (!pstat
) return 0;
446 for (i
= 0; i
< num_entries
; i
++)
448 proc
= procstat_getprocs( pstat
, KERN_PROC_PID
, map
[i
].unix_pid
, &proc_count
);
449 if (!proc
|| proc_count
< 1) continue;
451 fds
= procstat_getfiles( pstat
, proc
, 0 );
454 procstat_freeprocs( pstat
, proc
);
458 STAILQ_FOREACH( fd
, fds
, next
)
460 char errbuf
[_POSIX2_LINE_MAX
];
462 if (fd
->fs_type
!= PS_FST_TYPE_SOCKET
) continue;
464 procstat_get_socket_info( pstat
, fd
, &sock
, errbuf
);
466 if (sock
.so_pcb
== inode
)
468 procstat_freefiles( pstat
, fds
);
469 procstat_freeprocs( pstat
, proc
);
470 procstat_close( pstat
);
475 procstat_freefiles( pstat
, fds
);
476 procstat_freeprocs( pstat
, proc
);
479 procstat_close( pstat
);
481 #elif defined(HAVE_PROC_PIDINFO)
482 struct proc_fdinfo
*fds
;
483 struct socket_fdinfo sock
;
484 unsigned int i
, j
, n
;
486 for (i
= 0; i
< num_entries
; i
++)
488 int fd_len
= proc_pidinfo( map
[i
].unix_pid
, PROC_PIDLISTFDS
, 0, NULL
, 0 );
489 if (fd_len
<= 0) continue;
491 fds
= malloc( fd_len
);
494 proc_pidinfo( map
[i
].unix_pid
, PROC_PIDLISTFDS
, 0, fds
, fd_len
);
495 n
= fd_len
/ sizeof(struct proc_fdinfo
);
496 for (j
= 0; j
< n
; j
++)
498 if (fds
[j
].proc_fdtype
!= PROX_FDTYPE_SOCKET
) continue;
500 proc_pidfdinfo( map
[i
].unix_pid
, fds
[j
].proc_fd
, PROC_PIDFDSOCKETINFO
, &sock
, sizeof(sock
) );
501 if (sock
.psi
.soi_pcb
== inode
)
512 FIXME( "not implemented\n" );
517 static NTSTATUS
tcp_conns_enumerate_all( UINT filter
, struct nsi_tcp_conn_key
*key_data
, UINT key_size
,
518 void *rw
, UINT rw_size
,
519 struct nsi_tcp_conn_dynamic
*dynamic_data
, UINT dynamic_size
,
520 struct nsi_tcp_conn_static
*static_data
, UINT static_size
, UINT_PTR
*count
)
523 NTSTATUS status
= STATUS_SUCCESS
;
524 BOOL want_data
= key_size
|| rw_size
|| dynamic_size
|| static_size
;
525 struct nsi_tcp_conn_key key
;
526 struct nsi_tcp_conn_dynamic dyn
;
527 struct nsi_tcp_conn_static stat
;
528 struct ipv6_addr_scope
*addr_scopes
= NULL
;
529 unsigned int addr_scopes_size
= 0, pid_map_size
= 0;
530 struct pid_map
*pid_map
= NULL
;
539 if (!(fp
= fopen( "/proc/net/tcp", "r" ))) return ERROR_NOT_SUPPORTED
;
541 memset( &key
, 0, sizeof(key
) );
542 memset( &dyn
, 0, sizeof(dyn
) );
543 memset( &stat
, 0, sizeof(stat
) );
544 if (static_data
) pid_map
= get_pid_map( &pid_map_size
);
546 /* skip header line */
547 ptr
= fgets( buf
, sizeof(buf
), fp
);
548 while ((ptr
= fgets( buf
, sizeof(buf
), fp
)))
550 if (sscanf( ptr
, "%*x: %x:%hx %x:%hx %x %*s %*s %*s %*s %*s %d",
551 &laddr
, &key
.local
.Ipv4
.sin_port
,
552 &raddr
, &key
.remote
.Ipv4
.sin_port
,
553 &dyn
.state
, &inode
) != 6)
555 dyn
.state
= tcp_state_to_mib_state( dyn
.state
);
556 if (filter
&& filter
!= dyn
.state
) continue;
558 key
.local
.Ipv4
.sin_family
= key
.remote
.Ipv4
.sin_family
= WS_AF_INET
;
559 key
.local
.Ipv4
.sin_addr
.WS_s_addr
= laddr
;
560 key
.local
.Ipv4
.sin_port
= htons( key
.local
.Ipv4
.sin_port
);
561 key
.remote
.Ipv4
.sin_addr
.WS_s_addr
= raddr
;
562 key
.remote
.Ipv4
.sin_port
= htons( key
.remote
.Ipv4
.sin_port
);
566 if (key_data
) *key_data
++ = key
;
567 if (dynamic_data
) *dynamic_data
++ = dyn
;
570 stat
.pid
= find_owning_pid( pid_map
, pid_map_size
, inode
);
571 stat
.create_time
= 0; /* FIXME */
572 stat
.mod_info
= 0; /* FIXME */
573 *static_data
++ = stat
;
580 if ((fp
= fopen( "/proc/net/tcp6", "r" )))
582 memset( &key
, 0, sizeof(key
) );
583 memset( &dyn
, 0, sizeof(dyn
) );
584 memset( &stat
, 0, sizeof(stat
) );
586 addr_scopes
= get_ipv6_addr_scope_table( &addr_scopes_size
);
588 /* skip header line */
589 ptr
= fgets( buf
, sizeof(buf
), fp
);
590 while ((ptr
= fgets( buf
, sizeof(buf
), fp
)))
592 UINT
*local_addr
= (UINT
*)&key
.local
.Ipv6
.sin6_addr
;
593 UINT
*remote_addr
= (UINT
*)&key
.remote
.Ipv6
.sin6_addr
;
595 if (sscanf( ptr
, "%*u: %8x%8x%8x%8x:%hx %8x%8x%8x%8x:%hx %x %*s %*s %*s %*s %*s %*s %*s %d",
596 local_addr
, local_addr
+ 1, local_addr
+ 2, local_addr
+ 3, &key
.local
.Ipv6
.sin6_port
,
597 remote_addr
, remote_addr
+ 1, remote_addr
+ 2, remote_addr
+ 3, &key
.remote
.Ipv6
.sin6_port
,
598 &dyn
.state
, &inode
) != 12)
600 dyn
.state
= tcp_state_to_mib_state( dyn
.state
);
601 if (filter
&& filter
!= dyn
.state
) continue;
602 key
.local
.Ipv6
.sin6_family
= key
.remote
.Ipv6
.sin6_family
= WS_AF_INET6
;
603 key
.local
.Ipv6
.sin6_port
= htons( key
.local
.Ipv6
.sin6_port
);
604 key
.remote
.Ipv6
.sin6_port
= htons( key
.remote
.Ipv6
.sin6_port
);
605 key
.local
.Ipv6
.sin6_scope_id
= find_ipv6_addr_scope( &key
.local
.Ipv6
.sin6_addr
, addr_scopes
,
607 key
.remote
.Ipv6
.sin6_scope_id
= find_ipv6_addr_scope( &key
.remote
.Ipv6
.sin6_addr
, addr_scopes
,
611 if (key_data
) *key_data
++ = key
;
612 if (dynamic_data
) *dynamic_data
++ = dyn
;
615 stat
.pid
= find_owning_pid( pid_map
, pid_map_size
, inode
);
616 stat
.create_time
= 0; /* FIXME */
617 stat
.mod_info
= 0; /* FIXME */
618 *static_data
++ = stat
;
626 #elif defined(HAVE_SYS_SYSCTL_H) && defined(TCPCTL_PCBLIST) && defined(HAVE_STRUCT_XINPGEN)
628 int mib
[] = { CTL_NET
, PF_INET
, IPPROTO_TCP
, TCPCTL_PCBLIST
};
631 struct xinpgen
*xig
, *orig_xig
;
633 if (sysctl( mib
, ARRAY_SIZE(mib
), NULL
, &len
, NULL
, 0 ) < 0)
635 ERR( "Failure to read net.inet.tcp.pcblist via sysctl\n" );
636 status
= STATUS_NOT_SUPPORTED
;
643 status
= STATUS_NO_MEMORY
;
647 if (sysctl( mib
, ARRAY_SIZE(mib
), buf
, &len
, NULL
, 0 ) < 0)
649 ERR( "Failure to read net.inet.tcp.pcblist via sysctl\n" );
650 status
= STATUS_NOT_SUPPORTED
;
654 /* Might be nothing here; first entry is just a header it seems */
655 if (len
<= sizeof(struct xinpgen
)) goto err
;
657 addr_scopes
= get_ipv6_addr_scope_table( &addr_scopes_size
);
658 if (static_data
) pid_map
= get_pid_map( &pid_map_size
);
660 orig_xig
= (struct xinpgen
*)buf
;
663 for (xig
= (struct xinpgen
*)((char *)xig
+ xig
->xig_len
);
664 xig
->xig_len
> sizeof(struct xinpgen
);
665 xig
= (struct xinpgen
*)((char *)xig
+ xig
->xig_len
))
667 #if __FreeBSD_version >= 1200026
668 struct xtcpcb
*tcp
= (struct xtcpcb
*)xig
;
669 struct xinpcb
*in
= &tcp
->xt_inp
;
670 struct xsocket
*sock
= &in
->xi_socket
;
672 struct tcpcb
*tcp
= &((struct xtcpcb
*)xig
)->xt_tp
;
673 struct inpcb
*in
= &((struct xtcpcb
*)xig
)->xt_inp
;
674 struct xsocket
*sock
= &((struct xtcpcb
*)xig
)->xt_socket
;
676 static const struct in6_addr zero
;
678 /* Ignore sockets for other protocols */
679 if (sock
->xso_protocol
!= IPPROTO_TCP
) continue;
681 /* Ignore PCBs that were freed while generating the data */
682 if (in
->inp_gencnt
> orig_xig
->xig_gen
) continue;
684 /* we're only interested in IPv4 and IPV6 addresses */
685 if (!(in
->inp_vflag
& (INP_IPV4
| INP_IPV6
))) continue;
687 /* If all 0's, skip it */
688 if (in
->inp_vflag
& INP_IPV4
&& !in
->inp_laddr
.s_addr
&& !in
->inp_lport
&&
689 !in
->inp_faddr
.s_addr
&& !in
->inp_fport
) continue;
690 if (in
->inp_vflag
& INP_IPV6
&& !memcmp( &in
->in6p_laddr
, &zero
, sizeof(zero
) ) && !in
->inp_lport
&&
691 !memcmp( &in
->in6p_faddr
, &zero
, sizeof(zero
) ) && !in
->inp_fport
) continue;
693 dyn
.state
= tcp_state_to_mib_state( tcp
->t_state
);
694 if (filter
&& filter
!= dyn
.state
) continue;
696 if (in
->inp_vflag
& INP_IPV4
)
698 key
.local
.Ipv4
.sin_family
= key
.remote
.Ipv4
.sin_family
= WS_AF_INET
;
699 key
.local
.Ipv4
.sin_addr
.WS_s_addr
= in
->inp_laddr
.s_addr
;
700 key
.local
.Ipv4
.sin_port
= in
->inp_lport
;
701 key
.remote
.Ipv4
.sin_addr
.WS_s_addr
= in
->inp_faddr
.s_addr
;
702 key
.remote
.Ipv4
.sin_port
= in
->inp_fport
;
706 key
.local
.Ipv6
.sin6_family
= key
.remote
.Ipv6
.sin6_family
= WS_AF_INET6
;
707 memcpy( &key
.local
.Ipv6
.sin6_addr
, &in
->in6p_laddr
, sizeof(in
->in6p_laddr
) );
708 key
.local
.Ipv6
.sin6_port
= in
->inp_lport
;
709 key
.local
.Ipv6
.sin6_scope_id
= find_ipv6_addr_scope( &key
.local
.Ipv6
.sin6_addr
, addr_scopes
,
711 memcpy( &key
.remote
.Ipv6
.sin6_addr
, &in
->in6p_faddr
, sizeof(in
->in6p_faddr
) );
712 key
.remote
.Ipv6
.sin6_port
= in
->inp_fport
;
713 key
.remote
.Ipv6
.sin6_scope_id
= find_ipv6_addr_scope( &key
.remote
.Ipv6
.sin6_addr
, addr_scopes
,
719 if (key_data
) *key_data
++ = key
;
720 if (dynamic_data
) *dynamic_data
++ = dyn
;
723 stat
.pid
= find_owning_pid( pid_map
, pid_map_size
, (UINT_PTR
)sock
->so_pcb
);
724 stat
.create_time
= 0; /* FIXME */
725 stat
.mod_info
= 0; /* FIXME */
726 *static_data
++ = stat
;
735 FIXME( "not implemented\n" );
736 status
= STATUS_NOT_IMPLEMENTED
;
739 if (!want_data
|| num
<= *count
) *count
= num
;
740 else status
= STATUS_BUFFER_OVERFLOW
;
747 static NTSTATUS
tcp_all_enumerate_all( void *key_data
, UINT key_size
, void *rw_data
, UINT rw_size
,
748 void *dynamic_data
, UINT dynamic_size
,
749 void *static_data
, UINT static_size
, UINT_PTR
*count
)
751 TRACE( "%p %d %p %d %p %d %p %d %p\n", key_data
, key_size
, rw_data
, rw_size
,
752 dynamic_data
, dynamic_size
, static_data
, static_size
, count
);
754 return tcp_conns_enumerate_all( 0, key_data
, key_size
, rw_data
, rw_size
,
755 dynamic_data
, dynamic_size
, static_data
, static_size
, count
);
758 static NTSTATUS
tcp_estab_enumerate_all( void *key_data
, UINT key_size
, void *rw_data
, UINT rw_size
,
759 void *dynamic_data
, UINT dynamic_size
,
760 void *static_data
, UINT static_size
, UINT_PTR
*count
)
762 TRACE( "%p %d %p %d %p %d %p %d %p\n", key_data
, key_size
, rw_data
, rw_size
,
763 dynamic_data
, dynamic_size
, static_data
, static_size
, count
);
765 return tcp_conns_enumerate_all( MIB_TCP_STATE_ESTAB
, key_data
, key_size
, rw_data
, rw_size
,
766 dynamic_data
, dynamic_size
, static_data
, static_size
, count
);
769 static NTSTATUS
tcp_listen_enumerate_all( void *key_data
, UINT key_size
, void *rw_data
, UINT rw_size
,
770 void *dynamic_data
, UINT dynamic_size
,
771 void *static_data
, UINT static_size
, UINT_PTR
*count
)
773 TRACE( "%p %d %p %d %p %d %p %d %p\n", key_data
, key_size
, rw_data
, rw_size
,
774 dynamic_data
, dynamic_size
, static_data
, static_size
, count
);
776 return tcp_conns_enumerate_all( MIB_TCP_STATE_LISTEN
, key_data
, key_size
, rw_data
, rw_size
,
777 dynamic_data
, dynamic_size
, static_data
, static_size
, count
);
780 static struct module_table tcp_tables
[] =
786 sizeof(struct nsi_tcp_stats_dynamic
), sizeof(struct nsi_tcp_stats_static
)
789 tcp_stats_get_all_parameters
,
794 sizeof(struct nsi_tcp_conn_key
), 0,
795 sizeof(struct nsi_tcp_conn_dynamic
), sizeof(struct nsi_tcp_conn_static
)
797 tcp_all_enumerate_all
,
802 sizeof(struct nsi_tcp_conn_key
), 0,
803 sizeof(struct nsi_tcp_conn_dynamic
), sizeof(struct nsi_tcp_conn_static
)
805 tcp_estab_enumerate_all
,
808 NSI_TCP_LISTEN_TABLE
,
810 sizeof(struct nsi_tcp_conn_key
), 0,
811 sizeof(struct nsi_tcp_conn_dynamic
), sizeof(struct nsi_tcp_conn_static
)
813 tcp_listen_enumerate_all
,
820 const struct module tcp_module
=
822 &NPI_MS_TCP_MODULEID
,