From 38fa5ad1bce7b3a1fd303c956fbc19c209ffd458 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Tue, 13 May 2003 03:32:20 +0000 Subject: [PATCH] Added an implementation of iphlpapi.dll; most Get* functions introduced through Win98 are included. --- configure | 70 +-- configure.ac | 10 +- dlls/Makefile.in | 14 + dlls/iphlpapi/.cvsignore | 3 + dlls/iphlpapi/Makefile.in | 18 + dlls/iphlpapi/ifenum.c | 912 +++++++++++++++++++++++++++ dlls/iphlpapi/ifenum.h | 130 ++++ dlls/iphlpapi/iphlpapi.spec | 117 ++++ dlls/iphlpapi/iphlpapi_main.c | 1397 +++++++++++++++++++++++++++++++++++++++++ dlls/iphlpapi/ipstats.c | 829 ++++++++++++++++++++++++ dlls/iphlpapi/ipstats.h | 102 +++ include/Makefile.in | 4 + include/config.h.in | 15 + include/ipexport.h | 17 + include/iphlpapi.h | 138 ++++ include/ipifcons.h | 40 ++ include/iprtrmib.h | 276 ++++++++ include/iptypes.h | 87 +++ 18 files changed, 4113 insertions(+), 66 deletions(-) create mode 100644 dlls/iphlpapi/.cvsignore create mode 100644 dlls/iphlpapi/Makefile.in create mode 100644 dlls/iphlpapi/ifenum.c create mode 100644 dlls/iphlpapi/ifenum.h create mode 100644 dlls/iphlpapi/iphlpapi.spec create mode 100644 dlls/iphlpapi/iphlpapi_main.c create mode 100644 dlls/iphlpapi/ipstats.c create mode 100644 dlls/iphlpapi/ipstats.h create mode 100644 include/iphlpapi.h create mode 100644 include/ipifcons.h create mode 100644 include/iprtrmib.h create mode 100644 include/iptypes.h diff --git a/configure b/configure index a6c3dc385a7..79d43b57e8b 100755 --- a/configure +++ b/configure @@ -2247,12 +2247,12 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (exit $ac_status); }; }; then for ac_declaration in \ ''\ - '#include ' \ 'extern "C" void std::exit (int) throw (); using std::exit;' \ 'extern "C" void std::exit (int); using std::exit;' \ 'extern "C" void exit (int) throw ();' \ 'extern "C" void exit (int);' \ - 'void exit (int);' + 'void exit (int);' \ + '#include ' do cat >conftest.$ac_ext <<_ACEOF #line $LINENO "configure" @@ -13237,6 +13237,7 @@ done + for ac_header in \ arpa/inet.h \ arpa/nameser.h \ @@ -13263,6 +13264,7 @@ for ac_header in \ netinet/in.h \ netinet/in_systm.h \ netinet/tcp.h \ + netinet/tcp_fsm.h \ pty.h \ pwd.h \ regex.h \ @@ -13569,63 +13571,12 @@ done -for ac_header in net/if.h -do -as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 -if eval "test \"\${$as_ac_Header+set}\" = set"; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - cat >conftest.$ac_ext <<_ACEOF -#line $LINENO "configure" -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include - #if HAVE_SYS_SOCKET_H - # include - #endif -#include <$ac_header> -_ACEOF -rm -f conftest.$ac_objext -if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 - (eval $ac_compile) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } && - { ac_try='test -s conftest.$ac_objext' - { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 - (eval $ac_try) 2>&5 - ac_status=$? - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); }; }; then - eval "$as_ac_Header=yes" -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 -eval "$as_ac_Header=no" -fi -rm -f conftest.$ac_objext conftest.$ac_ext -fi -echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 -echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 -if test `eval echo '${'$as_ac_Header'}'` = yes; then - cat >>confdefs.h <<_ACEOF -#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF -fi -done - - -for ac_header in netinet/ip.h +for ac_header in net/if.h net/if_arp.h net/if_dl.h net/if_types.h net/route.h resolv.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -13644,9 +13595,6 @@ cat >>conftest.$ac_ext <<_ACEOF #if HAVE_SYS_SOCKET_H # include #endif - #if HAVE_NETINET_IN_SYSTM_H - # include - #endif #include <$ac_header> _ACEOF @@ -13684,7 +13632,7 @@ done -for ac_header in resolv.h +for ac_header in netinet/ip.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_header" >&5 @@ -13703,6 +13651,9 @@ cat >>conftest.$ac_ext <<_ACEOF #if HAVE_SYS_SOCKET_H # include #endif + #if HAVE_NETINET_IN_SYSTM_H + # include + #endif #include <$ac_header> _ACEOF @@ -16083,7 +16034,7 @@ MAKE_LIB_RULES=libs/Makelib.rules MAKE_PROG_RULES=programs/Makeprog.rules - ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3dim/Makefile dlls/d3dx8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrtd/Makefile dlls/msvideo/Makefile dlls/msvideo/msrle32/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/version/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winenas/Makefile dlls/winmm/winejack/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/uuid/Makefile libs/wine/Makefile libs/wpp/Makefile miscemu/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/osversioncheck/Makefile programs/progman/Makefile programs/regapi/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/regtest/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/wmc/Makefile tools/wrc/Makefile" + ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3dim/Makefile dlls/d3dx8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrtd/Makefile dlls/msvideo/Makefile dlls/msvideo/msrle32/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/version/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winenas/Makefile dlls/winmm/winejack/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/uuid/Makefile libs/wine/Makefile libs/wpp/Makefile miscemu/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/osversioncheck/Makefile programs/progman/Makefile programs/regapi/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/regtest/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/wmc/Makefile tools/wrc/Makefile" cat >confcache <<\_ACEOF @@ -16659,6 +16610,7 @@ do "dlls/icmp/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/icmp/Makefile" ;; "dlls/imagehlp/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/imagehlp/Makefile" ;; "dlls/imm32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/imm32/Makefile" ;; + "dlls/iphlpapi/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/iphlpapi/Makefile" ;; "dlls/kernel/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/kernel/Makefile" ;; "dlls/kernel/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/kernel/tests/Makefile" ;; "dlls/lzexpand/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/lzexpand/Makefile" ;; diff --git a/configure.ac b/configure.ac index 6d47f78718c..3e414c34f53 100644 --- a/configure.ac +++ b/configure.ac @@ -982,6 +982,7 @@ AC_CHECK_HEADERS(\ netinet/in.h \ netinet/in_systm.h \ netinet/tcp.h \ + netinet/tcp_fsm.h \ pty.h \ pwd.h \ regex.h \ @@ -1039,7 +1040,7 @@ AC_CHECK_HEADERS(sys/mount.h sys/user.h,,, # include #endif]) -AC_CHECK_HEADERS(net/if.h,,, +AC_CHECK_HEADERS([net/if.h net/if_arp.h net/if_dl.h net/if_types.h net/route.h resolv.h],,, [#include #if HAVE_SYS_SOCKET_H # include @@ -1054,12 +1055,6 @@ AC_CHECK_HEADERS(netinet/ip.h,,, # include #endif]) -AC_CHECK_HEADERS(resolv.h,,, - [#include - #if HAVE_SYS_SOCKET_H - # include - #endif]) - AC_CHECK_HEADERS(ucontext.h,,,[#include ]) dnl **** Check for IPX headers (currently Linux only) **** @@ -1402,6 +1397,7 @@ dlls/glu32/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile +dlls/iphlpapi/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile diff --git a/dlls/Makefile.in b/dlls/Makefile.in index 6ae5d7477a4..2198f72e403 100644 --- a/dlls/Makefile.in +++ b/dlls/Makefile.in @@ -47,6 +47,7 @@ BASEDIRS = \ icmp \ imagehlp \ imm32 \ + iphlpapi \ kernel \ lzexpand \ mapi32 \ @@ -226,6 +227,7 @@ all: \ imaadp32.acm$(DLLEXT) \ imagehlp.dll$(DLLEXT) \ imm32.dll$(DLLEXT) \ + iphlpapi.dll$(DLLEXT) \ joystick.drv$(DLLEXT) \ kernel32.dll$(DLLEXT) \ lz32.dll$(DLLEXT) \ @@ -415,6 +417,9 @@ imagehlp.dll$(DLLEXT): imagehlp/imagehlp.dll$(DLLEXT) imm32.dll$(DLLEXT) imm.dll$(DLLEXT): imm32/imm32.dll$(DLLEXT) $(RM) $@ && $(LN_S) imm32/imm32.dll$(DLLEXT) $@ +iphlpapi.dll$(DLLEXT): iphlpapi/iphlpapi.dll$(DLLEXT) + $(RM) $@ && $(LN_S) iphlpapi/iphlpapi.dll$(DLLEXT) $@ + joystick.drv$(DLLEXT): winmm/joystick/joystick.drv$(DLLEXT) $(RM) $@ && $(LN_S) winmm/joystick/joystick.drv$(DLLEXT) $@ @@ -688,6 +693,7 @@ IMPORT_LIBS = \ libicmp \ libimagehlp \ libimm32 \ + libiphlpapi \ libkernel32 \ liblz32 \ libmapi32 \ @@ -927,6 +933,11 @@ libimm32.def: imm32/imm32.spec.def libimm32.a: imm32/imm32.spec.def $(DLLTOOL) -k -l $@ -d imm32/imm32.spec.def +libiphlpapi.def: iphlpapi/iphlpapi.spec.def + $(RM) $@ && $(LN_S) iphlpapi/iphlpapi.spec.def $@ +libiphlpapi.a: iphlpapi/iphlpapi.spec.def + $(DLLTOOL) -k -l $@ -d iphlpapi/iphlpapi.spec.def + libkernel32.def: kernel/kernel32.spec.def $(RM) $@ && $(LN_S) kernel/kernel32.spec.def $@ libkernel32.a: kernel/kernel32.spec.def @@ -1253,6 +1264,7 @@ glu32/glu32.spec.def: $(WINEBUILD) icmp/icmp.spec.def: $(WINEBUILD) imagehlp/imagehlp.spec.def: $(WINEBUILD) imm32/imm32.spec.def: $(WINEBUILD) +iphlpapi/iphlpapi.spec.def: $(WINEBUILD) kernel/kernel32.spec.def: $(WINEBUILD) lzexpand/lz32.spec.def: $(WINEBUILD) mapi32/mapi32.spec.def: $(WINEBUILD) @@ -1354,6 +1366,7 @@ icmp/icmp.dll$(DLLEXT): icmp msacm/imaadp32/imaadp32.acm$(DLLEXT): msacm/imaadp32 imagehlp/imagehlp.dll$(DLLEXT): imagehlp imm32/imm32.dll$(DLLEXT): imm32 +iphlpapi/iphlpapi.dll$(DLLEXT): iphlpapi winmm/joystick/joystick.drv$(DLLEXT): winmm/joystick kernel/kernel32.dll$(DLLEXT): kernel lzexpand/lz32.dll$(DLLEXT): lzexpand @@ -1470,6 +1483,7 @@ icmp/__install__: icmp.dll$(DLLEXT) msacm/imaadp32/__install__: imaadp32.acm$(DLLEXT) imagehlp/__install__: imagehlp.dll$(DLLEXT) imm32/__install__: imm32.dll$(DLLEXT) +iphlpapi/__install__: iphlpapi.dll$(DLLEXT) winmm/joystick/__install__: joystick.drv$(DLLEXT) kernel/__install__: kernel32.dll$(DLLEXT) lzexpand/__install__: lz32.dll$(DLLEXT) diff --git a/dlls/iphlpapi/.cvsignore b/dlls/iphlpapi/.cvsignore new file mode 100644 index 00000000000..9a24656d9a5 --- /dev/null +++ b/dlls/iphlpapi/.cvsignore @@ -0,0 +1,3 @@ +Makefile +iphlpapi.dll.dbg.c +iphlpapi.spec.c diff --git a/dlls/iphlpapi/Makefile.in b/dlls/iphlpapi/Makefile.in new file mode 100644 index 00000000000..76d5bb460d8 --- /dev/null +++ b/dlls/iphlpapi/Makefile.in @@ -0,0 +1,18 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = iphlpapi.dll +IMPORTS = kernel32 + +LDDLLFLAGS = @LDDLLFLAGS@ +SYMBOLFILE = $(MODULE).tmp.o + +C_SRCS = \ + ifenum.c \ + iphlpapi_main.c \ + ipstats.c + +@MAKE_DLL_RULES@ + +### Dependencies: diff --git a/dlls/iphlpapi/ifenum.c b/dlls/iphlpapi/ifenum.c new file mode 100644 index 00000000000..6b2de75b186 --- /dev/null +++ b/dlls/iphlpapi/ifenum.c @@ -0,0 +1,912 @@ +/* Copyright (C) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Implementation notes + * Interface index fun: + * - Windows may rely on an index being cleared in the topmost 8 bits in some + * APIs; see GetFriendlyIfIndex and the mention of "backward compatible" + * indexes. It isn't clear which APIs might fail with non-backward-compatible + * indexes, but I'll keep them bits clear just in case. + * - Even though if_nametoindex and if_indextoname seem to be pretty portable, + * Linux, at any rate, uses the same interface index for all virtual + * interfaces of a real interface as well as for the real interface itself. + * If I used the Linux index as my index, this would break my statement that + * an index is a key, and that an interface has 0 or 1 IP addresses. + * If that behavior were consistent across UNIXen (I don't know), it could + * help me implement multiple IP addresses more in the Windows way. + * But here's a problem with doing so: + * - Netbios() has a concept of an LAN adapter number (LANA), which is an 8-bit + * number in the range 0-254, inclusive. The MSDN pages for Netbios() says + * the original Netbios() spec allowed only 0 or 1 to be used, though "new" + * applications should enumerate available adapters rather than assuming 0 + * is the default adapter. + * I'm concerned that some old application might depend on being able to get + * "the" MAC address of a machine by opening LANA 0 and getting its MAC + * address. This also implies LANA 0 should correspond to a non-loopback + * interface. + * On Linux, the if_nametoindex index is 1-based, and "lo" typically has + * index 1. + * I could make netapi32 do its own LANA map, independent of my index + * assignment, but it seems simpler just to assign 0-based indexes and put + * non-loopback adapters first, so the first 255 indexes (!) on a system will + * automatically map to LANA numbers without difficulty. + * - One more argument for doing it this way, if you don't buy the Netbios() + * argument: WsControl() (in wsock32) uses the same index to refer to an IP + * address and an interface. If I assigned multiple IP addresses to an + * interface, wsock32 would have to maintain a table of IP addresses with its + * own indexing scheme. No thanks. + * + * There are three implemened methods for determining the MAC address of an + * interface: + * - a specific IOCTL (Linux) + * - looking in the ARP cache (at least Solaris) + * - using the sysctl interface (FreeBSD and MacOSX) + * Solaris and some others have SIOCGENADDR, but I haven't gotten that to work + * on the Solaris boxes at SourceForge's compile farm, whereas SIOCGARP does. + */ + +#include "config.h" + +#include +#include +#include + +#if HAVE_UNISTD_H +#include +#endif + +#include + +#if HAVE_SYS_SOCKET_H +#include +#endif + +#if HAVE_NETINET_IN_H +#include +#endif + +#if HAVE_ARPA_INET_H +#include +#endif + +#if HAVE_NET_IF_H +#include +#endif + +#if HAVE_NET_IF_ARP_H +#include +#endif + +#if HAVE_NET_ROUTE_H +#include +#endif + +#if HAVE_SYS_IOCTL_H +#include +#endif + +#if HAVE_SYS_SYSCTL_H +#include +#endif + +#if HAVE_SYS_SOCKIO_H +#include +#endif + +#if HAVE_NET_IF_DL_H +#include +#endif + +#if HAVE_NET_IF_TYPES_H +#include +#endif + +#include "winbase.h" +#include "iprtrmib.h" +#include "ifenum.h" + +#if HAVE_STRUCT_SOCKADDR_SA_LEN +#define ifreq_len(ifr) \ + max(sizeof(struct ifreq), sizeof((ifr)->ifr_name)+(ifr)->ifr_addr.sa_len) +#else +#define ifreq_len(ifr) sizeof(struct ifreq) +#endif + +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE (~0U) +#endif + +#define INITIAL_INTERFACES_ASSUMED 4 + +#define INDEX_IS_LOOPBACK 0x00800000 + +/* Type declarations */ + +typedef struct _InterfaceNameMapEntry { + char name[IFNAMSIZ]; + BOOL inUse; + BOOL usedLastPass; +} InterfaceNameMapEntry; + +typedef struct _InterfaceNameMap { + DWORD numInterfaces; + DWORD nextAvailable; + DWORD numAllocated; + InterfaceNameMapEntry table[1]; +} InterfaceNameMap; + +/* Global variables */ + +static InterfaceNameMap *gNonLoopbackInterfaceMap = NULL; +static InterfaceNameMap *gLoopbackInterfaceMap = NULL; + +/* Functions */ + +/* Sizes the passed-in map to have enough space for numInterfaces interfaces. + * If map is NULL, allocates a new map. If it is not, may reallocate the + * existing map and return a map of increased size. Returns the allocated map, + * or NULL if it could not allocate a map of the requested size. + */ +InterfaceNameMap *sizeMap(InterfaceNameMap *map, DWORD numInterfaces) +{ + if (!map) { + numInterfaces = max(numInterfaces, INITIAL_INTERFACES_ASSUMED); + map = (InterfaceNameMap *)calloc(1, sizeof(InterfaceNameMap) + + (numInterfaces - 1) * sizeof(InterfaceNameMapEntry)); + if (map) + map->numAllocated = numInterfaces; + } + else { + if (map->numAllocated < numInterfaces) { + map = (InterfaceNameMap *)realloc(map, sizeof(InterfaceNameMap) + + (numInterfaces - 1) * sizeof(InterfaceNameMapEntry)); + if (map) + memset(&map->table[map->numAllocated], 0, + (numInterfaces - map->numAllocated) * sizeof(InterfaceNameMapEntry)); + } + } + return map; +} + +static int isLoopbackInterface(int fd, const char *name) +{ + int ret = 0; + + if (name) { + struct ifreq ifr; + + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ] = '\0'; + if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) + ret = ifr.ifr_flags & IFF_LOOPBACK; + } + return ret; +} + +static void countInterfaces(int fd, caddr_t buf, size_t len) +{ + caddr_t ifPtr = buf; + DWORD numNonLoopbackInterfaces = 0, numLoopbackInterfaces = 0; + + while (ifPtr && ifPtr < buf + len) { + struct ifreq *ifr = (struct ifreq *)ifPtr; + + if (isLoopbackInterface(fd, ifr->ifr_name)) + numLoopbackInterfaces++; + else + numNonLoopbackInterfaces++; + ifPtr += ifreq_len(ifr); + } + gNonLoopbackInterfaceMap = sizeMap(gNonLoopbackInterfaceMap, + numNonLoopbackInterfaces); + gLoopbackInterfaceMap = sizeMap(gLoopbackInterfaceMap, + numLoopbackInterfaces); +} + +/* Stores the name in the given map, and increments the map's numInterfaces + * member if stored successfully. Will store in the same slot as previously if + * usedLastPass is set, otherwise will store in a new slot. + * Assumes map and name are not NULL, and the usedLastPass flag is set + * correctly for each entry in the map, and that map->numInterfaces < + * map->numAllocated. + * FIXME: this is kind of expensive, doing a linear scan of the map with a + * string comparison of each entry to find the old slot. + */ +static void storeInterfaceInMap(InterfaceNameMap *map, const char *name) +{ + if (map && name) { + DWORD ndx; + BOOL stored = FALSE; + + /* look for previous slot, mark in use if so */ + for (ndx = 0; !stored && ndx < map->nextAvailable; ndx++) { + if (map->table[ndx].usedLastPass && !strncmp(map->table[ndx].name, name, + sizeof(map->table[ndx].name))) { + map->table[ndx].inUse = TRUE; + stored = TRUE; + } + } + /* look for new slot */ + for (ndx = 0; !stored && ndx < map->numAllocated; ndx++) { + if (!map->table[ndx].inUse) { + strncpy(map->table[ndx].name, name, IFNAMSIZ); + map->table[ndx].name[IFNAMSIZ] = '\0'; + map->table[ndx].inUse = TRUE; + stored = TRUE; + if (ndx >= map->nextAvailable) + map->nextAvailable = ndx + 1; + } + } + if (stored) + map->numInterfaces++; + } +} + +/* Sets all used entries' usedLastPass flag to their inUse flag, clears + * their inUse flag, and clears their numInterfaces member. + */ +static void markOldInterfaces(InterfaceNameMap *map) +{ + if (map) { + DWORD ndx; + + map->numInterfaces = 0; + for (ndx = 0; ndx < map->nextAvailable; ndx++) { + map->table[ndx].usedLastPass = map->table[ndx].inUse; + map->table[ndx].inUse = FALSE; + } + } +} + +static void classifyInterfaces(int fd, caddr_t buf, size_t len) +{ + caddr_t ifPtr = buf; + + markOldInterfaces(gNonLoopbackInterfaceMap); + markOldInterfaces(gLoopbackInterfaceMap); + while (ifPtr && ifPtr < buf + len) { + struct ifreq *ifr = (struct ifreq *)ifPtr; + + if (isLoopbackInterface(fd, ifr->ifr_name)) + storeInterfaceInMap(gLoopbackInterfaceMap, ifr->ifr_name); + else + storeInterfaceInMap(gNonLoopbackInterfaceMap, ifr->ifr_name); + ifPtr += ifreq_len(ifr); + } +} + +static void enumerateInterfaces(void) +{ + int fd; + + fd = socket(PF_INET, SOCK_DGRAM, 0); + if (fd != -1) { + int ret, guessedNumInterfaces; + struct ifconf ifc; + + /* try to avoid silly heap action by starting with the right size buffer */ + guessedNumInterfaces = 0; + if (gNonLoopbackInterfaceMap) + guessedNumInterfaces += gNonLoopbackInterfaceMap->numInterfaces; + if (gLoopbackInterfaceMap) + guessedNumInterfaces += gLoopbackInterfaceMap->numInterfaces; + + ret = 0; + memset(&ifc, 0, sizeof(ifc)); + /* there is no way to know the interface count beforehand, + so we need to loop again and again upping our max each time + until returned < max */ + do { + if (guessedNumInterfaces == 0) + guessedNumInterfaces = INITIAL_INTERFACES_ASSUMED; + else + guessedNumInterfaces *= 2; + if (ifc.ifc_buf) + free(ifc.ifc_buf); + ifc.ifc_len = sizeof(struct ifreq) * guessedNumInterfaces; + ifc.ifc_buf = (char *)malloc(ifc.ifc_len); + ret = ioctl(fd, SIOCGIFCONF, &ifc); + } while (ret == 0 && + ifc.ifc_len == (sizeof(struct ifreq) * guessedNumInterfaces)); + + if (ret == 0) { + countInterfaces(fd, ifc.ifc_buf, ifc.ifc_len); + classifyInterfaces(fd, ifc.ifc_buf, ifc.ifc_len); + } + + if (ifc.ifc_buf) + free(ifc.ifc_buf); + close(fd); + } +} + +DWORD getNumNonLoopbackInterfaces(void) +{ + enumerateInterfaces(); + return gNonLoopbackInterfaceMap ? gNonLoopbackInterfaceMap->numInterfaces : 0; +} + +DWORD getNumInterfaces(void) +{ + DWORD ret = getNumNonLoopbackInterfaces(); + + ret += gLoopbackInterfaceMap ? gLoopbackInterfaceMap->numInterfaces : 0; + return ret; +} + +const char *getInterfaceNameByIndex(DWORD index) +{ + DWORD realIndex; + InterfaceNameMap *map; + const char *ret = NULL; + + if (index & INDEX_IS_LOOPBACK) { + realIndex = index ^ INDEX_IS_LOOPBACK; + map = gLoopbackInterfaceMap; + } + else { + realIndex = index; + map = gNonLoopbackInterfaceMap; + } + if (map && realIndex < map->nextAvailable) + ret = map->table[realIndex].name; + return ret; +} + +DWORD getInterfaceIndexByName(const char *name, PDWORD index) +{ + DWORD ndx; + BOOL found = FALSE; + + if (!name) + return ERROR_INVALID_PARAMETER; + if (!index) + return ERROR_INVALID_PARAMETER; + + for (ndx = 0; !found && gNonLoopbackInterfaceMap && + ndx < gNonLoopbackInterfaceMap->nextAvailable; ndx++) + if (!strncmp(gNonLoopbackInterfaceMap->table[ndx].name, name, IFNAMSIZ)) { + found = TRUE; + *index = ndx; + } + for (ndx = 0; !found && gLoopbackInterfaceMap && + ndx < gLoopbackInterfaceMap->nextAvailable; ndx++) + if (!strncmp(gLoopbackInterfaceMap->table[ndx].name, name, IFNAMSIZ)) { + found = TRUE; + *index = ndx | INDEX_IS_LOOPBACK; + } + if (found) + return NO_ERROR; + else + return ERROR_INVALID_DATA; +} + +static void addMapEntriesToIndexTable(InterfaceIndexTable *table, + const InterfaceNameMap *map) +{ + if (table && map) { + DWORD ndx; + + for (ndx = 0; ndx < map->nextAvailable && + table->numIndexes < table->numAllocated; ndx++) + if (map->table[ndx].inUse) { + DWORD externalNdx = ndx; + + if (map == gLoopbackInterfaceMap) + externalNdx |= INDEX_IS_LOOPBACK; + table->indexes[table->numIndexes++] = externalNdx; + } + } +} + +InterfaceIndexTable *getInterfaceIndexTable(void) +{ + DWORD numInterfaces = getNumInterfaces(); + InterfaceIndexTable *ret = (InterfaceIndexTable *)calloc(1, + sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD)); + + if (ret) { + ret->numAllocated = numInterfaces; + addMapEntriesToIndexTable(ret, gNonLoopbackInterfaceMap); + addMapEntriesToIndexTable(ret, gLoopbackInterfaceMap); + } + return ret; +} + +InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void) +{ + DWORD numInterfaces = getNumNonLoopbackInterfaces(); + InterfaceIndexTable *ret = (InterfaceIndexTable *)calloc(1, + sizeof(InterfaceIndexTable) + (numInterfaces - 1) * sizeof(DWORD)); + + if (ret) { + ret->numAllocated = numInterfaces; + addMapEntriesToIndexTable(ret, gNonLoopbackInterfaceMap); + } + return ret; +} + +DWORD getInterfaceIPAddrByName(const char *name) +{ + DWORD ret = INADDR_ANY; + + if (name) { + int fd = socket(PF_INET, SOCK_DGRAM, 0); + + if (fd != -1) { + struct ifreq ifr; + + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ] = '\0'; + if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) + memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD)); + close(fd); + } + } + return ret; +} + +DWORD getInterfaceIPAddrByIndex(DWORD index) +{ + DWORD ret; + const char *name = getInterfaceNameByIndex(index); + + if (name) + ret = getInterfaceIPAddrByName(name); + else + ret = INADDR_ANY; + return ret; +} + +DWORD getInterfaceBCastAddrByName(const char *name) +{ + DWORD ret = INADDR_ANY; + + if (name) { + int fd = socket(PF_INET, SOCK_DGRAM, 0); + + if (fd != -1) { + struct ifreq ifr; + + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ] = '\0'; + if (ioctl(fd, SIOCGIFBRDADDR, &ifr) == 0) + memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD)); + close(fd); + } + } + return ret; +} + +DWORD getInterfaceBCastAddrByIndex(DWORD index) +{ + DWORD ret; + const char *name = getInterfaceNameByIndex(index); + + if (name) + ret = getInterfaceBCastAddrByName(name); + else + ret = INADDR_ANY; + return ret; +} + +DWORD getInterfaceMaskByName(const char *name) +{ + DWORD ret = INADDR_NONE; + + if (name) { + int fd = socket(PF_INET, SOCK_DGRAM, 0); + + if (fd != -1) { + struct ifreq ifr; + + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ] = '\0'; + if (ioctl(fd, SIOCGIFNETMASK, &ifr) == 0) + memcpy(&ret, ifr.ifr_addr.sa_data + 2, sizeof(DWORD)); + close(fd); + } + } + return ret; +} + +DWORD getInterfaceMaskByIndex(DWORD index) +{ + DWORD ret; + const char *name = getInterfaceNameByIndex(index); + + if (name) + ret = getInterfaceMaskByName(name); + else + ret = INADDR_NONE; + return ret; +} + +#if defined (SIOCGIFHWADDR) +DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr, + PDWORD type) +{ + DWORD ret; + int fd; + + if (!name || !len || !addr || !type) + return ERROR_INVALID_PARAMETER; + + fd = socket(PF_INET, SOCK_DGRAM, 0); + if (fd != -1) { + struct ifreq ifr; + + memset(&ifr, 0, sizeof(struct ifreq)); + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ] = '\0'; + if ((ioctl(fd, SIOCGIFHWADDR, &ifr))) + ret = ERROR_INVALID_DATA; + else { + int addrLen; + + switch (ifr.ifr_hwaddr.sa_family) + { + case ARPHRD_LOOPBACK: + addrLen = 0; + *type = MIB_IF_TYPE_LOOPBACK; + break; + case ARPHRD_ETHER: + addrLen = ETH_ALEN; + *type = MIB_IF_TYPE_ETHERNET; + break; + case ARPHRD_FDDI: + addrLen = ETH_ALEN; + *type = MIB_IF_TYPE_FDDI; + break; + case ARPHRD_IEEE802: /* 802.2 Ethernet && Token Ring, guess TR? */ + addrLen = ETH_ALEN; + *type = MIB_IF_TYPE_TOKENRING; + break; + case ARPHRD_IEEE802_TR: /* also Token Ring? */ + addrLen = ETH_ALEN; + *type = MIB_IF_TYPE_TOKENRING; + break; + case ARPHRD_SLIP: + addrLen = 0; + *type = MIB_IF_TYPE_SLIP; + break; + case ARPHRD_PPP: + addrLen = 0; + *type = MIB_IF_TYPE_PPP; + break; + default: + addrLen = min(MAX_INTERFACE_PHYSADDR, sizeof(ifr.ifr_hwaddr.sa_data)); + *type = MIB_IF_TYPE_OTHER; + } + if (addrLen > *len) { + ret = ERROR_INSUFFICIENT_BUFFER; + *len = addrLen; + } + else { + if (addrLen > 0) + memcpy(addr, ifr.ifr_hwaddr.sa_data, addrLen); + /* zero out remaining bytes for broken implementations */ + memset(addr + addrLen, 0, *len - addrLen); + *len = addrLen; + ret = NO_ERROR; + } + } + close(fd); + } + else + ret = ERROR_NO_MORE_FILES; + return ret; +} +#elif defined (SIOCGARP) +DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr, + PDWORD type) +{ + DWORD ret; + int fd; + + if (!name || !len || !addr || !type) + return ERROR_INVALID_PARAMETER; + + fd = socket(PF_INET, SOCK_DGRAM, 0); + if (fd != -1) { + if (isLoopbackInterface(fd, name)) { + *type = MIB_IF_TYPE_LOOPBACK; + memset(addr, 0, *len); + *len = 0; + } + else { + struct arpreq arp; + struct sockaddr_in *saddr; + + memset(&arp, 0, sizeof(struct arpreq)); + arp.arp_pa.sa_family = AF_INET; + saddr = (struct sockaddr_in *)&arp; /* proto addr is first member */ + saddr->sin_family = AF_INET; + saddr->sin_addr.s_addr = getInterfaceAddrByName(name); + if ((ioctl(fd, SIOCGARP, &arp))) + ret = ERROR_INVALID_DATA; + else { + /* FIXME: heh: who said it was ethernet? */ + int addrLen = ETH_ALEN; + + if (addrLen > *len) { + ret = ERROR_INSUFFICIENT_BUFFER; + *len = addrLen; + } + else { + if (addrLen > 0) + memcpy(addr, &arp.arp_ha.sa_data[0], addrLen); + /* zero out remaining bytes for broken implementations */ + memset(addr + addrLen, 0, *len - addrLen); + *len = addrLen; + *type = MIB_IF_TYPE_ETHERNET; + ret = NO_ERROR; + } + } + } + else + ret = ERROR_NO_MORE_FILES; + } + return ret; +} +#elif defined (HAVE_SYS_SYSCTL_H) && defined (HAVE_NET_IF_DL_H) +DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr, + PDWORD type) +{ + DWORD ret; + struct if_msghdr *ifm; + struct sockaddr_dl *sdl; + u_char *p, *buf; + size_t mibLen; + int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }; + int addrLen; + BOOL found = FALSE; + + if (!name || !len || !addr || !type) + return ERROR_INVALID_PARAMETER; + + if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) + return ERROR_NO_MORE_FILES; + + buf = (u_char *)malloc(mibLen); + if (!buf) + return ERROR_NOT_ENOUGH_MEMORY; + + if (sysctl(mib, 6, buf, &mibLen, NULL, 0) < 0) { + free(buf); + return ERROR_NO_MORE_FILES; + } + + ret = ERROR_INVALID_DATA; + for (p = buf; !found && p < buf + mibLen; p += ifm->ifm_msglen) { + ifm = (struct if_msghdr *)p; + sdl = (struct sockaddr_dl *)(ifm + 1); + + if (ifm->ifm_type != RTM_IFINFO || (ifm->ifm_addrs & RTA_IFP) == 0) + continue; + + if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 || + memcmp(sdl->sdl_data, name, max(sdl->sdl_nlen, strlen(name))) != 0) + continue; + + found = TRUE; + addrLen = min(MAX_INTERFACE_PHYSADDR, sdl->sdl_alen); + if (addrLen > *len) { + ret = ERROR_INSUFFICIENT_BUFFER; + *len = addrLen; + } + else { + if (addrLen > 0) + memcpy(addr, LLADDR(sdl), addrLen); + /* zero out remaining bytes for broken implementations */ + memset(addr + addrLen, 0, *len - addrLen); + *len = addrLen; +#if defined(HAVE_NET_IF_TYPES_H) + switch (sdl->sdl_type) + { + case IFT_ETHER: + *type = MIB_IF_TYPE_ETHERNET; + break; + case IFT_FDDI: + *type = MIB_IF_TYPE_FDDI; + break; + case IFT_ISO88024: /* Token Bus */ + *type = MIB_IF_TYPE_TOKENRING; + break; + case IFT_ISO88025: /* Token Ring */ + *type = MIB_IF_TYPE_TOKENRING; + break; + case IFT_PPP: + *type = MIB_IF_TYPE_PPP; + break; + case IFT_SLIP: + *type = MIB_IF_TYPE_SLIP; + break; + case IFT_LOOP: + *type = MIB_IF_TYPE_LOOPBACK; + break; + default: + *type = MIB_IF_TYPE_OTHER; + } +#else + /* default if we don't know */ + *type = MIB_IF_TYPE_ETHERNET; +#endif + ret = NO_ERROR; + } + } + free(buf); + return ret; +} +#endif + +DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr, + PDWORD type) +{ + const char *name = getInterfaceNameByIndex(index); + + if (name) + return getInterfacePhysicalByName(name, len, addr, type); + else + return ERROR_INVALID_DATA; +} + +DWORD getInterfaceMtuByName(const char *name, PDWORD mtu) +{ + DWORD ret; + int fd; + + if (!name) + return ERROR_INVALID_PARAMETER; + if (!mtu) + return ERROR_INVALID_PARAMETER; + + fd = socket(PF_INET, SOCK_DGRAM, 0); + if (fd != -1) { + struct ifreq ifr; + + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ] = '\0'; + if ((ioctl(fd, SIOCGIFMTU, &ifr))) + ret = ERROR_INVALID_DATA; + else { + *mtu = ifr.ifr_mtu; + ret = NO_ERROR; + } + } + else + ret = ERROR_NO_MORE_FILES; + return ret; +} + +DWORD getInterfaceMtuByIndex(DWORD index, PDWORD mtu) +{ + const char *name = getInterfaceNameByIndex(index); + + if (name) + return getInterfaceMtuByName(name, mtu); + else + return ERROR_INVALID_DATA; +} + +DWORD getInterfaceStatusByName(const char *name, PDWORD status) +{ + DWORD ret; + int fd; + + if (!name) + return ERROR_INVALID_PARAMETER; + if (!status) + return ERROR_INVALID_PARAMETER; + + fd = socket(PF_INET, SOCK_DGRAM, 0); + if (fd != -1) { + struct ifreq ifr; + + strncpy(ifr.ifr_name, name, IFNAMSIZ); + ifr.ifr_name[IFNAMSIZ] = '\0'; + if ((ioctl(fd, SIOCGIFFLAGS, &ifr))) + ret = ERROR_INVALID_DATA; + else { + if (ifr.ifr_flags & IFF_UP) + *status = MIB_IF_OPER_STATUS_OPERATIONAL; + else + *status = MIB_IF_OPER_STATUS_NON_OPERATIONAL; + ret = NO_ERROR; + } + } + else + ret = ERROR_NO_MORE_FILES; + return ret; +} + +DWORD getInterfaceStatusByIndex(DWORD index, PDWORD status) +{ + const char *name = getInterfaceNameByIndex(index); + + if (name) + return getInterfaceStatusByName(name, status); + else + return ERROR_INVALID_DATA; +} + +DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry) +{ + BYTE addr[MAX_INTERFACE_PHYSADDR]; + DWORD ret, len = sizeof(addr), type; + + if (!name) + return ERROR_INVALID_PARAMETER; + if (!entry) + return ERROR_INVALID_PARAMETER; + + if (getInterfacePhysicalByName(name, &len, addr, &type) == NO_ERROR) { + WCHAR *assigner; + const char *walker; + + memset(entry, 0, sizeof(MIB_IFROW)); + for (assigner = entry->wszName, walker = name; *walker; + walker++, assigner++) + *assigner = *walker; + *assigner = 0; + getInterfaceIndexByName(name, &entry->dwIndex); + entry->dwPhysAddrLen = len; + memcpy(entry->bPhysAddr, addr, len); + memset(entry->bPhysAddr + len, 0, sizeof(entry->bPhysAddr) - len); + entry->dwType = type; + /* FIXME: how to calculate real speed? */ + getInterfaceMtuByName(name, &entry->dwMtu); + /* lie, there's no "administratively down" here */ + entry->dwAdminStatus = MIB_IF_ADMIN_STATUS_UP; + getInterfaceStatusByName(name, &entry->dwOperStatus); + /* punt on dwLastChange? */ + entry->dwDescrLen = min(strlen(name), MAX_INTERFACE_DESCRIPTION - 1); + memcpy(entry->bDescr, name, entry->dwDescrLen); + entry->bDescr[entry->dwDescrLen] = '\0'; + entry->dwDescrLen++; + ret = NO_ERROR; + } + else + ret = ERROR_INVALID_DATA; + return ret; +} + +DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry) +{ + const char *name = getInterfaceNameByIndex(index); + + if (name) + return getInterfaceEntryByName(name, entry); + else + return ERROR_INVALID_DATA; +} + +char *toIPAddressString(unsigned int addr, char string[16]) +{ + if (string) { + struct in_addr iAddr; + + iAddr.s_addr = addr; + /* extra-anal, just to make auditors happy */ + strncpy(string, inet_ntoa(iAddr), 16); + string[16] = '\0'; + } + return string; +} diff --git a/dlls/iphlpapi/ifenum.h b/dlls/iphlpapi/ifenum.h new file mode 100644 index 00000000000..f06e33ab2da --- /dev/null +++ b/dlls/iphlpapi/ifenum.h @@ -0,0 +1,130 @@ +/* ifenum.h + * Copyright (C) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This module implements functions shared by DLLs that need to enumerate + * network interfaces and addresses. It's meant to hide some problematic + * defines like socket(), as well as provide only one file + * that needs to be ported to implement these functions on different platforms, + * since the Windows API provides multiple ways to get at this info. + * + * Like Windows, it uses a numeric index to identify an interface uniquely. + * As implemented, an interface represents a UNIX network interface, virtual + * or real, and thus can have 0 or 1 IP addresses associated with it. (This + * only supports IPv4.) + * The indexes returned are not guaranteed to be contiguous, so don't call + * getNumInterfaces() and assume the values [0,getNumInterfaces() - 1] will be + * valid indexes; use getInterfaceIndexTable() instead. Non-loopback + * interfaces have lower index values than loopback interfaces, in order to + * make the indexes somewhat reusable as Netbios LANA numbers. See ifenum.c + * for more detail on this. + * + * See also the companion file, ipstats.h, for functions related to getting + * statistics. + */ +#ifndef WINE_IFENUM_H_ +#define WINE_IFENUM_H_ + +#include "windef.h" +#include "iprtrmib.h" + +#define MAX_INTERFACE_PHYSADDR 8 +#define MAX_INTERFACE_DESCRIPTION 256 + +DWORD getNumInterfaces(void); +DWORD getNumNonLoopbackInterfaces(void); + +/* A table of interface indexes, see get*InterfaceTable(). Ignore numAllocated, + * it's used during the creation of the table. + */ +typedef struct _InterfaceIndexTable { + DWORD numIndexes; + DWORD numAllocated; + DWORD indexes[1]; +} InterfaceIndexTable; + +/* Returns a table with all known interface indexes, or NULL if one could not + * be allocated. free() the returned table. + */ +InterfaceIndexTable *getInterfaceIndexTable(void); + +/* Like getInterfaceIndexTable, but filters out loopback interfaces. */ +InterfaceIndexTable *getNonLoopbackInterfaceIndexTable(void); + +/* ByName/ByIndex versions of various getter functions. */ + +/* can be used as quick check to see if you've got a valid index, returns NULL + * if not. The buffer's only valid till the next call, so copy it right away + * if you care. + */ +const char *getInterfaceNameByIndex(DWORD index); + +/* Fills index with the index of name, if found. Returns + * ERROR_INVALID_PARAMETER if name or index is NULL, ERROR_INVALID_DATA if name + * is not found, and NO_ERROR on success. + */ +DWORD getInterfaceIndexByName(const char *name, PDWORD index); + +/* This bunch returns IP addresses, and INADDR_ANY or INADDR_NONE if not found, + * appropriately depending on the f/n. + */ +DWORD getInterfaceIPAddrByName(const char *name); +DWORD getInterfaceIPAddrByIndex(DWORD index); +DWORD getInterfaceMaskByName(const char *name); +DWORD getInterfaceMaskByIndex(DWORD index); +DWORD getInterfaceBCastAddrByName(const char *name); +DWORD getInterfaceBCastAddrByIndex(DWORD index); + +/* Gets a few physical charactersistics of a device: MAC addr len, MAC addr, + * and type as one of the MIB_IF_TYPEs. + * len's in-out: on in, needs to say how many bytes are available in addr, + * which to be safe should be MAX_INTERFACE_PHYSADDR. On out, it's how many + * bytes were set, or how many were required if addr isn't big enough. + * Returns ERROR_INVALID_PARAMETER if name, len, addr, or type is NULL. + * Returns ERROR_INVALID_DATA if name/index isn't valid. + * Returns ERROR_INSUFFICIENT_BUFFER if addr isn't large enough for the + * physical address; *len will contain the required size. + * May return other errors, e.g. ERROR_OUTOFMEMORY or ERROR_NO_MORE_FILES, + * if internal errors occur. + * Returns NO_ERROR on success. + */ +DWORD getInterfacePhysicalByName(const char *name, PDWORD len, PBYTE addr, + PDWORD type); +DWORD getInterfacePhysicalByIndex(DWORD index, PDWORD len, PBYTE addr, + PDWORD type); + +/* Get the operational status as a (MIB_)IF_OPER_STATUS type. + */ +DWORD getInterfaceStatusByName(const char *name, PDWORD status); +DWORD getInterfaceStatusByIndex(DWORD index, PDWORD status); + +DWORD getInterfaceMtuByName(const char *name, PDWORD mtu); +DWORD getInterfaceMtuByIndex(DWORD index, PDWORD mtu); + +/* Fills in the MIB_IFROW by name/index. Doesn't fill in interface statistics, + * see ipstats.h for that. + * Returns ERROR_INVALID_PARAMETER if name or entry is NULL, ERROR_INVALID_DATA + * if name/index isn't valid, and NO_ERROR otherwise. + */ +DWORD getInterfaceEntryByName(const char *name, PMIB_IFROW entry); +DWORD getInterfaceEntryByIndex(DWORD index, PMIB_IFROW entry); + +/* Converts the network-order bytes in addr to a printable string. Returns + * string. + */ +char *toIPAddressString(unsigned int addr, char string[16]); + +#endif /* ndef WINE_IFENUM_H_ */ diff --git a/dlls/iphlpapi/iphlpapi.spec b/dlls/iphlpapi/iphlpapi.spec new file mode 100644 index 00000000000..599b2c1fad2 --- /dev/null +++ b/dlls/iphlpapi/iphlpapi.spec @@ -0,0 +1,117 @@ +@ stdcall AddIPAddress( long long long ptr ptr ) +@ stub AllocateAndGetArpEntTableFromStack +@ stub AllocateAndGetIfTableFromStack +@ stub AllocateAndGetIpAddrTableFromStack +@ stub AllocateAndGetIpForwardTableFromStack +@ stub AllocateAndGetIpNetTableFromStack +@ stub AllocateAndGetTcpTableFromStack +@ stub AllocateAndGetUdpTableFromStack +@ stdcall CreateIpForwardEntry( ptr ) +@ stdcall CreateIpNetEntry( ptr ) +@ stdcall CreateProxyArpEntry( long long long ) +@ stdcall DeleteIPAddress( long ) +@ stdcall DeleteIpForwardEntry( ptr ) +@ stdcall DeleteIpNetEntry( ptr ) +@ stdcall DeleteProxyArpEntry( long long long ) +@ stdcall EnableRouter( ptr ptr ) +@ stdcall FlushIpNetTable( long ) +@ stub FlushIpNetTableFromStack +@ stdcall GetAdapterIndex( wstr ptr ) +@ stub GetAdapterOrderMap +@ stdcall GetAdaptersInfo( ptr ptr ) +@ stdcall GetBestInterface( long ptr ) +@ stub GetBestInterfaceFromStack +@ stdcall GetBestRoute( long long long ) +@ stub GetBestRouteFromStack +@ stdcall GetFriendlyIfIndex( long ) +@ stdcall GetIcmpStatistics( ptr ) +@ stub GetIcmpStatsFromStack +@ stdcall GetIfEntry( ptr ) +@ stub GetIfEntryFromStack +@ stdcall GetIfTable( ptr ptr long ) +@ stub GetIfTableFromStack +@ stub GetIgmpList +@ stdcall GetInterfaceInfo( ptr ptr ) +@ stdcall GetIpAddrTable( ptr ptr long ) +@ stub GetIpAddrTableFromStack +@ stdcall GetIpForwardTable( ptr ptr long ) +@ stub GetIpForwardTableFromStack +@ stdcall GetIpNetTable( ptr ptr long ) +@ stub GetIpNetTableFromStack +@ stdcall GetIpStatistics( ptr ) +@ stub GetIpStatsFromStack +@ stdcall GetNetworkParams( ptr ptr ) +@ stdcall GetNumberOfInterfaces( ptr ) +@ stdcall GetPerAdapterInfo( long ptr ptr ) +@ stdcall GetRTTAndHopCount( long ptr long ptr ) +@ stdcall GetTcpStatistics( ptr ) +@ stub GetTcpStatsFromStack +@ stdcall GetTcpTable( ptr ptr long ) +@ stub GetTcpTableFromStack +@ stdcall GetUdpStatistics( ptr ) +@ stub GetUdpStatsFromStack +@ stdcall GetUdpTable( ptr ptr long ) +@ stub GetUdpTableFromStack +@ stdcall GetUniDirectionalAdapterInfo( ptr ptr ) +@ stub InternalCreateIpForwardEntry +@ stub InternalCreateIpNetEntry +@ stub InternalDeleteIpForwardEntry +@ stub InternalDeleteIpNetEntry +@ stub InternalGetIfTable +@ stub InternalGetIpAddrTable +@ stub InternalGetIpForwardTable +@ stub InternalGetIpNetTable +@ stub InternalGetTcpTable +@ stub InternalGetUdpTable +@ stub InternalSetIfEntry +@ stub InternalSetIpForwardEntry +@ stub InternalSetIpNetEntry +@ stub InternalSetIpStats +@ stub InternalSetTcpEntry +@ stdcall IpReleaseAddress( ptr ) +@ stdcall IpRenewAddress( ptr ) +@ stub IsLocalAddress +@ stub NTPTimeToNTFileTime +@ stub NTTimeToNTPTime +@ stub NhGetGuidFromInterfaceName +@ stub NhGetInterfaceNameFromGuid +@ stub NhpAllocateAndGetInterfaceInfoFromStack +@ stub NhpGetInterfaceIndexFromStack +@ stdcall NotifyAddrChange( ptr ptr ) +@ stdcall NotifyRouteChange( ptr ptr ) +@ stub NotifyRouteChangeEx +@ stub _PfAddFiltersToInterface@24 +@ stub _PfAddGlobalFilterToInterface@8 +@ stub _PfBindInterfaceToIPAddress@12 +@ stub _PfBindInterfaceToIndex@16 +@ stub _PfCreateInterface@24 +@ stub _PfDeleteInterface@4 +@ stub _PfDeleteLog@0 +@ stub _PfGetInterfaceStatistics@16 +@ stub _PfMakeLog@4 +@ stub _PfRebindFilters@8 +@ stub _PfRemoveFilterHandles@12 +@ stub _PfRemoveFiltersFromInterface@20 +@ stub _PfRemoveGlobalFilterFromInterface@8 +@ stub _PfSetLogBuffer@28 +@ stub _PfTestPacket@20 +@ stub _PfUnBindInterface@4 +@ stdcall SendARP( long long ptr ptr ) +@ stub SetAdapterIpAddress +@ stub SetBlockRoutes +@ stdcall SetIfEntry( ptr ) +@ stub SetIfEntryToStack +@ stdcall SetIpForwardEntry( ptr ) +@ stub SetIpForwardEntryToStack +@ stub SetIpMultihopRouteEntryToStack +@ stdcall SetIpNetEntry( ptr ) +@ stub SetIpNetEntryToStack +@ stub SetIpRouteEntryToStack +@ stdcall SetIpStatistics( ptr ) +@ stub SetIpStatsToStack +@ stdcall SetIpTTL( long ) +@ stub SetProxyArpEntryToStack +@ stub SetRouteWithRef +@ stdcall SetTcpEntry( ptr ) +@ stub SetTcpEntryToStack +@ stdcall UnenableRouter( ptr ptr ) diff --git a/dlls/iphlpapi/iphlpapi_main.c b/dlls/iphlpapi/iphlpapi_main.c new file mode 100644 index 00000000000..d2d054e8fcc --- /dev/null +++ b/dlls/iphlpapi/iphlpapi_main.c @@ -0,0 +1,1397 @@ +/* + * iphlpapi dll implementation + * + * Copyright (C) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include "winbase.h" +#include "iphlpapi.h" +#include "ifenum.h" +#include "ipstats.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi); + + +/****************************************************************** + * AddIPAddress (IPHLPAPI.@) + * + * + * PARAMS + * + * Address [In] + * IpMask [In] + * IfIndex [In] + * NTEContext [In/Out] + * NTEInstance [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, PULONG NTEContext, PULONG NTEInstance) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * CreateIpForwardEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pRoute [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute) +{ + /* could use SIOCADDRT, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * CreateIpNetEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pArpEntry [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry) +{ + /* could use SIOCSARP on systems that support it, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * CreateProxyArpEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * dwAddress [In] + * dwMask [In] + * dwIfIndex [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * DeleteIPAddress (IPHLPAPI.@) + * + * + * PARAMS + * + * NTEContext [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI DeleteIPAddress(ULONG NTEContext) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * DeleteIpForwardEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pRoute [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute) +{ + /* could use SIOCDELRT, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * DeleteIpNetEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pArpEntry [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry) +{ + /* could use SIOCDARP on systems that support it, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * DeleteProxyArpEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * dwAddress [In] + * dwMask [In] + * dwIfIndex [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, DWORD dwIfIndex) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * EnableRouter (IPHLPAPI.@) + * + * + * PARAMS + * + * pHandle [In/Out] + * pOverlapped [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI EnableRouter(HANDLE * pHandle, OVERLAPPED * pOverlapped) +{ + FIXME(":stub\n"); + /* could echo "1" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to + could map EACCESS to ERROR_ACCESS_DENIED, I suppose + marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * FlushIpNetTable (IPHLPAPI.@) + * + * + * PARAMS + * + * dwIfIndex [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex) +{ + FIXME(":stub\n"); + /* this flushes the arp cache of the given index + marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * GetAdapterIndex (IPHLPAPI.@) + * + * + * PARAMS + * + * AdapterName [In/Out] + * IfIndex [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * GetAdaptersInfo (IPHLPAPI.@) + * + * + * PARAMS + * + * pAdapterInfo [In/Out] + * pOutBufLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen) +{ + DWORD ret; + + if (!pOutBufLen) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numNonLoopbackInterfaces = getNumNonLoopbackInterfaces(); + + if (numNonLoopbackInterfaces > 0) { + /* this calculation assumes only one address in the IP_ADDR_STRING lists. + that's okay, because: + - we don't get multiple addresses per adapter anyway + - we don't know about per-adapter gateways + - we don't know about DHCP or WINS (and these must be single anyway) */ + ULONG size = sizeof(IP_ADAPTER_INFO) * numNonLoopbackInterfaces; + + if (!pAdapterInfo || *pOutBufLen < size) { + *pOutBufLen = size; + ret = ERROR_BUFFER_OVERFLOW; + } + else { + InterfaceIndexTable *table = getNonLoopbackInterfaceIndexTable(); + + if (table) { + size = sizeof(IP_ADAPTER_INFO) * table->numIndexes; + if (*pOutBufLen < size) { + *pOutBufLen = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + DWORD ndx; + + memset(pAdapterInfo, 0, size); + for (ndx = 0; ndx < table->numIndexes; ndx++) { + PIP_ADAPTER_INFO ptr = &pAdapterInfo[ndx]; + DWORD addrLen = sizeof(ptr->Address), type; + + /* on Win98 this is left empty, but whatever */ + strncpy(ptr->AdapterName, + getInterfaceNameByIndex(table->indexes[ndx]), + sizeof(ptr->AdapterName)); + ptr->AdapterName[MAX_ADAPTER_NAME_LENGTH] = '\0'; + getInterfacePhysicalByIndex(table->indexes[ndx], &addrLen, + ptr->Address, &type); + /* MS defines address length and type as UINT in some places and + DWORD in others, **sigh**. Don't want to assume that PUINT and + PDWORD are equiv (64-bit?) */ + ptr->AddressLength = addrLen; + ptr->Type = type; + ptr->Index = table->indexes[ndx]; + toIPAddressString(getInterfaceIPAddrByIndex(table->indexes[ndx]), + ptr->IpAddressList.IpAddress.String); + toIPAddressString(getInterfaceMaskByIndex(table->indexes[ndx]), + ptr->IpAddressList.IpMask.String); + if (ndx < table->numIndexes + 1) + ptr->Next = &pAdapterInfo[ndx + 1]; + } + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + else + ret = ERROR_NO_DATA; + } + return ret; +} + + +/****************************************************************** + * GetBestInterface (IPHLPAPI.@) + * + * + * PARAMS + * + * dwDestAddr [In] + * pdwBestIfIndex [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex) +{ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * GetBestRoute (IPHLPAPI.@) + * + * + * PARAMS + * + * dwDestAddr [In] + * dwSourceAddr [In] + * OUT [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDROW pBestRoute) +{ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * GetFriendlyIfIndex (IPHLPAPI.@) + * + * + * PARAMS + * + * IfIndex [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex) +{ + /* windows doesn't validate these, either, just makes sure the top byte is + cleared. I assume my ipshared module never gives an index with the top + byte set. */ + return IfIndex; +} + + +/****************************************************************** + * GetIcmpStatistics (IPHLPAPI.@) + * + * + * PARAMS + * + * pStats [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats) +{ + return getICMPStats(pStats); +} + + +/****************************************************************** + * GetIfEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pIfRow [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow) +{ + DWORD ret; + const char *name; + + if (!pIfRow) + return ERROR_INVALID_PARAMETER; + + name = getInterfaceNameByIndex(pIfRow->dwIndex); + if (name) { + ret = getInterfaceEntryByName(name, pIfRow); + if (ret == NO_ERROR) + ret = getInterfaceStatsByName(name, pIfRow); + } + else + ret = ERROR_INVALID_DATA; + return ret; +} + + +/****************************************************************** + * GetIfTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pIfTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numInterfaces = getNumInterfaces(); + ULONG size = sizeof(MIB_IFTABLE) + (numInterfaces - 1) * sizeof(MIB_IFROW); + + if (!pIfTable || *pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + InterfaceIndexTable *table = getInterfaceIndexTable(); + + if (table) { + size = sizeof(MIB_IFTABLE) + (table->numIndexes - 1) * + sizeof(MIB_IFROW); + if (*pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + DWORD ndx; + + if (bOrder) + FIXME(":order not implemented"); + pIfTable->dwNumEntries = 0; + for (ndx = 0; ndx < table->numIndexes; ndx++) { + pIfTable->table[ndx].dwIndex = table->indexes[ndx]; + GetIfEntry(&pIfTable->table[ndx]); + pIfTable->dwNumEntries++; + } + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetInterfaceInfo (IPHLPAPI.@) + * + * + * PARAMS + * + * pIfTable [In/Out] + * dwOutBufLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen) +{ + DWORD ret; + + if (!dwOutBufLen) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numInterfaces = getNumInterfaces(); + ULONG size = sizeof(IP_INTERFACE_INFO) + (numInterfaces - 1) * + sizeof(IP_ADAPTER_INDEX_MAP); + + if (!pIfTable || *dwOutBufLen < size) { + *dwOutBufLen = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + InterfaceIndexTable *table = getInterfaceIndexTable(); + + if (table) { + size = sizeof(IP_INTERFACE_INFO) + (table->numIndexes - 1) * + sizeof(IP_ADAPTER_INDEX_MAP); + if (*dwOutBufLen < size) { + *dwOutBufLen = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + DWORD ndx; + + pIfTable->NumAdapters = 0; + for (ndx = 0; ndx < table->numIndexes; ndx++) { + const char *walker, *name; + WCHAR *assigner; + + pIfTable->Adapter[ndx].Index = table->indexes[ndx]; + name = getInterfaceNameByIndex(table->indexes[ndx]); + for (walker = name, assigner = pIfTable->Adapter[ndx].Name; + walker && *walker && + assigner - pIfTable->Adapter[ndx].Name < MAX_ADAPTER_NAME - 1; + walker++, assigner++) + *assigner = *walker; + *assigner = 0; + pIfTable->NumAdapters++; + } + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetIpAddrTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pIpAddrTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numInterfaces = getNumInterfaces(); + ULONG size = sizeof(MIB_IPADDRTABLE) + (numInterfaces - 1) * + sizeof(MIB_IPADDRROW); + + if (!pIpAddrTable || *pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + InterfaceIndexTable *table = getInterfaceIndexTable(); + + if (table) { + size = sizeof(MIB_IPADDRTABLE) + (table->numIndexes - 1) * + sizeof(MIB_IPADDRROW); + if (*pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + DWORD ndx; + + if (bOrder) + FIXME(":order not implemented"); + pIpAddrTable->dwNumEntries = 0; + for (ndx = 0; ndx < table->numIndexes; ndx++) { + pIpAddrTable->table[ndx].dwIndex = table->indexes[ndx]; + pIpAddrTable->table[ndx].dwAddr = + getInterfaceIPAddrByIndex(table->indexes[ndx]); + pIpAddrTable->table[ndx].dwMask = + getInterfaceMaskByIndex(table->indexes[ndx]); + pIpAddrTable->table[ndx].dwBCastAddr = + getInterfaceBCastAddrByIndex(table->indexes[ndx]); + /* FIXME: hardcoded reasm size, not sure where to get it */ + pIpAddrTable->table[ndx].dwReasmSize = 65535; + pIpAddrTable->table[ndx].unused1 = 0; + pIpAddrTable->table[ndx].wType = 0; /* aka unused2 */ + pIpAddrTable->dwNumEntries++; + } + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetIpForwardTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pIpForwardTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, PULONG pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numRoutes = getNumRoutes(); + ULONG sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (numRoutes - 1) * + sizeof(MIB_IPFORWARDROW); + + if (!pIpForwardTable || *pdwSize < sizeNeeded) { + *pdwSize = sizeNeeded; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + RouteTable *table = getRouteTable(); + if (table) { + sizeNeeded = sizeof(MIB_IPFORWARDTABLE) + (table->numRoutes - 1) * + sizeof(MIB_IPFORWARDROW); + if (*pdwSize < sizeNeeded) { + *pdwSize = sizeNeeded; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + DWORD ndx; + + if (bOrder) + FIXME(":order not implemented"); + pIpForwardTable->dwNumEntries = table->numRoutes; + for (ndx = 0; ndx < numRoutes; ndx++) { + pIpForwardTable->table[ndx].dwForwardIfIndex = + table->routes[ndx].ifIndex; + pIpForwardTable->table[ndx].dwForwardDest = + table->routes[ndx].dest; + pIpForwardTable->table[ndx].dwForwardMask = + table->routes[ndx].mask; + pIpForwardTable->table[ndx].dwForwardPolicy = 0; + pIpForwardTable->table[ndx].dwForwardNextHop = + table->routes[ndx].gateway; + /* FIXME: this type is appropriate for local interfaces; may not + always be appropriate */ + pIpForwardTable->table[ndx].dwForwardType = MIB_IPROUTE_TYPE_DIRECT; + /* FIXME: other protos might be appropriate, e.g. the default route + is typically set with MIB_IPPROTO_NETMGMT instead */ + pIpForwardTable->table[ndx].dwForwardProto = MIB_IPPROTO_LOCAL; + /* punt on age and AS */ + pIpForwardTable->table[ndx].dwForwardAge = 0; + pIpForwardTable->table[ndx].dwForwardNextHopAS = 0; + pIpForwardTable->table[ndx].dwForwardMetric1 = + table->routes[ndx].metric; + /* rest of the metrics are 0.. */ + pIpForwardTable->table[ndx].dwForwardMetric2 = 0; + pIpForwardTable->table[ndx].dwForwardMetric3 = 0; + pIpForwardTable->table[ndx].dwForwardMetric4 = 0; + pIpForwardTable->table[ndx].dwForwardMetric5 = 0; + } + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetIpNetTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pIpNetTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numEntries = getNumArpEntries(); + ULONG size = sizeof(MIB_IPNETTABLE) + (numEntries - 1) * + sizeof(MIB_IPNETROW); + + if (!pIpNetTable || *pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + PMIB_IPNETTABLE table = getArpTable(); + + if (table) { + size = sizeof(MIB_IPNETTABLE) + (table->dwNumEntries - 1) * + sizeof(MIB_IPNETROW); + if (*pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + if (bOrder) + FIXME(":order not implemented"); + memcpy(pIpNetTable, table, size); + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetIpStatistics (IPHLPAPI.@) + * + * + * PARAMS + * + * pStats [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats) +{ + return getIPStats(pStats); +} + + +/****************************************************************** + * GetNetworkParams (IPHLPAPI.@) + * + * + * PARAMS + * + * pFixedInfo [In/Out] + * pOutBufLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen) +{ + DWORD size; + + if (!pOutBufLen) + return ERROR_INVALID_PARAMETER; + + size = sizeof(FIXED_INFO) + min(1, (_res.nscount - 1) * + sizeof(IP_ADDR_STRING)); + if (!pFixedInfo || *pOutBufLen < size) { + *pOutBufLen = size; + return ERROR_BUFFER_OVERFLOW; + } + + memset(pFixedInfo, 0, size); + size = sizeof(pFixedInfo->HostName); + GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size); + size = sizeof(pFixedInfo->DomainName); + GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size); + if (_res.nscount > 0) { + PIP_ADDR_STRING ptr; + int i; + + for (i = 0, ptr = &pFixedInfo->DnsServerList; i < _res.nscount; + i++, ptr = ptr->Next) { + toIPAddressString(_res.nsaddr_list[i].sin_addr.s_addr, + ptr->IpAddress.String); + ptr->Next = (PIP_ADDR_STRING)((PBYTE)ptr + sizeof(IP_ADDRESS_STRING)); + } + } + /* FIXME: can check whether routing's enabled in /proc/sys/net/ipv4/ip_forward + I suppose could also check for a listener on port 53 to set EnableDns */ + return NO_ERROR; +} + + +/****************************************************************** + * GetNumberOfInterfaces (IPHLPAPI.@) + * + * + * PARAMS + * + * pdwNumIf [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf) +{ + DWORD ret; + + if (!pdwNumIf) + ret = ERROR_INVALID_PARAMETER; + else { + *pdwNumIf = getNumInterfaces(); + ret = NO_ERROR; + } + return ret; +} + + +/****************************************************************** + * GetPerAdapterInfo (IPHLPAPI.@) + * + * + * PARAMS + * + * IfIndex [In] + * pPerAdapterInfo [In/Out] + * pOutBufLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * GetRTTAndHopCount (IPHLPAPI.@) + * + * + * PARAMS + * + * DestIpAddress [In] + * HopCount [In/Out] + * MaxHops [In] + * RTT [In/Out] + * + * RETURNS + * + * BOOL + * + */ +BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT) +{ + FIXME(":stub\n"); + return (BOOL) 0; +} + + +/****************************************************************** + * GetTcpStatistics (IPHLPAPI.@) + * + * + * PARAMS + * + * pStats [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats) +{ + return getTCPStats(pStats); +} + + +/****************************************************************** + * GetTcpTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pTcpTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numEntries = getNumTcpEntries(); + ULONG size = sizeof(MIB_TCPTABLE) + (numEntries - 1) * sizeof(MIB_TCPROW); + + if (!pTcpTable || *pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + PMIB_TCPTABLE table = getTcpTable(); + + if (table) { + size = sizeof(MIB_TCPTABLE) + (table->dwNumEntries - 1) * + sizeof(MIB_TCPROW); + if (*pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + if (bOrder) + FIXME(":order not implemented"); + memcpy(pTcpTable, table, size); + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetUdpStatistics (IPHLPAPI.@) + * + * + * PARAMS + * + * pStats [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats) +{ + return getUDPStats(pStats); +} + + +/****************************************************************** + * GetUdpTable (IPHLPAPI.@) + * + * + * PARAMS + * + * pUdpTable [In/Out] + * pdwSize [In/Out] + * bOrder [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder) +{ + DWORD ret; + + if (!pdwSize) + ret = ERROR_INVALID_PARAMETER; + else { + DWORD numEntries = getNumUdpEntries(); + ULONG size = sizeof(MIB_UDPTABLE) + (numEntries - 1) * sizeof(MIB_UDPROW); + + if (!pUdpTable || *pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + PMIB_UDPTABLE table = getUdpTable(); + + if (table) { + size = sizeof(MIB_UDPTABLE) + (table->dwNumEntries - 1) * + sizeof(MIB_UDPROW); + if (*pdwSize < size) { + *pdwSize = size; + ret = ERROR_INSUFFICIENT_BUFFER; + } + else { + if (bOrder) + FIXME(":order not implemented"); + memcpy(pUdpTable, table, size); + ret = NO_ERROR; + } + free(table); + } + else + ret = ERROR_OUTOFMEMORY; + } + } + return ret; +} + + +/****************************************************************** + * GetUniDirectionalAdapterInfo (IPHLPAPI.@) + * + * + * PARAMS + * + * pIPIfInfo [In/Out] + * dwOutBufLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI GetUniDirectionalAdapterInfo(PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen) +{ + /* a unidirectional adapter?? not bloody likely! */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * IpReleaseAddress (IPHLPAPI.@) + * + * + * PARAMS + * + * AdapterInfo [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo) +{ + /* not a stub, never going to support this (and I never mark an adapter as + DHCP enabled, see GetAdaptersInfo, so this should never get called) */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * IpRenewAddress (IPHLPAPI.@) + * + * + * PARAMS + * + * AdapterInfo [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo) +{ + /* not a stub, never going to support this (and I never mark an adapter as + DHCP enabled, see GetAdaptersInfo, so this should never get called) */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * NotifyAddrChange (IPHLPAPI.@) + * + * + * PARAMS + * + * Handle [In/Out] + * overlapped [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * NotifyRouteChange (IPHLPAPI.@) + * + * + * PARAMS + * + * Handle [In/Out] + * overlapped [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * SendARP (IPHLPAPI.@) + * + * + * PARAMS + * + * DestIP [In] + * SrcIP [In] + * pMacAddr [In/Out] + * PhyAddrLen [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen) +{ + FIXME(":stub\n"); + /* marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * SetIfEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pIfRow [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow) +{ + /* this is supposed to set an administratively interface up or down. + Could do SIOCSIFFLAGS and set/clear IFF_UP, but, not sure I want to, and + this sort of down is indistinguishable from other sorts of down (e.g. no + link). */ + FIXME(":stub\n"); + return ERROR_NOT_SUPPORTED; +} + + +/****************************************************************** + * SetIpForwardEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pRoute [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute) +{ + /* this is to add a route entry, how's it distinguishable from + CreateIpForwardEntry? + could use SIOCADDRT, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * SetIpNetEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pArpEntry [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry) +{ + /* same as CreateIpNetEntry here, could use SIOCSARP, not sure I want to */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * SetIpStatistics (IPHLPAPI.@) + * + * + * PARAMS + * + * pIpStats [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats) +{ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * SetIpTTL (IPHLPAPI.@) + * + * + * PARAMS + * + * nTTL [In] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetIpTTL(UINT nTTL) +{ + /* could echo nTTL > /proc/net/sys/net/ipv4/ip_default_ttl, not sure I + want to. Could map EACCESS to ERROR_ACCESS_DENIED, I suppose */ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * SetTcpEntry (IPHLPAPI.@) + * + * + * PARAMS + * + * pTcpRow [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow) +{ + FIXME(":stub\n"); + return (DWORD) 0; +} + + +/****************************************************************** + * UnenableRouter (IPHLPAPI.@) + * + * + * PARAMS + * + * pOverlapped [In/Out] + * lpdwEnableCount [In/Out] + * + * RETURNS + * + * DWORD + * + */ +DWORD WINAPI UnenableRouter(OVERLAPPED * pOverlapped, LPDWORD lpdwEnableCount) +{ + FIXME(":stub\n"); + /* could echo "0" > /proc/net/sys/net/ipv4/ip_forward, not sure I want to + could map EACCESS to ERROR_ACCESS_DENIED, I suppose + marking Win2K+ functions not supported */ + return ERROR_NOT_SUPPORTED; +} diff --git a/dlls/iphlpapi/ipstats.c b/dlls/iphlpapi/ipstats.c new file mode 100644 index 00000000000..b574ec5417b --- /dev/null +++ b/dlls/iphlpapi/ipstats.c @@ -0,0 +1,829 @@ +/* Copyright (C) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file implements statistics getting using the /proc filesystem exported + * by Linux, and maybe other OSes. + */ + +#include "config.h" + +#include +#include +#include + +#if HAVE_NET_IF_H +#include +#endif + +#if HAVE_NETINET_TCP_H +#include +#endif + +#if HAVE_NETINET_TCP_FSM_H +#include +#endif + +#include "winbase.h" +#include "iprtrmib.h" +#include "ifenum.h" +#include "ipstats.h" + +DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry) +{ + FILE *fp; + + if (!name) + return ERROR_INVALID_PARAMETER; + if (!entry) + return ERROR_INVALID_PARAMETER; + + /* get interface stats from /proc/net/dev, no error if can't + no inUnknownProtos, outNUcastPkts, outQLen */ + fp = fopen("/proc/net/dev", "r"); + if (fp) { + char buf[512] = { 0 }, *ptr; + int nameLen = strlen(name), nameFound = 0; + + + ptr = fgets(buf, sizeof(buf), fp); + while (ptr && !nameFound) { + while (*ptr && isspace(*ptr)) + ptr++; + if (strncasecmp(ptr, name, nameLen) == 0 && *(ptr + nameLen) == ':') + nameFound = 1; + else + ptr = fgets(buf, sizeof(buf), fp); + } + if (nameFound) { + char *endPtr; + + ptr += nameLen + 1; + if (ptr && *ptr) { + entry->dwInOctets = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + entry->dwInUcastPkts = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + entry->dwInErrors = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + entry->dwInDiscards = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + strtoul(ptr, &endPtr, 10); /* skip */ + ptr = endPtr; + } + if (ptr && *ptr) { + strtoul(ptr, &endPtr, 10); /* skip */ + ptr = endPtr; + } + if (ptr && *ptr) { + strtoul(ptr, &endPtr, 10); /* skip */ + ptr = endPtr; + } + if (ptr && *ptr) { + entry->dwInNUcastPkts = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + entry->dwOutOctets = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + entry->dwOutUcastPkts = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + entry->dwOutErrors = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + entry->dwOutDiscards = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + } + fclose(fp); + } + return NO_ERROR; +} + +DWORD getICMPStats(MIB_ICMP *stats) +{ + FILE *fp; + + if (!stats) + return ERROR_INVALID_PARAMETER; + + memset(stats, 0, sizeof(MIB_ICMP)); + /* get most of these stats from /proc/net/snmp, no error if can't */ + fp = fopen("/proc/net/snmp", "r"); + if (fp) { + const char hdr[] = "Icmp:"; + char buf[512] = { 0 }, *ptr; + + do { + ptr = fgets(buf, sizeof(buf), fp); + } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1)); + if (ptr) { + /* last line was a header, get another */ + ptr = fgets(buf, sizeof(buf), fp); + if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) { + char *endPtr; + + ptr += sizeof(hdr); + if (ptr && *ptr) { + stats->stats.icmpInStats.dwMsgs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwErrors = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwTimeExcds = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwParmProbs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwRedirects = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwEchoReps = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwTimestamps = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwTimestampReps = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwAddrMasks = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpInStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwMsgs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwErrors = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwDestUnreachs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwTimeExcds = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwParmProbs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwSrcQuenchs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwRedirects = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwEchoReps = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwTimestamps = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwTimestampReps = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwAddrMasks = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->stats.icmpOutStats.dwAddrMaskReps = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + } + } + fclose(fp); + } + return NO_ERROR; +} + +DWORD getIPStats(PMIB_IPSTATS stats) +{ + FILE *fp; + + if (!stats) + return ERROR_INVALID_PARAMETER; + + memset(stats, 0, sizeof(MIB_IPSTATS)); + stats->dwNumIf = stats->dwNumAddr = getNumInterfaces(); + stats->dwNumRoutes = getNumRoutes(); + + /* get most of these stats from /proc/net/snmp, no error if can't */ + fp = fopen("/proc/net/snmp", "r"); + if (fp) { + const char hdr[] = "Ip:"; + char buf[512] = { 0 }, *ptr; + + do { + ptr = fgets(buf, sizeof(buf), fp); + } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1)); + if (ptr) { + /* last line was a header, get another */ + ptr = fgets(buf, sizeof(buf), fp); + if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) { + char *endPtr; + + ptr += sizeof(hdr); + if (ptr && *ptr) { + stats->dwForwarding = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwDefaultTTL = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwInReceives = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwInHdrErrors = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwInAddrErrors = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwForwDatagrams = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwInUnknownProtos = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwInDiscards = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwInDelivers = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwOutRequests = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwOutDiscards = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwOutNoRoutes = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwReasmTimeout = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwReasmReqds = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwReasmOks = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwReasmFails = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwFragOks = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwFragFails = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwFragCreates = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + /* hmm, no routingDiscards */ + } + } + fclose(fp); + } + return NO_ERROR; +} + +DWORD getTCPStats(MIB_TCPSTATS *stats) +{ + FILE *fp; + + if (!stats) + return ERROR_INVALID_PARAMETER; + + memset(stats, 0, sizeof(MIB_TCPSTATS)); + + /* get from /proc/net/snmp, no error if can't */ + fp = fopen("/proc/net/snmp", "r"); + if (fp) { + const char hdr[] = "Tcp:"; + char buf[512] = { 0 }, *ptr; + + + do { + ptr = fgets(buf, sizeof(buf), fp); + } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1)); + if (ptr) { + /* last line was a header, get another */ + ptr = fgets(buf, sizeof(buf), fp); + if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) { + char *endPtr; + + ptr += sizeof(hdr); + if (ptr && *ptr) { + stats->dwRtoAlgorithm = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwRtoMin = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwRtoMin = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwMaxConn = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwActiveOpens = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwPassiveOpens = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwAttemptFails = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwEstabResets = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwCurrEstab = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwInSegs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwOutSegs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwRetransSegs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwInErrs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwOutRsts = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + stats->dwNumConns = getNumTcpEntries(); + } + } + fclose(fp); + } + return NO_ERROR; +} + +DWORD getUDPStats(MIB_UDPSTATS *stats) +{ + FILE *fp; + + if (!stats) + return ERROR_INVALID_PARAMETER; + + memset(stats, 0, sizeof(MIB_UDPSTATS)); + + /* get from /proc/net/snmp, no error if can't */ + fp = fopen("/proc/net/snmp", "r"); + if (fp) { + const char hdr[] = "Udp:"; + char buf[512] = { 0 }, *ptr; + + + do { + ptr = fgets(buf, sizeof(buf), fp); + } while (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1)); + if (ptr) { + /* last line was a header, get another */ + ptr = fgets(buf, sizeof(buf), fp); + if (ptr && strncasecmp(buf, hdr, sizeof(hdr) - 1) == 0) { + char *endPtr; + + ptr += sizeof(hdr); + if (ptr && *ptr) { + stats->dwInDatagrams = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwNoPorts = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwInErrors = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwOutDatagrams = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + if (ptr && *ptr) { + stats->dwNumAddrs = strtoul(ptr, &endPtr, 10); + ptr = endPtr; + } + } + } + fclose(fp); + } + return NO_ERROR; +} + +static DWORD getNumWithOneHeader(const char *filename) +{ + FILE *fp; + int ret = 0; + + fp = fopen(filename, "r"); + if (fp) { + char buf[512] = { 0 }, *ptr; + + + ptr = fgets(buf, sizeof(buf), fp); + if (ptr) { + do { + ptr = fgets(buf, sizeof(buf), fp); + if (ptr) + ret++; + } while (ptr); + } + fclose(fp); + } + return ret; +} + +DWORD getNumRoutes(void) +{ + return getNumWithOneHeader("/proc/net/route"); +} + +RouteTable *getRouteTable(void) +{ + DWORD numRoutes = getNumRoutes(); + RouteTable *ret; + + ret = (RouteTable *)calloc(1, sizeof(RouteTable) + + (numRoutes - 1) * sizeof(RouteEntry)); + if (ret) { + FILE *fp; + + /* get from /proc/net/route, no error if can't */ + fp = fopen("/proc/net/route", "r"); + if (fp) { + char buf[512] = { 0 }, *ptr; + + /* skip header line */ + ptr = fgets(buf, sizeof(buf), fp); + while (ptr && ret->numRoutes < numRoutes) { + ptr = fgets(buf, sizeof(buf), fp); + if (ptr) { + DWORD index; + + while (!isspace(*ptr)) + ptr++; + *ptr = '\0'; + ptr++; + if (getInterfaceIndexByName(buf, &index) == NO_ERROR) { + char *endPtr; + + ret->routes[ret->numRoutes].ifIndex = index; + if (*ptr) { + ret->routes[ret->numRoutes].dest = strtoul(ptr, &endPtr, 16); + ptr = endPtr; + } + if (ptr && *ptr) { + ret->routes[ret->numRoutes].gateway = strtoul(ptr, &endPtr, 16); + ptr = endPtr; + } + if (ptr && *ptr) { + strtoul(ptr, &endPtr, 16); /* flags, skip */ + ptr = endPtr; + } + if (ptr && *ptr) { + strtoul(ptr, &endPtr, 16); /* refcount, skip */ + ptr = endPtr; + } + if (ptr && *ptr) { + strtoul(ptr, &endPtr, 16); /* use, skip */ + ptr = endPtr; + } + if (ptr && *ptr) { + ret->routes[ret->numRoutes].metric = strtoul(ptr, &endPtr, 16); + ptr = endPtr; + } + if (ptr && *ptr) { + ret->routes[ret->numRoutes].mask = strtoul(ptr, &endPtr, 16); + ptr = endPtr; + } + ret->numRoutes++; + } + } + } + fclose(fp); + } + } + return ret; +} + +DWORD getNumArpEntries(void) +{ + return getNumWithOneHeader("/proc/net/arp"); +} + +PMIB_IPNETTABLE getArpTable(void) +{ + DWORD numEntries = getNumArpEntries(); + PMIB_IPNETTABLE ret; + + ret = (PMIB_IPNETTABLE)calloc(1, sizeof(MIB_IPNETTABLE) + + (numEntries - 1) * sizeof(MIB_IPNETROW)); + if (ret) { + FILE *fp; + + /* get from /proc/net/arp, no error if can't */ + fp = fopen("/proc/net/arp", "r"); + if (fp) { + char buf[512] = { 0 }, *ptr; + + /* skip header line */ + ptr = fgets(buf, sizeof(buf), fp); + while (ptr && ret->dwNumEntries < numEntries) { + ptr = fgets(buf, sizeof(buf), fp); + if (ptr) { + char *endPtr; + + if (ptr && *ptr) { + ret->table[ret->dwNumEntries].dwAddr = strtoul(ptr, &endPtr, 16); + ptr = endPtr; + } + if (ptr && *ptr) { + strtoul(ptr, &endPtr, 16); /* hw type (skip) */ + ptr = endPtr; + } + if (ptr && *ptr) { + strtoul(ptr, &endPtr, 16); /* flags (skip) */ + ptr = endPtr; + } + /* FIXME: maybe this comes from flags? */ + ret->table[ret->dwNumEntries].dwType = MIB_IPNET_TYPE_DYNAMIC; + while (ptr && *ptr && isspace(*ptr)) + ptr++; + while (ptr && *ptr && !isspace(*ptr)) { + DWORD byte = strtoul(ptr, &endPtr, 16); + + if (endPtr && *endPtr) { + endPtr++; + ret->table[ret->dwNumEntries].bPhysAddr[ + ret->table[ret->dwNumEntries].dwPhysAddrLen++] = byte & 0x0ff; + } + ptr = endPtr; + } + if (ptr && *ptr) { + strtoul(ptr, &endPtr, 16); /* mask (skip) */ + ptr = endPtr; + } + getInterfaceIndexByName(ptr, &ret->table[ret->dwNumEntries].dwIndex); + ret->dwNumEntries++; + } + } + fclose(fp); + } + } + return ret; +} + +DWORD getNumUdpEntries(void) +{ + return getNumWithOneHeader("/proc/net/udp"); +} + +PMIB_UDPTABLE getUdpTable(void) +{ + DWORD numEntries = getNumUdpEntries(); + PMIB_UDPTABLE ret; + + ret = (PMIB_UDPTABLE)calloc(1, sizeof(MIB_UDPTABLE) + + (numEntries - 1) * sizeof(MIB_UDPROW)); + if (ret) { + FILE *fp; + + /* get from /proc/net/udp, no error if can't */ + fp = fopen("/proc/net/udp", "r"); + if (fp) { + char buf[512] = { 0 }, *ptr; + + /* skip header line */ + ptr = fgets(buf, sizeof(buf), fp); + while (ptr && ret->dwNumEntries < numEntries) { + ptr = fgets(buf, sizeof(buf), fp); + if (ptr) { + char *endPtr; + + if (ptr && *ptr) { + strtoul(ptr, &endPtr, 16); /* skip */ + ptr = endPtr; + } + if (ptr && *ptr) { + ptr++; + ret->table[ret->dwNumEntries].dwLocalAddr = strtoul(ptr, &endPtr, + 16); + ptr = endPtr; + } + if (ptr && *ptr) { + ptr++; + ret->table[ret->dwNumEntries].dwLocalPort = strtoul(ptr, &endPtr, + 16); + ptr = endPtr; + } + ret->dwNumEntries++; + } + } + fclose(fp); + } + } + return ret; +} + +DWORD getNumTcpEntries(void) +{ + return getNumWithOneHeader("/proc/net/tcp"); +} + +PMIB_TCPTABLE getTcpTable(void) +{ + DWORD numEntries = getNumTcpEntries(); + PMIB_TCPTABLE ret; + + ret = (PMIB_TCPTABLE)calloc(1, sizeof(MIB_TCPTABLE) + + (numEntries - 1) * sizeof(MIB_TCPROW)); + if (ret) { + FILE *fp; + + /* get from /proc/net/tcp, no error if can't */ + fp = fopen("/proc/net/tcp", "r"); + if (fp) { + char buf[512] = { 0 }, *ptr; + + /* skip header line */ + ptr = fgets(buf, sizeof(buf), fp); + while (ptr && ret->dwNumEntries < numEntries) { + ptr = fgets(buf, sizeof(buf), fp); + if (ptr) { + char *endPtr; + + while (ptr && *ptr && *ptr != ':') + ptr++; + if (ptr && *ptr) + ptr++; + if (ptr && *ptr) { + ret->table[ret->dwNumEntries].dwLocalAddr = strtoul(ptr, &endPtr, + 16); + ptr = endPtr; + } + if (ptr && *ptr) { + ptr++; + ret->table[ret->dwNumEntries].dwLocalPort = strtoul(ptr, &endPtr, + 16); + ptr = endPtr; + } + if (ptr && *ptr) { + ret->table[ret->dwNumEntries].dwRemoteAddr = strtoul(ptr, &endPtr, + 16); + ptr = endPtr; + } + if (ptr && *ptr) { + ptr++; + ret->table[ret->dwNumEntries].dwRemotePort = strtoul(ptr, &endPtr, + 16); + ptr = endPtr; + } + if (ptr && *ptr) { + DWORD state = strtoul(ptr, &endPtr, 16); + +#if HAVE_NETINET_TCP_H + switch (state) + { + case TCP_ESTABLISHED: + ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_ESTAB; + break; + case TCP_SYN_SENT: + ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_SYN_SENT; + break; + case TCP_SYN_RECV: + ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_SYN_RCVD; + break; + case TCP_FIN_WAIT1: + ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_FIN_WAIT1; + break; + case TCP_FIN_WAIT2: + ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_FIN_WAIT2; + break; + case TCP_TIME_WAIT: + ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_TIME_WAIT; + break; + case TCP_CLOSE: + ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_CLOSED; + break; + case TCP_CLOSE_WAIT: + ret->table[ret->dwNumEntries].dwState = + MIB_TCP_STATE_CLOSE_WAIT; + break; + case TCP_LAST_ACK: + ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_LAST_ACK; + break; + case TCP_LISTEN: + ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_LISTEN; + break; + case TCP_CLOSING: + ret->table[ret->dwNumEntries].dwState = MIB_TCP_STATE_CLOSING; + break; + + } +#endif + ptr = endPtr; + } + ret->dwNumEntries++; + } + } + fclose(fp); + } + } + return ret; +} diff --git a/dlls/iphlpapi/ipstats.h b/dlls/iphlpapi/ipstats.h new file mode 100644 index 00000000000..de9fbce518c --- /dev/null +++ b/dlls/iphlpapi/ipstats.h @@ -0,0 +1,102 @@ +/* ipstats.h + * Copyright (C) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This module implements functions shared by DLLs that need to get network- + * related statistics. It's meant to hide some platform-specificisms, and + * share code that was previously duplicated. + */ +#ifndef WINE_IPSTATS_H_ +#define WINE_IPSTATS_H_ + +#include "windef.h" +#include "iprtrmib.h" + +/* Fills in entry's interface stats, using name to find them. + * Returns ERROR_INVALID_PARAMETER if name or entry is NULL, NO_ERROR otherwise. + */ +DWORD getInterfaceStatsByName(const char *name, PMIB_IFROW entry); + +/* Gets ICMP statistics into stats. Returns ERROR_INVALID_PARAMETER if stats is + * NULL, NO_ERROR otherwise. + */ +DWORD getICMPStats(MIB_ICMP *stats); + +/* Gets IP statistics into stats. Returns ERROR_INVALID_PARAMETER if stats is + * NULL, NO_ERROR otherwise. + */ +DWORD getIPStats(PMIB_IPSTATS stats); + +/* Gets TCP statistics into stats. Returns ERROR_INVALID_PARAMETER if stats is + * NULL, NO_ERROR otherwise. + */ +DWORD getTCPStats(MIB_TCPSTATS *stats); + +/* Gets UDP statistics into stats. Returns ERROR_INVALID_PARAMETER if stats is + * NULL, NO_ERROR otherwise. + */ +DWORD getUDPStats(MIB_UDPSTATS *stats); + +/* Route table functions */ + +DWORD getNumRoutes(void); + +/* Minimalist route entry, only has the fields I can actually fill in. How + * these map to the different windows route data structures is up to you. + */ +typedef struct _RouteEntry { + DWORD dest; + DWORD mask; + DWORD gateway; + DWORD ifIndex; + DWORD metric; +} RouteEntry; + +typedef struct _RouteTable { + DWORD numRoutes; + RouteEntry routes[1]; +} RouteTable; + +/* Allocates and returns to you the route table, or NULL if it can't allocate + * enough memory. free() the returned table. + */ +RouteTable *getRouteTable(void); + +/* Returns the number of entries in the arp table. */ +DWORD getNumArpEntries(void); + +/* Allocates and returns to you the arp table, or NULL if it can't allocate + * enough memory. free() the returned table. + */ +PMIB_IPNETTABLE getArpTable(void); + +/* Returns the number of entries in the UDP state table. */ +DWORD getNumUdpEntries(void); + +/* Allocates and returns to you the UDP state table, or NULL if it can't + * allocate enough memory. free() the returned table. + */ +PMIB_UDPTABLE getUdpTable(void); + +/* Returns the number of entries in the TCP state table. */ +DWORD getNumTcpEntries(void); + +/* Allocates and returns to you the TCP state table, or NULL if it can't + * allocate enough memory. free() the returned table. + */ +PMIB_TCPTABLE getTcpTable(void); + +#endif /* ndef WINE_IPSTATS_H_ */ diff --git a/include/Makefile.in b/include/Makefile.in index 070f20d5783..a2f64dd6192 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -68,6 +68,10 @@ WINDOWS_INCLUDES = \ initguid.h \ instance.h \ ipexport.h \ + iphlpapi.h \ + ipifcons.h \ + iprtrmib.h \ + iptypes.h \ lm.h \ lmaccess.h \ lmapibuf.h \ diff --git a/include/config.h.in b/include/config.h.in index 41d0fe6a1c2..6fadc146b49 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -335,12 +335,27 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_IP_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_TCP_FSM_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETINET_TCP_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_ARP_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_DL_H + /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_H +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_IF_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NET_ROUTE_H + /* Define to use glibc NPTL threading support. */ #undef HAVE_NPTL diff --git a/include/ipexport.h b/include/ipexport.h index 31de4b1e21e..09a989dbf7f 100644 --- a/include/ipexport.h +++ b/include/ipexport.h @@ -96,4 +96,21 @@ typedef struct icmp_echo_reply ICMP_ECHO_REPLY, *PICMP_ECHO_REPLY; #define IP_PENDING (IP_STATUS_BASE + 255) +#define MAX_ADAPTER_NAME 128 + +typedef struct _IP_ADAPTER_INDEX_MAP { + ULONG Index; + WCHAR Name[MAX_ADAPTER_NAME]; +} IP_ADAPTER_INDEX_MAP, *PIP_ADAPTER_INDEX_MAP; + +typedef struct _IP_INTERFACE_INFO { + LONG NumAdapters; + IP_ADAPTER_INDEX_MAP Adapter[1]; +} IP_INTERFACE_INFO,*PIP_INTERFACE_INFO; + +typedef struct _IP_UNIDIRECTIONAL_ADAPTER_ADDRESS { + ULONG NumAdapters; + IPAddr Address[1]; +} IP_UNIDIRECTIONAL_ADAPTER_ADDRESS, *PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS; + #endif /* __WINE_IPEXPORT_H */ diff --git a/include/iphlpapi.h b/include/iphlpapi.h new file mode 100644 index 00000000000..594fd91c353 --- /dev/null +++ b/include/iphlpapi.h @@ -0,0 +1,138 @@ +/* WINE iphlpapi.h + * Copyright (C) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef WINE_IPHLPAPI_H__ +#define WINE_IPHLPAPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +DWORD WINAPI GetNumberOfInterfaces(PDWORD pdwNumIf); + +DWORD WINAPI GetIfEntry(PMIB_IFROW pIfRow); + +DWORD WINAPI GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder); + +DWORD WINAPI GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize, + BOOL bOrder); + +DWORD WINAPI GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize, + BOOL bOrder); + +DWORD WINAPI GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, + PULONG pdwSize, BOOL bOrder); + +DWORD WINAPI GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder); + +DWORD WINAPI GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder); + +DWORD WINAPI GetIpStatistics(PMIB_IPSTATS pStats); + +DWORD WINAPI GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily); + +DWORD WINAPI GetIcmpStatistics(PMIB_ICMP pStats); + +DWORD WINAPI GetTcpStatistics(PMIB_TCPSTATS pStats); + +DWORD WINAPI GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily); + +DWORD WINAPI GetUdpStatistics(PMIB_UDPSTATS pStats); + +DWORD WINAPI GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily); + +DWORD WINAPI SetIfEntry(PMIB_IFROW pIfRow); + +DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute); + +DWORD WINAPI SetIpForwardEntry(PMIB_IPFORWARDROW pRoute); + +DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute); + +DWORD WINAPI SetIpStatistics(PMIB_IPSTATS pIpStats); + +DWORD WINAPI SetIpTTL(UINT nTTL); + +DWORD WINAPI CreateIpNetEntry(PMIB_IPNETROW pArpEntry); + +DWORD WINAPI SetIpNetEntry(PMIB_IPNETROW pArpEntry); + +DWORD WINAPI DeleteIpNetEntry(PMIB_IPNETROW pArpEntry); + +DWORD WINAPI FlushIpNetTable(DWORD dwIfIndex); + +DWORD WINAPI CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask, + DWORD dwIfIndex); + +DWORD WINAPI DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask, + DWORD dwIfIndex); + +DWORD WINAPI SetTcpEntry(PMIB_TCPROW pTcpRow); + +DWORD WINAPI GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG dwOutBufLen); + +DWORD WINAPI GetUniDirectionalAdapterInfo( + PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen); + +DWORD WINAPI GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex); + +DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, + PMIB_IPFORWARDROW pBestRoute); + +DWORD WINAPI NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped); + +DWORD WINAPI NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped); + +DWORD WINAPI GetAdapterIndex(IN LPWSTR AdapterName, OUT PULONG IfIndex); + +DWORD WINAPI AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, + PULONG NTEContext, PULONG NTEInstance); + +DWORD WINAPI DeleteIPAddress(ULONG NTEContext); + +DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen); + +DWORD WINAPI GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen); + +DWORD WINAPI GetPerAdapterInfo(ULONG IfIndex, + PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen); + +DWORD WINAPI IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo); + +DWORD WINAPI IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo); + +DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, + PULONG PhyAddrLen); + +BOOL WINAPI GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, + ULONG MaxHops, PULONG RTT); + +DWORD WINAPI GetFriendlyIfIndex(DWORD IfIndex); + +DWORD WINAPI EnableRouter(HANDLE* pHandle, OVERLAPPED* pOverlapped); + +DWORD WINAPI UnenableRouter(OVERLAPPED* pOverlapped, LPDWORD lpdwEnableCount); + +#ifdef __cplusplus +} +#endif + +#endif /* WINE_IPHLPAPI_H__ */ diff --git a/include/ipifcons.h b/include/ipifcons.h new file mode 100644 index 00000000000..76a2453b882 --- /dev/null +++ b/include/ipifcons.h @@ -0,0 +1,40 @@ +/* WINE ipifcons.h + * Copyright (C) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef WINE_IPIFCONS_H__ +#define WINE_IPIFCONS_H__ + +#define MIB_IF_TYPE_OTHER 1 +#define MIB_IF_TYPE_ETHERNET 6 +#define MIB_IF_TYPE_TOKENRING 9 +#define MIB_IF_TYPE_FDDI 15 +#define MIB_IF_TYPE_PPP 23 +#define MIB_IF_TYPE_LOOPBACK 24 +#define MIB_IF_TYPE_SLIP 28 + +#define MIB_IF_ADMIN_STATUS_UP 1 +#define MIB_IF_ADMIN_STATUS_DOWN 2 +#define MIB_IF_ADMIN_STATUS_TESTING 3 + +#define MIB_IF_OPER_STATUS_NON_OPERATIONAL 0 +#define MIB_IF_OPER_STATUS_UNREACHABLE 1 +#define MIB_IF_OPER_STATUS_DISCONNECTED 2 +#define MIB_IF_OPER_STATUS_CONNECTING 3 +#define MIB_IF_OPER_STATUS_CONNECTED 4 +#define MIB_IF_OPER_STATUS_OPERATIONAL 5 + +#endif /* WINE_ROUTING_IPIFCONS_H__ */ diff --git a/include/iprtrmib.h b/include/iprtrmib.h new file mode 100644 index 00000000000..7644cf70f1a --- /dev/null +++ b/include/iprtrmib.h @@ -0,0 +1,276 @@ +/* WINE iprtrmib.h + * Copyright (C) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef WINE_IPRTRMIB_H__ +#define WINE_IPRTRMIB_H__ + +#define MAX_INTERFACE_NAME_LEN 256 + +#include + +#define MAXLEN_IFDESCR 256 +#define MAXLEN_PHYSADDR 8 + +typedef struct _MIB_IFROW +{ + WCHAR wszName[MAX_INTERFACE_NAME_LEN]; + DWORD dwIndex; + DWORD dwType; + DWORD dwMtu; + DWORD dwSpeed; + DWORD dwPhysAddrLen; + BYTE bPhysAddr[MAXLEN_PHYSADDR]; + DWORD dwAdminStatus; + DWORD dwOperStatus; + DWORD dwLastChange; + DWORD dwInOctets; + DWORD dwInUcastPkts; + DWORD dwInNUcastPkts; + DWORD dwInDiscards; + DWORD dwInErrors; + DWORD dwInUnknownProtos; + DWORD dwOutOctets; + DWORD dwOutUcastPkts; + DWORD dwOutNUcastPkts; + DWORD dwOutDiscards; + DWORD dwOutErrors; + DWORD dwOutQLen; + DWORD dwDescrLen; + BYTE bDescr[MAXLEN_IFDESCR]; +} MIB_IFROW,*PMIB_IFROW; + +typedef struct _MIB_IFTABLE +{ + DWORD dwNumEntries; + MIB_IFROW table[1]; +} MIB_IFTABLE, *PMIB_IFTABLE; + +typedef struct _MIBICMPSTATS +{ + DWORD dwMsgs; + DWORD dwErrors; + DWORD dwDestUnreachs; + DWORD dwTimeExcds; + DWORD dwParmProbs; + DWORD dwSrcQuenchs; + DWORD dwRedirects; + DWORD dwEchos; + DWORD dwEchoReps; + DWORD dwTimestamps; + DWORD dwTimestampReps; + DWORD dwAddrMasks; + DWORD dwAddrMaskReps; +} MIBICMPSTATS; + +typedef struct _MIBICMPINFO +{ + MIBICMPSTATS icmpInStats; + MIBICMPSTATS icmpOutStats; +} MIBICMPINFO; + +typedef struct _MIB_ICMP +{ + MIBICMPINFO stats; +} MIB_ICMP,*PMIB_ICMP; + +typedef struct _MIB_UDPSTATS +{ + DWORD dwInDatagrams; + DWORD dwNoPorts; + DWORD dwInErrors; + DWORD dwOutDatagrams; + DWORD dwNumAddrs; +} MIB_UDPSTATS,*PMIB_UDPSTATS; + +typedef struct _MIB_UDPROW +{ + DWORD dwLocalAddr; + DWORD dwLocalPort; +} MIB_UDPROW, *PMIB_UDPROW; + +typedef struct _MIB_UDPTABLE +{ + DWORD dwNumEntries; + MIB_UDPROW table[1]; +} MIB_UDPTABLE, *PMIB_UDPTABLE; + +typedef struct _MIB_TCPSTATS +{ + DWORD dwRtoAlgorithm; + DWORD dwRtoMin; + DWORD dwRtoMax; + DWORD dwMaxConn; + DWORD dwActiveOpens; + DWORD dwPassiveOpens; + DWORD dwAttemptFails; + DWORD dwEstabResets; + DWORD dwCurrEstab; + DWORD dwInSegs; + DWORD dwOutSegs; + DWORD dwRetransSegs; + DWORD dwInErrs; + DWORD dwOutRsts; + DWORD dwNumConns; +} MIB_TCPSTATS, *PMIB_TCPSTATS; + +typedef struct _MIB_TCPROW +{ + DWORD dwState; + DWORD dwLocalAddr; + DWORD dwLocalPort; + DWORD dwRemoteAddr; + DWORD dwRemotePort; +} MIB_TCPROW, *PMIB_TCPROW; + +#define MIB_TCP_STATE_CLOSED 1 +#define MIB_TCP_STATE_LISTEN 2 +#define MIB_TCP_STATE_SYN_SENT 3 +#define MIB_TCP_STATE_SYN_RCVD 4 +#define MIB_TCP_STATE_ESTAB 5 +#define MIB_TCP_STATE_FIN_WAIT1 6 +#define MIB_TCP_STATE_FIN_WAIT2 7 +#define MIB_TCP_STATE_CLOSE_WAIT 8 +#define MIB_TCP_STATE_CLOSING 9 +#define MIB_TCP_STATE_LAST_ACK 10 +#define MIB_TCP_STATE_TIME_WAIT 11 +#define MIB_TCP_STATE_DELETE_TCB 12 + +typedef struct _MIB_TCPTABLE +{ + DWORD dwNumEntries; + MIB_TCPROW table[1]; +} MIB_TCPTABLE, *PMIB_TCPTABLE; + +typedef struct _MIB_IPSTATS +{ + DWORD dwForwarding; + DWORD dwDefaultTTL; + DWORD dwInReceives; + DWORD dwInHdrErrors; + DWORD dwInAddrErrors; + DWORD dwForwDatagrams; + DWORD dwInUnknownProtos; + DWORD dwInDiscards; + DWORD dwInDelivers; + DWORD dwOutRequests; + DWORD dwRoutingDiscards; + DWORD dwOutDiscards; + DWORD dwOutNoRoutes; + DWORD dwReasmTimeout; + DWORD dwReasmReqds; + DWORD dwReasmOks; + DWORD dwReasmFails; + DWORD dwFragOks; + DWORD dwFragFails; + DWORD dwFragCreates; + DWORD dwNumIf; + DWORD dwNumAddr; + DWORD dwNumRoutes; +} MIB_IPSTATS, *PMIB_IPSTATS; + +typedef struct _MIB_IPADDRROW +{ + DWORD dwAddr; + DWORD dwIndex; + DWORD dwMask; + DWORD dwBCastAddr; + DWORD dwReasmSize; + unsigned short unused1; + unsigned short wType; +} MIB_IPADDRROW, *PMIB_IPADDRROW; + +typedef struct _MIB_IPADDRTABLE +{ + DWORD dwNumEntries; + MIB_IPADDRROW table[1]; +} MIB_IPADDRTABLE, *PMIB_IPADDRTABLE; + + +typedef struct _MIB_IPFORWARDNUMBER +{ + DWORD dwValue; +}MIB_IPFORWARDNUMBER,*PMIB_IPFORWARDNUMBER; + +typedef struct _MIB_IPFORWARDROW +{ + DWORD dwForwardDest; + DWORD dwForwardMask; + DWORD dwForwardPolicy; + DWORD dwForwardNextHop; + DWORD dwForwardIfIndex; + DWORD dwForwardType; + DWORD dwForwardProto; + DWORD dwForwardAge; + DWORD dwForwardNextHopAS; + DWORD dwForwardMetric1; + DWORD dwForwardMetric2; + DWORD dwForwardMetric3; + DWORD dwForwardMetric4; + DWORD dwForwardMetric5; +}MIB_IPFORWARDROW, *PMIB_IPFORWARDROW; + +#define MIB_IPROUTE_TYPE_OTHER 1 +#define MIB_IPROUTE_TYPE_INVALID 2 +#define MIB_IPROUTE_TYPE_DIRECT 3 +#define MIB_IPROUTE_TYPE_INDIRECT 4 + +#define MIB_IPPROTO_OTHER 1 +#define MIB_IPPROTO_LOCAL 2 +#define MIB_IPPROTO_NETMGMT 3 +#define MIB_IPPROTO_ICMP 4 +#define MIB_IPPROTO_EGP 5 +#define MIB_IPPROTO_GGP 6 +#define MIB_IPPROTO_HELLO 7 +#define MIB_IPPROTO_RIP 8 +#define MIB_IPPROTO_IS_IS 9 +#define MIB_IPPROTO_ES_IS 10 +#define MIB_IPPROTO_CISCO 11 +#define MIB_IPPROTO_BBN 12 +#define MIB_IPPROTO_OSPF 13 +#define MIB_IPPROTO_BGP 14 + +#define MIB_IPPROTO_NT_AUTOSTATIC 10002 +#define MIB_IPPROTO_NT_STATIC 10006 +#define MIB_IPPROTO_NT_STATIC_NON_DOD 10007 + +typedef struct _MIB_IPFORWARDTABLE +{ + DWORD dwNumEntries; + MIB_IPFORWARDROW table[1]; +} MIB_IPFORWARDTABLE, *PMIB_IPFORWARDTABLE; + +typedef struct _MIB_IPNETROW +{ + DWORD dwIndex; + DWORD dwPhysAddrLen; + BYTE bPhysAddr[MAXLEN_PHYSADDR]; + DWORD dwAddr; + DWORD dwType; +} MIB_IPNETROW, *PMIB_IPNETROW; + +#define MIB_IPNET_TYPE_OTHER 1 +#define MIB_IPNET_TYPE_INVALID 2 +#define MIB_IPNET_TYPE_DYNAMIC 3 +#define MIB_IPNET_TYPE_STATIC 4 + +typedef struct _MIB_IPNETTABLE +{ + DWORD dwNumEntries; + MIB_IPNETROW table[1]; +} MIB_IPNETTABLE, *PMIB_IPNETTABLE; + +#endif /* WINE_IPRTRMIB_H__ */ diff --git a/include/iptypes.h b/include/iptypes.h new file mode 100644 index 00000000000..3265ae38ff6 --- /dev/null +++ b/include/iptypes.h @@ -0,0 +1,87 @@ +/* WINE iptypes.h + * Copyright (C) 2003 Juan Lang + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef WINE_IPTYPES_H_ +#define WINE_IPTYPES_H_ + +#include + +#define MAX_ADAPTER_DESCRIPTION_LENGTH 128 +#define MAX_ADAPTER_NAME_LENGTH 256 +#define MAX_ADAPTER_ADDRESS_LENGTH 8 +#define MAX_HOSTNAME_LEN 128 +#define MAX_DOMAIN_NAME_LEN 128 +#define MAX_SCOPE_ID_LEN 256 + +#define BROADCAST_NODETYPE 1 +#define PEER_TO_PEER_NODETYPE 2 +#define MIXED_NODETYPE 4 +#define HYBRID_NODETYPE 8 + +typedef struct { + char String[4 * 4]; +} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING; + +typedef struct _IP_ADDR_STRING { + struct _IP_ADDR_STRING* Next; + IP_ADDRESS_STRING IpAddress; + IP_MASK_STRING IpMask; + DWORD Context; +} IP_ADDR_STRING, *PIP_ADDR_STRING; + +typedef struct _IP_ADAPTER_INFO { + struct _IP_ADAPTER_INFO* Next; + DWORD ComboIndex; + char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4]; + char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4]; + UINT AddressLength; + BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH]; + DWORD Index; + UINT Type; + UINT DhcpEnabled; + PIP_ADDR_STRING CurrentIpAddress; + IP_ADDR_STRING IpAddressList; + IP_ADDR_STRING GatewayList; + IP_ADDR_STRING DhcpServer; + BOOL HaveWins; + IP_ADDR_STRING PrimaryWinsServer; + IP_ADDR_STRING SecondaryWinsServer; + time_t LeaseObtained; + time_t LeaseExpires; +} IP_ADAPTER_INFO, *PIP_ADAPTER_INFO; + +typedef struct _IP_PER_ADAPTER_INFO { + UINT AutoconfigEnabled; + UINT AutoconfigActive; + PIP_ADDR_STRING CurrentDnsServer; + IP_ADDR_STRING DnsServerList; +} IP_PER_ADAPTER_INFO, *PIP_PER_ADAPTER_INFO; + +typedef struct { + char HostName[MAX_HOSTNAME_LEN + 4] ; + char DomainName[MAX_DOMAIN_NAME_LEN + 4]; + PIP_ADDR_STRING CurrentDnsServer; + IP_ADDR_STRING DnsServerList; + UINT NodeType; + char ScopeId[MAX_SCOPE_ID_LEN + 4]; + UINT EnableRouting; + UINT EnableProxy; + UINT EnableDns; +} FIXED_INFO, *PFIXED_INFO; + +#endif /* WINE_IPTYPES_H_*/ -- 2.11.4.GIT