├── .gitattributes ├── .gitignore ├── Win7Release └── tdi_fw.lib ├── adfilter.sln └── sys ├── adfilter ├── adfilter.inf ├── adfilter.vcxproj ├── adfilter.vcxproj.filters └── src │ └── adfilter.c └── tdi_fw ├── src ├── conn_state.c ├── conn_state.h ├── disp_conn.c ├── disp_dg.c ├── disp_ev.c ├── disp_obj.c ├── disp_sr.c ├── dispatch.c ├── dispatch.h ├── ev_conn.c ├── ev_dg.c ├── ev_recv.c ├── events.c ├── events.h ├── filter.c ├── filter.h ├── ipc.c ├── ipc.h ├── memtrack.c ├── memtrack.h ├── ndis_hk_ioctl.h ├── net.h ├── obj_tbl.c ├── obj_tbl.h ├── packet.c ├── packet.h ├── pid_pname.c ├── pid_pname.h ├── sids.c ├── sids.h ├── sock.c ├── sock.h ├── tdi_fw.c ├── tdi_fw.h └── tdi_fw_lib.h ├── tdi_fw.inf ├── tdi_fw.vcxproj └── tdi_fw.vcxproj.filters /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.sln.docstates 8 | 9 | # Build results 10 | [Dd]ebug/ 11 | [Rr]elease/ 12 | build/ 13 | [Bb]in/ 14 | [Oo]bj/ 15 | [Ww]in7Debug/ 16 | 17 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 18 | !packages/*/build/ 19 | 20 | # MSTest test Results 21 | [Tt]est[Rr]esult*/ 22 | [Bb]uild[Ll]og.* 23 | 24 | *_i.c 25 | *_p.c 26 | *.ilk 27 | *.meta 28 | *.obj 29 | *.pch 30 | *.pdb 31 | *.pgc 32 | *.pgd 33 | *.rsp 34 | *.sbr 35 | *.tlb 36 | *.tli 37 | *.tlh 38 | *.tmp 39 | *.tmp_proj 40 | *.log 41 | *.vspscc 42 | *.vssscc 43 | .builds 44 | *.pidb 45 | *.log 46 | *.scc 47 | 48 | # Visual C++ cache files 49 | ipch/ 50 | *.aps 51 | *.ncb 52 | *.opensdf 53 | *.sdf 54 | *.cachefile 55 | 56 | # Visual Studio profiler 57 | *.psess 58 | *.vsp 59 | *.vspx 60 | 61 | # Guidance Automation Toolkit 62 | *.gpState 63 | 64 | # ReSharper is a .NET coding add-in 65 | _ReSharper*/ 66 | *.[Rr]e[Ss]harper 67 | 68 | # TeamCity is a build add-in 69 | _TeamCity* 70 | 71 | # DotCover is a Code Coverage Tool 72 | *.dotCover 73 | 74 | # NCrunch 75 | *.ncrunch* 76 | .*crunch*.local.xml 77 | 78 | # Installshield output folder 79 | [Ee]xpress/ 80 | 81 | # DocProject is a documentation generator add-in 82 | DocProject/buildhelp/ 83 | DocProject/Help/*.HxT 84 | DocProject/Help/*.HxC 85 | DocProject/Help/*.hhc 86 | DocProject/Help/*.hhk 87 | DocProject/Help/*.hhp 88 | DocProject/Help/Html2 89 | DocProject/Help/html 90 | 91 | # Click-Once directory 92 | publish/ 93 | 94 | # Publish Web Output 95 | *.Publish.xml 96 | 97 | # NuGet Packages Directory 98 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 99 | #packages/ 100 | 101 | # Windows Azure Build Output 102 | csx 103 | *.build.csdef 104 | 105 | # Windows Store app package directory 106 | AppPackages/ 107 | 108 | # Others 109 | sql/ 110 | *.Cache 111 | ClientBin/ 112 | [Ss]tyle[Cc]op.* 113 | ~$* 114 | *~ 115 | *.dbmdl 116 | *.[Pp]ublish.xml 117 | *.pfx 118 | *.publishsettings 119 | 120 | # RIA/Silverlight projects 121 | Generated_Code/ 122 | 123 | # Backup & report files from converting an old project file to a newer 124 | # Visual Studio version. Backup files are not needed, because we have git ;-) 125 | _UpgradeReport_Files/ 126 | Backup*/ 127 | UpgradeLog*.XML 128 | UpgradeLog*.htm 129 | 130 | # SQL Server files 131 | App_Data/*.mdf 132 | App_Data/*.ldf 133 | 134 | 135 | #LightSwitch generated files 136 | GeneratedArtifacts/ 137 | _Pvt_Extensions/ 138 | ModelManifest.xml 139 | 140 | # ========================= 141 | # Windows detritus 142 | # ========================= 143 | 144 | # Windows image file caches 145 | Thumbs.db 146 | ehthumbs.db 147 | 148 | # Folder config file 149 | Desktop.ini 150 | 151 | # Recycle Bin used on file shares 152 | $RECYCLE.BIN/ 153 | 154 | # Mac desktop service store files 155 | .DS_Store 156 | 157 | 158 | *.sln.ide 159 | *.exe.config 160 | build/ 161 | !lib/**/*.dll 162 | lib/*/plugins/plugins.dat -------------------------------------------------------------------------------- /Win7Release/tdi_fw.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue-blood/tdifw/f5c22cab34535034218a6d8fd45cb3a6af7434d9/Win7Release/tdi_fw.lib -------------------------------------------------------------------------------- /adfilter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.40629.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adfilter", "sys\adfilter\adfilter.vcxproj", "{5671BBFE-6F3E-455E-B3F0-A993DDA2856A}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tdi_fw", "sys\tdi_fw\tdi_fw.vcxproj", "{E41842B6-3E8B-476C-AA59-BBC98BCFA547}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Win7 Debug|Win32 = Win7 Debug|Win32 13 | Win7 Debug|x64 = Win7 Debug|x64 14 | Win7 Release|Win32 = Win7 Release|Win32 15 | Win7 Release|x64 = Win7 Release|x64 16 | Win8 Debug|Win32 = Win8 Debug|Win32 17 | Win8 Debug|x64 = Win8 Debug|x64 18 | Win8 Release|Win32 = Win8 Release|Win32 19 | Win8 Release|x64 = Win8 Release|x64 20 | Win8.1 Debug|Win32 = Win8.1 Debug|Win32 21 | Win8.1 Debug|x64 = Win8.1 Debug|x64 22 | Win8.1 Release|Win32 = Win8.1 Release|Win32 23 | Win8.1 Release|x64 = Win8.1 Release|x64 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Debug|Win32.ActiveCfg = Win7 Debug|Win32 27 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Debug|Win32.Build.0 = Win7 Debug|Win32 28 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Debug|Win32.Deploy.0 = Win7 Debug|Win32 29 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64 30 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Debug|x64.Build.0 = Win7 Debug|x64 31 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64 32 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32 33 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Release|Win32.Build.0 = Win7 Release|Win32 34 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32 35 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 36 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Release|x64.Build.0 = Win7 Release|x64 37 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win7 Release|x64.Deploy.0 = Win7 Release|x64 38 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 39 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 40 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 41 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 42 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 43 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64 44 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32 45 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Release|Win32.Build.0 = Win8 Release|Win32 46 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32 47 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 48 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Release|x64.Build.0 = Win8 Release|x64 49 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 50 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 51 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 52 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 53 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 54 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 55 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 56 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 57 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 58 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 59 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 60 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 61 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 62 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Debug|Win32.ActiveCfg = Win7 Release|Win32 63 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Debug|Win32.Build.0 = Win7 Release|Win32 64 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Debug|Win32.Deploy.0 = Win7 Release|Win32 65 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Debug|x64.ActiveCfg = Win7 Debug|x64 66 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Debug|x64.Build.0 = Win7 Debug|x64 67 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Debug|x64.Deploy.0 = Win7 Debug|x64 68 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Release|Win32.ActiveCfg = Win7 Release|Win32 69 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Release|Win32.Build.0 = Win7 Release|Win32 70 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Release|Win32.Deploy.0 = Win7 Release|Win32 71 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Release|x64.ActiveCfg = Win7 Release|x64 72 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Release|x64.Build.0 = Win7 Release|x64 73 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win7 Release|x64.Deploy.0 = Win7 Release|x64 74 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Debug|Win32.ActiveCfg = Win8 Debug|Win32 75 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Debug|Win32.Build.0 = Win8 Debug|Win32 76 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Debug|Win32.Deploy.0 = Win8 Debug|Win32 77 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 78 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 79 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Debug|x64.Deploy.0 = Win8 Debug|x64 80 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Release|Win32.ActiveCfg = Win8 Release|Win32 81 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Release|Win32.Build.0 = Win8 Release|Win32 82 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Release|Win32.Deploy.0 = Win8 Release|Win32 83 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 84 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Release|x64.Build.0 = Win8 Release|x64 85 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8 Release|x64.Deploy.0 = Win8 Release|x64 86 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Debug|Win32.ActiveCfg = Win8.1 Debug|Win32 87 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Debug|Win32.Build.0 = Win8.1 Debug|Win32 88 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Debug|Win32.Deploy.0 = Win8.1 Debug|Win32 89 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 90 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 91 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Debug|x64.Deploy.0 = Win8.1 Debug|x64 92 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Release|Win32.ActiveCfg = Win8.1 Release|Win32 93 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Release|Win32.Build.0 = Win8.1 Release|Win32 94 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Release|Win32.Deploy.0 = Win8.1 Release|Win32 95 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 96 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 97 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547}.Win8.1 Release|x64.Deploy.0 = Win8.1 Release|x64 98 | EndGlobalSection 99 | GlobalSection(SolutionProperties) = preSolution 100 | HideSolutionNode = FALSE 101 | EndGlobalSection 102 | EndGlobal 103 | -------------------------------------------------------------------------------- /sys/adfilter/adfilter.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; adfilter.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class= 8 | ClassGuid= 9 | Provider= 10 | DriverVer= 11 | CatalogFile= 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | 17 | [SourceDisksNames] 18 | 1 = %DiskName%,,,"" 19 | 20 | [SourceDisksFiles] 21 | 22 | 23 | [Manufacturer] 24 | %ManufacturerName%=Standard,NT$ARCH$ 25 | 26 | [Standard.NT$ARCH$] 27 | 28 | 29 | [Strings] 30 | ManufacturerName="" 31 | ClassName="" 32 | DiskName="adfilter Source Disk" 33 | -------------------------------------------------------------------------------- /sys/adfilter/adfilter.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Win8.1 Debug 6 | Win32 7 | 8 | 9 | Win8.1 Release 10 | Win32 11 | 12 | 13 | Win8 Debug 14 | Win32 15 | 16 | 17 | Win8 Release 18 | Win32 19 | 20 | 21 | Win7 Debug 22 | Win32 23 | 24 | 25 | Win7 Release 26 | Win32 27 | 28 | 29 | Win8.1 Debug 30 | x64 31 | 32 | 33 | Win8.1 Release 34 | x64 35 | 36 | 37 | Win8 Debug 38 | x64 39 | 40 | 41 | Win8 Release 42 | x64 43 | 44 | 45 | Win7 Debug 46 | x64 47 | 48 | 49 | Win7 Release 50 | x64 51 | 52 | 53 | 54 | {5671BBFE-6F3E-455E-B3F0-A993DDA2856A} 55 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 56 | v4.5 57 | 11.0 58 | Win8.1 Debug 59 | Win32 60 | adfilter 61 | 62 | 63 | 64 | WindowsV6.3 65 | true 66 | WindowsKernelModeDriver8.1 67 | Driver 68 | WDM 69 | 70 | 71 | WindowsV6.3 72 | false 73 | WindowsKernelModeDriver8.1 74 | Driver 75 | WDM 76 | 77 | 78 | Windows8 79 | true 80 | WindowsKernelModeDriver8.1 81 | Driver 82 | WDM 83 | 84 | 85 | Windows8 86 | false 87 | WindowsKernelModeDriver8.1 88 | Driver 89 | WDM 90 | 91 | 92 | Windows7 93 | true 94 | WindowsKernelModeDriver8.1 95 | Driver 96 | WDM 97 | 98 | 99 | Windows7 100 | false 101 | WindowsKernelModeDriver8.1 102 | Driver 103 | WDM 104 | 105 | 106 | WindowsV6.3 107 | true 108 | WindowsKernelModeDriver8.1 109 | Driver 110 | WDM 111 | 112 | 113 | WindowsV6.3 114 | false 115 | WindowsKernelModeDriver8.1 116 | Driver 117 | WDM 118 | 119 | 120 | Windows8 121 | true 122 | WindowsKernelModeDriver8.1 123 | Driver 124 | WDM 125 | 126 | 127 | Windows8 128 | false 129 | WindowsKernelModeDriver8.1 130 | Driver 131 | WDM 132 | 133 | 134 | Windows7 135 | true 136 | WindowsKernelModeDriver8.1 137 | Driver 138 | WDM 139 | 140 | 141 | Windows7 142 | false 143 | WindowsKernelModeDriver8.1 144 | Driver 145 | WDM 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | DbgengKernelDebugger 157 | 158 | 159 | DbgengKernelDebugger 160 | 161 | 162 | DbgengKernelDebugger 163 | 164 | 165 | DbgengKernelDebugger 166 | 167 | 168 | DbgengKernelDebugger 169 | $(SolutionDir)sys\tdi_fw\src\;$(IncludePath) 170 | $(SolutionDir)sys\tdi_fw\bin\;$(LibraryPath) 171 | 172 | 173 | DbgengKernelDebugger 174 | 175 | 176 | DbgengKernelDebugger 177 | 178 | 179 | DbgengKernelDebugger 180 | 181 | 182 | DbgengKernelDebugger 183 | 184 | 185 | DbgengKernelDebugger 186 | 187 | 188 | DbgengKernelDebugger 189 | 190 | 191 | DbgengKernelDebugger 192 | 193 | 194 | 195 | Level3 196 | 197 | 198 | 199 | 200 | false 201 | 202 | 203 | tdi.lib;tdi_fw.lib;%(AdditionalDependencies) 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /sys/adfilter/adfilter.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | -------------------------------------------------------------------------------- /sys/adfilter/src/adfilter.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xue-blood/tdifw/f5c22cab34535034218a6d8fd45cb3a6af7434d9/sys/adfilter/src/adfilter.c -------------------------------------------------------------------------------- /sys/tdi_fw/src/conn_state.h: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 2 | // 3 | // $Id: conn_state.h,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 4 | 5 | #ifndef _conn_state_h_ 6 | #define _conn_state_h_ 7 | 8 | #include "ipc.h" 9 | 10 | NTSTATUS conn_state_init(void); 11 | void conn_state_free(void); 12 | 13 | /* work with listening ports for all protocols */ 14 | 15 | NTSTATUS add_listen(struct ot_entry *ote_addr); 16 | 17 | void del_listen_obj(struct listen_entry *le, BOOLEAN no_guard); 18 | 19 | BOOLEAN is_listen(ULONG addr, USHORT port, int ipproto); 20 | 21 | BOOLEAN is_bcast_listen(ULONG addr, USHORT port, int ipproto); 22 | 23 | NTSTATUS enum_listen(struct listen_nfo *buf, ULONG *buf_len, ULONG buf_size); 24 | 25 | /* work with TCP only connections */ 26 | 27 | NTSTATUS add_tcp_conn(struct ot_entry *ote_conn, int tcp_state); 28 | void del_tcp_conn(PFILE_OBJECT connobj, BOOLEAN is_disconnect); 29 | 30 | void del_tcp_conn_obj(struct conn_entry *ce, BOOLEAN no_guard); 31 | void log_disconnect(struct ot_entry *ote_conn); 32 | 33 | NTSTATUS set_tcp_conn_state(PFILE_OBJECT connobj, int state); 34 | NTSTATUS set_tcp_conn_local(PFILE_OBJECT connobj, TA_ADDRESS *local); 35 | 36 | int get_tcp_conn_state(ULONG laddr, USHORT lport, ULONG raddr, USHORT rport); 37 | int get_tcp_conn_state_by_obj(PFILE_OBJECT connobj); 38 | 39 | NTSTATUS enum_tcp_conn(struct tcp_conn_nfo *buf, ULONG *buf_len, ULONG buf_size); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/disp_conn.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: disp_conn.c,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 14 | 15 | /* 16 | * This file contains TDI_CONNECT & TDI_DISCONNECT handlers 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "conn_state.h" 24 | #include "dispatch.h" 25 | #include "events.h" 26 | #include "memtrack.h" 27 | #include "obj_tbl.h" 28 | #include "sids.h" 29 | #include "tdi_fw.h" 30 | 31 | struct delayed_ucn_param { 32 | WORK_QUEUE_ITEM item; 33 | PDEVICE_OBJECT devobj; 34 | PFILE_OBJECT fileobj; 35 | }; 36 | 37 | struct uci_param { 38 | PFILE_OBJECT connobj; 39 | char address[]; 40 | }; 41 | 42 | static void delayed_ucn(PVOID p); 43 | static NTSTATUS update_conn_info_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); 44 | 45 | 46 | static NTSTATUS tdi_connect_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); 47 | static NTSTATUS tdi_disconnect_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); 48 | 49 | //---------------------------------------------------------------------------- 50 | 51 | /* 52 | * TDI_CONNECT handler 53 | */ 54 | 55 | int 56 | tdi_connect(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 57 | { 58 | PTDI_REQUEST_KERNEL_CONNECT param = (PTDI_REQUEST_KERNEL_CONNECT)(&irps->Parameters); 59 | TA_ADDRESS *remote_addr = ((TRANSPORT_ADDRESS *)(param->RequestConnectionInformation->RemoteAddress))->Address; 60 | PFILE_OBJECT addrobj; 61 | NTSTATUS status; 62 | TA_ADDRESS *local_addr; 63 | int result = FILTER_DENY, ipproto; 64 | struct ot_entry *ote_conn = NULL, *ote_addr; 65 | KIRQL irql; 66 | struct flt_request request; 67 | struct flt_rule rule; 68 | 69 | memset(&request, 0, sizeof(request)); 70 | 71 | KdPrint(("[tdi_fw] tdi_connect: connobj 0x%x, to address %x:%u\n", 72 | irps->FileObject, 73 | ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), 74 | ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port))); 75 | 76 | // check device object: TCP or UDP 77 | if (irps->DeviceObject != g_tcpfltobj && irps->DeviceObject != g_udpfltobj) { 78 | KdPrint(("[tdi_fw] tdi_connect: unknown DeviceObject 0x%x!\n", irps->DeviceObject)); 79 | goto done; 80 | } 81 | 82 | ote_conn = ot_find_fileobj(irps->FileObject, &irql); 83 | if (ote_conn == NULL) { 84 | KdPrint(("[tdi_fw] tdi_connect: ot_find_fileobj(0x%x)!\n", irps->FileObject)); 85 | goto done; 86 | } 87 | 88 | if (get_original_devobj(irps->DeviceObject, &ipproto) == NULL || 89 | (ipproto != IPPROTO_TCP && ipproto != IPPROTO_UDP)) { 90 | // invalid device object! 91 | KdPrint(("[tdi_fw] tdi_connect: invalid device object 0x%x!\n", irps->DeviceObject)); 92 | goto done; 93 | } 94 | 95 | if (ipproto == IPPROTO_TCP) { 96 | /* 97 | * For TCP: get addrobj by connobj and get local address by it 98 | */ 99 | 100 | addrobj = ote_conn->associated_fileobj; 101 | if (addrobj == NULL) { 102 | KdPrint(("[tdi_fw] tdi_connect: empty addrobj!\n")); 103 | goto done; 104 | } 105 | 106 | ote_addr = ot_find_fileobj(addrobj, NULL); // we're already in spinlock 107 | if (ote_addr == NULL) { 108 | KdPrint(("[tdi_fw] tdi_connect: ot_find_fileobj(0x%x)!\n", addrobj)); 109 | goto done; 110 | } 111 | 112 | } else { 113 | /* 114 | * For UDP: connobj and addrobj are the same 115 | */ 116 | KdPrint(("[tdi_fw] tdi_connect: connected UDP socket detected\n")); 117 | 118 | // for connected UDP sockets connobj and addrobj are the same 119 | addrobj= irps->FileObject; 120 | ote_addr = ote_conn; 121 | } 122 | 123 | local_addr = (TA_ADDRESS *)(ote_addr->local_addr); 124 | 125 | // sanity check 126 | if (local_addr->AddressLength != remote_addr->AddressLength) { 127 | KdPrint(("[tdi_fw] tdi_connect: different addr lengths! (%u != %u)\n", 128 | local_addr->AddressLength, remote_addr->AddressLength)); 129 | goto done; 130 | } 131 | 132 | // set remote address with connobj 133 | 134 | if (remote_addr->AddressLength > sizeof(ote_conn->remote_addr)) { 135 | KdPrint(("[tdi_fw] tdi_connect: address too long! (%u)\n", remote_addr->AddressLength)); 136 | goto done; 137 | } 138 | memcpy(ote_conn->remote_addr, remote_addr, remote_addr->AddressLength); 139 | 140 | // set local address with connobj 141 | 142 | if (local_addr->AddressLength > sizeof(ote_conn->local_addr)) { 143 | KdPrint(("[tdi_fw] tdi_connect: address to long! (%u)\n", local_addr->AddressLength)); 144 | goto done; 145 | } 146 | memcpy(ote_conn->local_addr, local_addr, local_addr->AddressLength); 147 | 148 | KdPrint(("[tdi_fw] tdi_connect(pid:%u/%u): %x:%u -> %x:%u (ipproto = %d)\n", 149 | ote_conn->pid, PsGetCurrentProcessId(), 150 | ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr), 151 | ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port), 152 | ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), 153 | ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port), ipproto)); 154 | 155 | /* 156 | * Call quick_filter 157 | */ 158 | 159 | request.struct_size = sizeof(request); 160 | 161 | request.type = TYPE_CONNECT; 162 | request.direction = DIRECTION_OUT; 163 | request.proto = ipproto; 164 | 165 | // don't use ote_conn->pid because one process can create connection object 166 | // but another one can connect 167 | request.pid = (ULONG)PsGetCurrentProcessId(); 168 | if (request.pid == 0) { 169 | // avoid idle process pid (XXX do we need this?) 170 | request.pid = ote_addr->pid; 171 | } 172 | 173 | // get user SID & attributes (can't call get_current_sid_a at DISPATCH_LEVEL) 174 | if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL) 175 | request.sid_a_size = ote_addr->sid_a_size; 176 | 177 | memcpy(&request.addr.from, &local_addr->AddressType, sizeof(struct sockaddr)); 178 | memcpy(&request.addr.to, &remote_addr->AddressType, sizeof(struct sockaddr)); 179 | request.addr.len = sizeof(struct sockaddr_in); 180 | 181 | memset(&rule, 0, sizeof(rule)); 182 | 183 | result = quick_filter(&request, &rule); 184 | 185 | memcpy(request.log_rule_id, rule.rule_id, RULE_ID_SIZE); 186 | 187 | if (result == FILTER_ALLOW && ipproto == IPPROTO_TCP) { 188 | struct flt_request *context_req = NULL; 189 | 190 | // add connection with state "SYN_SENT" 191 | status = add_tcp_conn(ote_conn, TCP_STATE_SYN_SENT); 192 | if (status != STATUS_SUCCESS) { 193 | KdPrint(("[tdi_fw] tdi_connect: add_conn: 0x%x!\n", status)); 194 | 195 | result = FILTER_DENY; 196 | goto done; // don't log this failure 197 | } 198 | 199 | if (rule.log >= RULE_LOG_LOG) { 200 | // set ote_conn->log_disconnect 201 | ote_conn->log_disconnect = (rule.log >= RULE_LOG_COUNT); 202 | 203 | // copy request for completion (LOG success or not) 204 | context_req = (struct flt_request *)malloc_np(sizeof(*context_req)); 205 | if (context_req != NULL) { 206 | memcpy(context_req, &request, sizeof(*context_req)); 207 | 208 | // don't free SID 209 | request.sid_a = NULL; 210 | 211 | // don't log request in this time 212 | rule.log = RULE_LOG_NOLOG; 213 | } 214 | } 215 | 216 | // set completion to add connection info to connection table 217 | completion->routine = tdi_connect_complete; 218 | completion->context = context_req; 219 | } 220 | 221 | // if logging is needed log request 222 | if (rule.log >= RULE_LOG_LOG) 223 | log_request(&request); 224 | 225 | done: 226 | // cleanup 227 | if (ote_conn != NULL) 228 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 229 | if (request.sid_a != NULL) 230 | free(request.sid_a); 231 | 232 | if (result != FILTER_ALLOW) { 233 | irp->IoStatus.Status = STATUS_REMOTE_NOT_LISTENING; // set fake status 234 | } 235 | 236 | return result; 237 | } 238 | 239 | NTSTATUS 240 | tdi_connect_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 241 | { 242 | NTSTATUS status; 243 | struct flt_request *request = (struct flt_request *)Context; 244 | PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(Irp); 245 | 246 | KdPrint(("[tdi_fw] tdi_connect_complete: status 0x%x\n", Irp->IoStatus.Status)); 247 | 248 | if (Irp->IoStatus.Status == STATUS_SUCCESS) { 249 | 250 | if (request != NULL) 251 | log_request(request); // log successful connection 252 | 253 | // very good! set connection state to "ESTABLISHED" 254 | status = set_tcp_conn_state(irps->FileObject, TCP_STATE_ESTABLISHED_OUT); 255 | if (status != STATUS_SUCCESS) { 256 | KdPrint(("[tdi_fw] tdi_connect_complete: set_tcp_conn_state: 0x%x!\n", status)); 257 | 258 | // set fake status 259 | Irp->IoStatus.Status = STATUS_REMOTE_NOT_LISTENING; 260 | // TDI client will close connection object and connection will not "hang" (maybe) 261 | goto done; 262 | } 263 | 264 | // and update local address for this connection in state table 265 | update_conn_info(DeviceObject, irps->FileObject); 266 | 267 | } else { 268 | 269 | if (request != NULL) { 270 | 271 | switch (Irp->IoStatus.Status) { // are status codes correct? 272 | case STATUS_CONNECTION_REFUSED: 273 | case STATUS_CONNECTION_RESET: 274 | request->type = TYPE_CONNECT_RESET; 275 | break; 276 | case STATUS_CONNECTION_ABORTED: 277 | case STATUS_CANCELLED: 278 | request->type = TYPE_CONNECT_CANCELED; 279 | break; 280 | case STATUS_IO_TIMEOUT: 281 | request->type = TYPE_CONNECT_TIMEOUT; 282 | break; 283 | case STATUS_NETWORK_UNREACHABLE: 284 | case STATUS_HOST_UNREACHABLE: 285 | case STATUS_PROTOCOL_UNREACHABLE: 286 | case STATUS_PORT_UNREACHABLE: 287 | request->type = TYPE_CONNECT_UNREACH; 288 | break; 289 | default: 290 | request->type = TYPE_CONNECT_ERROR; 291 | } 292 | 293 | // anyway save status 294 | request->status = Irp->IoStatus.Status; 295 | 296 | log_request(request); 297 | } 298 | 299 | del_tcp_conn(irps->FileObject, FALSE); 300 | } 301 | 302 | done: 303 | if (request != NULL) { 304 | if (request->sid_a != NULL) 305 | free(request->sid_a); 306 | free(request); 307 | } 308 | return tdi_generic_complete(DeviceObject, Irp, Context); 309 | } 310 | 311 | void 312 | delayed_ucn(PVOID p) 313 | { 314 | struct delayed_ucn_param *ucn_param = (struct delayed_ucn_param *)p; 315 | 316 | update_conn_info(ucn_param->devobj, ucn_param->fileobj); 317 | 318 | free(ucn_param); 319 | } 320 | 321 | /* query local address and port for connection */ 322 | void 323 | update_conn_info(PDEVICE_OBJECT devobj, PFILE_OBJECT connobj) 324 | { 325 | PIRP query_irp; 326 | PMDL mdl = NULL; 327 | struct uci_param *uci_param = NULL; 328 | 329 | // MUST be executed at PASSIVE_LEVEL 330 | 331 | if (KeGetCurrentIrql() != PASSIVE_LEVEL) { 332 | // do it a bit later :-) 333 | struct delayed_ucn_param *ucn_param = (struct delayed_ucn_param *)malloc_np(sizeof(*ucn_param)); 334 | if (ucn_param != NULL) { 335 | 336 | memset(ucn_param, 0, sizeof(*ucn_param)); 337 | 338 | ucn_param->devobj = devobj; 339 | ucn_param->fileobj = connobj; 340 | 341 | ExInitializeWorkItem(&ucn_param->item, delayed_ucn, ucn_param); 342 | ExQueueWorkItem(&ucn_param->item, DelayedWorkQueue); // DelayedWorkQueue a good value? 343 | 344 | } else { 345 | KdPrint(("[ndis_hk] tdi_connect_complete: malloc_np!\n")); 346 | // so we'll live without known local address :-( 347 | } 348 | return; 349 | } 350 | 351 | // we're at PASSIVE_LEVEL 352 | 353 | query_irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION, devobj, connobj, NULL, NULL); 354 | if (query_irp == NULL) { 355 | KdPrint(("[tdi_fw] update_conn_info: TdiBuildInternalDeviceControlIrp!\n")); 356 | goto done; 357 | } 358 | 359 | uci_param = (struct uci_param *)malloc_np(sizeof(*uci_param) + TDI_ADDRESS_INFO_MAX); 360 | if (uci_param == NULL) { 361 | KdPrint(("[tdi_fw] update_conn_info: malloc_np!\n")); 362 | goto done; 363 | } 364 | 365 | memset(uci_param, 0, sizeof(*uci_param) + TDI_ADDRESS_INFO_MAX); 366 | uci_param->connobj = connobj; 367 | 368 | mdl = IoAllocateMdl(uci_param->address, TDI_ADDRESS_INFO_MAX, FALSE, FALSE, NULL); 369 | if (mdl == NULL) { 370 | KdPrint(("[tdi_fw] update_conn_info: IoAllocateMdl!\n")); 371 | goto done; 372 | } 373 | MmBuildMdlForNonPagedPool(mdl); 374 | 375 | TdiBuildQueryInformation(query_irp, devobj, connobj, 376 | update_conn_info_complete, uci_param, 377 | TDI_QUERY_ADDRESS_INFO, mdl); 378 | 379 | IoCallDriver(devobj, query_irp); 380 | 381 | query_irp = NULL; 382 | mdl = NULL; 383 | uci_param = NULL; 384 | 385 | done: 386 | // cleanup 387 | if (mdl != NULL) 388 | IoFreeMdl(mdl); 389 | if (uci_param != NULL) 390 | ExFreePool(uci_param); 391 | if (query_irp != NULL) 392 | IoCompleteRequest(query_irp, IO_NO_INCREMENT); 393 | } 394 | 395 | NTSTATUS 396 | update_conn_info_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 397 | { 398 | struct uci_param *param = (struct uci_param *)Context; 399 | TA_ADDRESS *addr = ((TDI_ADDRESS_INFO *)(param->address))->Address.Address; 400 | NTSTATUS status; 401 | 402 | status = set_tcp_conn_local(param->connobj, addr); 403 | if (status != STATUS_SUCCESS) 404 | KdPrint(("[tdi_fw] update_conn_info_complete: set_tcp_conn_local: 0x%x!\n", status)); 405 | 406 | // cleanup MDL to avoid unlocking pages from NonPaged pool 407 | if (Irp->MdlAddress != NULL) { 408 | IoFreeMdl(Irp->MdlAddress); 409 | Irp->MdlAddress = NULL; 410 | } 411 | 412 | free(param); 413 | return STATUS_SUCCESS; 414 | } 415 | 416 | //---------------------------------------------------------------------------- 417 | 418 | /* 419 | * TDI_DISCONNECT handler 420 | */ 421 | 422 | int 423 | tdi_disconnect(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 424 | { 425 | TDI_REQUEST_KERNEL_DISCONNECT *param = (TDI_REQUEST_KERNEL_DISCONNECT *)(&irps->Parameters); 426 | 427 | KdPrint(("[tdi_fw] tdi_disconnect: connobj 0x%x (flags: 0x%x)\n", 428 | irps->FileObject, param->RequestFlags)); 429 | 430 | if (param->RequestFlags & TDI_DISCONNECT_RELEASE) { 431 | int state = get_tcp_conn_state_by_obj(irps->FileObject), new_state; 432 | 433 | if (state == TCP_STATE_ESTABLISHED_IN || state == TCP_STATE_ESTABLISHED_OUT) 434 | new_state = TCP_STATE_FIN_WAIT1; 435 | else if (state == TCP_STATE_CLOSE_WAIT) 436 | new_state = TCP_STATE_LAST_ACK; 437 | else 438 | KdPrint(("[tdi_fw] tdi_disconnect: weird conn state: %d\n", state)); 439 | 440 | set_tcp_conn_state(irps->FileObject, new_state); 441 | 442 | completion->routine = tdi_disconnect_complete; 443 | completion->context = (PVOID)new_state; 444 | 445 | } else { 446 | 447 | // set TCP_STATE_CLOSED and delete object in completion 448 | 449 | set_tcp_conn_state(irps->FileObject, TCP_STATE_CLOSED); 450 | 451 | completion->routine = tdi_disconnect_complete; 452 | completion->context = (PVOID)TCP_STATE_CLOSED; 453 | 454 | } 455 | 456 | return FILTER_ALLOW; 457 | } 458 | 459 | NTSTATUS 460 | tdi_disconnect_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 461 | { 462 | PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(Irp); 463 | int state = (int)Context; 464 | 465 | KdPrint(("[tdi_fw] tdi_disconnect_complete: connobj 0x%x; status: 0x%x\n", 466 | irps->FileObject, Irp->IoStatus.Status)); 467 | 468 | if (Irp->IoStatus.Status == STATUS_SUCCESS) { 469 | 470 | // update TCP state table 471 | 472 | if (state == TCP_STATE_FIN_WAIT1) 473 | set_tcp_conn_state(irps->FileObject, TCP_STATE_FIN_WAIT2); 474 | else if (state == TCP_STATE_LAST_ACK) 475 | del_tcp_conn(irps->FileObject, TRUE); 476 | else if (state == TCP_STATE_CLOSED) 477 | del_tcp_conn(irps->FileObject, TRUE); 478 | else 479 | KdPrint(("[tdi_fw] tdi_disconnect_complete: weird conn state: %d\n", state)); 480 | } 481 | 482 | return tdi_generic_complete(DeviceObject, Irp, Context); 483 | } 484 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/disp_dg.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: disp_dg.c,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 14 | 15 | /* 16 | * This file contains TDI_SEND_DATAGRAM and TDI_RECEIVE_DATAGRAM handlers 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "dispatch.h" 24 | #include "filter.h" 25 | #include "memtrack.h" 26 | #include "obj_tbl.h" 27 | #include "sids.h" 28 | #include "tdi_fw.h" 29 | 30 | static NTSTATUS tdi_receive_datagram_complete( 31 | IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); 32 | 33 | 34 | //---------------------------------------------------------------------------- 35 | 36 | /* 37 | * TDI_SEND_DATAGRAM handler 38 | */ 39 | 40 | int 41 | tdi_send_datagram(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 42 | { 43 | TDI_REQUEST_KERNEL_SENDDG *param = (TDI_REQUEST_KERNEL_SENDDG *)(&irps->Parameters); 44 | TA_ADDRESS *local_addr, *remote_addr; 45 | NTSTATUS status; 46 | struct ot_entry *ote_addr = NULL; 47 | KIRQL irql; 48 | int result = FILTER_DENY, ipproto; 49 | struct flt_request request; 50 | struct flt_rule rule; 51 | 52 | memset(&request, 0, sizeof(request)); 53 | 54 | // check device object: UDP or RawIP 55 | if (get_original_devobj(irps->DeviceObject, &ipproto) == NULL || 56 | (ipproto != IPPROTO_UDP && ipproto != IPPROTO_IP)) { 57 | // unknown device object! 58 | KdPrint(("[tdi_fw] tdi_send_datagram: unknown DeviceObject 0x%x!\n", 59 | irps->DeviceObject)); 60 | goto done; 61 | } 62 | 63 | // get local address of address object 64 | 65 | ote_addr = ot_find_fileobj(irps->FileObject, &irql); 66 | if (ote_addr == NULL) { 67 | KdPrint(("[tdi_fw] tdi_send_datagram: ot_find_fileobj(0x%x)!\n", irps->FileObject)); 68 | #if DBG 69 | // address object was created before driver was started 70 | result = FILTER_ALLOW; 71 | #endif 72 | goto done; 73 | } 74 | 75 | KdPrint(("[tdi_fw] tdi_send_datagram: addrobj 0x%x (size: %u)\n", irps->FileObject, 76 | param->SendLength)); 77 | 78 | local_addr = (TA_ADDRESS *)(ote_addr->local_addr); 79 | remote_addr = ((TRANSPORT_ADDRESS *)(param->SendDatagramInformation->RemoteAddress))->Address; 80 | 81 | KdPrint(("[tdi_fw] tdi_send_datagram(pid:%u/%u): %x:%u -> %x:%u\n", 82 | ote_addr->pid, PsGetCurrentProcessId(), 83 | ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr), 84 | ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port), 85 | ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), 86 | ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port))); 87 | 88 | request.struct_size = sizeof(request); 89 | 90 | request.type = TYPE_DATAGRAM; 91 | request.direction = DIRECTION_OUT; 92 | request.proto = ipproto; 93 | 94 | // don't use ote_addr->pid because one process can create address object 95 | // but another one can send datagram on it 96 | request.pid = (ULONG)PsGetCurrentProcessId(); 97 | if (request.pid == 0) { 98 | // some NetBT datagrams are sent in context of idle process: avoid it 99 | request.pid = ote_addr->pid; 100 | } 101 | 102 | // get user SID & attributes (can't call get_current_sid_a at DISPATCH_LEVEL) 103 | if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL) 104 | request.sid_a_size = ote_addr->sid_a_size; 105 | 106 | memcpy(&request.addr.from, &local_addr->AddressType, sizeof(struct sockaddr)); 107 | memcpy(&request.addr.to, &remote_addr->AddressType, sizeof(struct sockaddr)); 108 | request.addr.len = sizeof(struct sockaddr_in); 109 | 110 | memset(&rule, 0, sizeof(rule)); 111 | 112 | result = quick_filter(&request, &rule); 113 | 114 | memcpy(request.log_rule_id, rule.rule_id, RULE_ID_SIZE); 115 | 116 | if (rule.log >= RULE_LOG_LOG) { 117 | ULONG bytes = param->SendLength; 118 | 119 | // traffic stats 120 | KeAcquireSpinLockAtDpcLevel(&g_traffic_guard); 121 | 122 | g_traffic[TRAFFIC_TOTAL_OUT] += bytes; 123 | 124 | if (rule.log >= RULE_LOG_COUNT) { 125 | request.log_bytes_out = bytes; 126 | 127 | g_traffic[TRAFFIC_COUNTED_OUT] += bytes; 128 | 129 | } else 130 | request.log_bytes_out = (ULONG)-1; 131 | 132 | KeReleaseSpinLockFromDpcLevel(&g_traffic_guard); 133 | 134 | log_request(&request); 135 | } 136 | 137 | done: 138 | 139 | // cleanup 140 | if (ote_addr != NULL) 141 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 142 | if (request.sid_a != NULL) 143 | free(request.sid_a); 144 | 145 | if (result == FILTER_DENY) 146 | irp->IoStatus.Status = STATUS_INVALID_ADDRESS; // set fake status 147 | 148 | return result; 149 | } 150 | 151 | //---------------------------------------------------------------------------- 152 | 153 | /* 154 | * TDI_RECEIVE_DATAGRAM handler 155 | */ 156 | 157 | int 158 | tdi_receive_datagram(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 159 | { 160 | KdPrint(("[tdi_fw] tdi_receive_datagram: addrobj 0x%x\n", irps->FileObject)); 161 | 162 | completion->routine = tdi_receive_datagram_complete; 163 | 164 | return FILTER_ALLOW; 165 | } 166 | 167 | NTSTATUS 168 | tdi_receive_datagram_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 169 | { 170 | PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(Irp); 171 | TDI_REQUEST_KERNEL_RECEIVEDG *param = (TDI_REQUEST_KERNEL_RECEIVEDG *)(&irps->Parameters); 172 | PFILE_OBJECT addrobj = irps->FileObject; 173 | struct ot_entry *ote_addr = NULL; 174 | KIRQL irql; 175 | int result = FILTER_DENY, ipproto; 176 | NTSTATUS status = STATUS_SUCCESS; 177 | struct flt_request request; 178 | struct flt_rule rule; 179 | TA_ADDRESS *local_addr, *remote_addr; 180 | 181 | memset(&request, 0, sizeof(request)); 182 | 183 | // check device object: UDP or RawIP 184 | if (get_original_devobj(DeviceObject, &ipproto) == NULL || 185 | (ipproto != IPPROTO_UDP && ipproto != IPPROTO_IP)) { 186 | // unknown device object! 187 | KdPrint(("[tdi_fw] tdi_receive_datagram_complete: unknown DeviceObject 0x%x!\n", 188 | DeviceObject)); 189 | status = STATUS_UNSUCCESSFUL; 190 | goto done; 191 | } 192 | 193 | KdPrint(("[tdi_fw] tdi_receive_datagram_complete: addrobj 0x%x; status 0x%x; information %u\n", 194 | addrobj, Irp->IoStatus.Status, Irp->IoStatus.Information)); 195 | 196 | if (Irp->IoStatus.Status != STATUS_SUCCESS) { 197 | KdPrint(("[tdi_fw] tdi_receive_datagram_complete: status 0x%x\n", 198 | Irp->IoStatus.Status)); 199 | status = Irp->IoStatus.Status; 200 | goto done; 201 | } 202 | 203 | ote_addr = ot_find_fileobj(addrobj, &irql); 204 | if (ote_addr == NULL) { 205 | KdPrint(("[tdi_fw] tdi_receive_datagram_complete: ot_find_fileobj(0x%x)!\n", 206 | addrobj)); 207 | status = STATUS_UNSUCCESSFUL; 208 | goto done; 209 | } 210 | 211 | request.struct_size = sizeof(request); 212 | 213 | request.type = TYPE_DATAGRAM; 214 | request.direction = DIRECTION_IN; 215 | request.proto = ipproto; 216 | request.pid = ote_addr->pid; 217 | 218 | // get user SID & attributes! 219 | if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL) 220 | request.sid_a_size = ote_addr->sid_a_size; 221 | 222 | local_addr = (TA_ADDRESS *)(ote_addr->local_addr); 223 | remote_addr = ((TRANSPORT_ADDRESS *)(param->ReceiveDatagramInformation->RemoteAddress))->Address; 224 | 225 | KdPrint(("[tdi_fw] tdi_receive_datagram_complete(pid:%u): %x:%u -> %x:%u\n", 226 | ote_addr->pid, 227 | ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), 228 | ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port), 229 | ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr), 230 | ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port))); 231 | 232 | memcpy(&request.addr.from, &remote_addr->AddressType, sizeof(struct sockaddr)); 233 | memcpy(&request.addr.to, &local_addr->AddressType, sizeof(struct sockaddr)); 234 | request.addr.len = sizeof(struct sockaddr_in); 235 | 236 | memset(&rule, 0, sizeof(rule)); 237 | 238 | result = quick_filter(&request, &rule); 239 | 240 | memcpy(request.log_rule_id, rule.rule_id, RULE_ID_SIZE); 241 | 242 | if (rule.log >= RULE_LOG_LOG) { 243 | ULONG bytes = Irp->IoStatus.Information; 244 | 245 | // traffic stats 246 | KeAcquireSpinLockAtDpcLevel(&g_traffic_guard); 247 | 248 | g_traffic[TRAFFIC_TOTAL_IN] += bytes; 249 | 250 | if (rule.log >= RULE_LOG_COUNT) { 251 | request.log_bytes_in = bytes; 252 | 253 | g_traffic[TRAFFIC_COUNTED_IN] += bytes; 254 | 255 | } else 256 | request.log_bytes_in = (ULONG)-1; 257 | 258 | KeReleaseSpinLockFromDpcLevel(&g_traffic_guard); 259 | 260 | log_request(&request); 261 | } 262 | 263 | done: 264 | // convert result to NTSTATUS 265 | if (result == FILTER_ALLOW) 266 | status = STATUS_SUCCESS; 267 | else { /* FILTER_DENY */ 268 | 269 | if (status == STATUS_SUCCESS) 270 | status = Irp->IoStatus.Status = STATUS_ACCESS_DENIED; // good status? 271 | 272 | } 273 | 274 | // cleanup 275 | if (ote_addr != NULL) 276 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 277 | if (request.sid_a != NULL) 278 | free(request.sid_a); 279 | 280 | return tdi_generic_complete(DeviceObject, Irp, Context); 281 | } 282 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/disp_ev.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: disp_ev.c,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 14 | 15 | /* 16 | * This file contains TDI_SET_EVENT_HANDLER handler 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "conn_state.h" 24 | #include "dispatch.h" 25 | #include "events.h" 26 | #include "memtrack.h" 27 | #include "obj_tbl.h" 28 | #include "sids.h" 29 | #include "tdi_fw.h" 30 | 31 | int 32 | tdi_set_event_handler(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 33 | { 34 | PTDI_REQUEST_KERNEL_SET_EVENT r = (PTDI_REQUEST_KERNEL_SET_EVENT)&irps->Parameters; 35 | NTSTATUS status; 36 | struct ot_entry *ote_addr = NULL; 37 | KIRQL irql; 38 | int result = FILTER_DENY; 39 | TDI_EVENT_CONTEXT *ctx; 40 | 41 | KdPrint(("[tdi_fw] tdi_set_event_handler: [%s] devobj 0x%x; addrobj 0x%x; EventType: %d\n", 42 | r->EventHandler ? "(+)ADD" : "(-)REMOVE", 43 | irps->DeviceObject, 44 | irps->FileObject, 45 | r->EventType)); 46 | 47 | ote_addr = ot_find_fileobj(irps->FileObject, &irql); 48 | if (ote_addr == NULL) { 49 | KdPrint(("[tdi_fw] tdi_set_event_handler: ot_find_fileobj(0x%x)\n", irps->FileObject)); 50 | if (r->EventHandler == NULL) { 51 | // for fileobjects loaded earlier than our driver allow removing 52 | result = FILTER_ALLOW; 53 | } 54 | goto done; 55 | } 56 | 57 | if (r->EventType < 0 || r->EventType >= MAX_EVENT) { 58 | KdPrint(("[tdi_fw] tdi_set_event_handler: unknown EventType %d!\n", r->EventType)); 59 | result = FILTER_ALLOW; 60 | goto done; 61 | } 62 | 63 | ctx = &ote_addr->ctx[r->EventType]; 64 | 65 | if (r->EventHandler != NULL) { 66 | /* add EventHandler */ 67 | int i; 68 | 69 | for (i = 0; g_tdi_event_handlers[i].event != (ULONG)-1; i++) 70 | if (g_tdi_event_handlers[i].event == r->EventType) 71 | break; 72 | 73 | if (g_tdi_event_handlers[i].event == (ULONG)-1) { 74 | KdPrint(("[tdi_fw] tdi_set_event_handler: unknown EventType %d!\n", r->EventType)); 75 | result = FILTER_ALLOW; 76 | goto done; 77 | } 78 | 79 | ctx->old_handler = r->EventHandler; 80 | ctx->old_context = r->EventContext; 81 | 82 | if (g_tdi_event_handlers[i].handler != NULL) { 83 | r->EventHandler = g_tdi_event_handlers[i].handler; 84 | r->EventContext = ctx; 85 | } else { 86 | r->EventHandler = NULL; 87 | r->EventContext = NULL; 88 | } 89 | 90 | KdPrint(("[tdi_fw] tdi_set_event_handler: old_handler 0x%x; old_context 0x%x\n", 91 | r->EventHandler, r->EventContext)); 92 | 93 | } else { 94 | /* remove EventHandler */ 95 | ctx->old_handler = NULL; 96 | ctx->old_context = NULL; 97 | } 98 | 99 | // change LISTEN state 100 | if (r->EventType == TDI_EVENT_CONNECT) { 101 | TA_ADDRESS *local_addr; 102 | 103 | if (r->EventHandler != NULL) { 104 | // add "LISTEN" info 105 | status = add_listen(ote_addr); 106 | if (status != STATUS_SUCCESS) { 107 | KdPrint(("[tdi_fw] tdi_set_event_handler: add_listen: 0x%x!\n", status)); 108 | goto done; 109 | } 110 | } else if (ote_addr->listen_entry != NULL) { 111 | // remove "LISTEN" info 112 | del_listen_obj(ote_addr->listen_entry, FALSE); 113 | 114 | ote_addr->listen_entry = NULL; 115 | } 116 | 117 | // log it if address is not 127.0.0.1 118 | local_addr = (TA_ADDRESS *)(ote_addr->local_addr); 119 | if (ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr) != 0x7f000001) { 120 | struct flt_request request; 121 | 122 | memset(&request, 0, sizeof(request)); 123 | 124 | request.struct_size = sizeof(request); 125 | 126 | request.type = (r->EventHandler != NULL) ? TYPE_LISTEN : TYPE_NOT_LISTEN; 127 | request.proto = IPPROTO_TCP; // correct? 128 | 129 | if (r->EventHandler != NULL) { 130 | // for removing event handler ProcessNotifyProc can be already called 131 | request.pid = (ULONG)PsGetCurrentProcessId(); 132 | if (request.pid == 0) { 133 | // avoid idle process pid (XXX do we need this?) 134 | request.pid = ote_addr->pid; 135 | } 136 | } else 137 | request.pid = (ULONG)-1; 138 | 139 | // get user SID & attributes (can't call get_current_sid_a at DISPATCH_LEVEL) 140 | if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL) 141 | request.sid_a_size = ote_addr->sid_a_size; 142 | 143 | memcpy(&request.addr.from, &local_addr->AddressType, sizeof(struct sockaddr)); 144 | request.addr.len = sizeof(struct sockaddr_in); 145 | 146 | log_request(&request); 147 | 148 | if (request.sid_a != NULL) 149 | free(request.sid_a); 150 | } 151 | } 152 | 153 | result = FILTER_ALLOW; 154 | done: 155 | // cleanup 156 | if (ote_addr != NULL) 157 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 158 | 159 | return result; 160 | } 161 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/disp_obj.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: disp_obj.c,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 14 | 15 | /* 16 | * This file contains TDI_CREATE, TDI_CLEANUP, TDI_ASSOCIATE_ADDRESS and 17 | * TDI_DISASSOCIATE_ADDRESS handlers 18 | */ 19 | 20 | #include 21 | #include 22 | #include "sock.h" 23 | 24 | #include "conn_state.h" 25 | #include "dispatch.h" 26 | #include "events.h" 27 | #include "memtrack.h" 28 | #include "obj_tbl.h" 29 | #include "pid_pname.h" 30 | #include "sids.h" 31 | #include "tdi_fw.h" 32 | 33 | /* IRP completion routines and their contexts */ 34 | 35 | static NTSTATUS tdi_create_addrobj_complete( 36 | IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); 37 | 38 | // context for tdi_create_addrobj_complete2 39 | typedef struct { 40 | TDI_ADDRESS_INFO *tai; /* address info -- result of TDI_QUERY_ADDRESS_INFO */ 41 | PFILE_OBJECT fileobj; /* FileObject from IO_STACK_LOCATION */ 42 | } TDI_CREATE_ADDROBJ2_CTX; 43 | 44 | static NTSTATUS tdi_create_addrobj_complete2( 45 | IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); 46 | 47 | //---------------------------------------------------------------------------- 48 | 49 | /* 50 | * TDI_CREATE handler 51 | */ 52 | 53 | int 54 | tdi_create(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 55 | { 56 | NTSTATUS status; 57 | FILE_FULL_EA_INFORMATION *ea = (FILE_FULL_EA_INFORMATION *)irp->AssociatedIrp.SystemBuffer; 58 | 59 | /* pid resolving stuff: a good place for it (PASSIVE level, begin of working with TDI-objects) */ 60 | ULONG pid = (ULONG)PsGetCurrentProcessId(); 61 | 62 | // if process name is unknown try to resolve it 63 | if (!pid_pname_resolve(pid, NULL, 0)) { 64 | KEVENT event; 65 | struct flt_request request; 66 | 67 | KeInitializeEvent(&event, NotificationEvent, FALSE); 68 | pid_pname_set_event(pid, &event); 69 | 70 | memset(&request, 0, sizeof(request)); 71 | request.struct_size = sizeof(request); 72 | 73 | request.type = TYPE_RESOLVE_PID; 74 | request.pid = pid; 75 | 76 | // get user SID & attributes! 77 | request.sid_a = get_current_sid_a(&request.sid_a_size); 78 | 79 | if (log_request(&request)) { 80 | // wait a little for reply from user-mode application 81 | LARGE_INTEGER li; 82 | li.QuadPart = 5000 * -10000; // 5 sec 83 | 84 | status = KeWaitForSingleObject(&event, UserRequest, KernelMode, FALSE, &li); 85 | 86 | } else { 87 | // check all rulesets: we've got the only _default_ ruleset active 88 | status = default_chain_only() ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 89 | } 90 | 91 | if (request.sid_a != NULL) 92 | free(request.sid_a); 93 | 94 | // reset wait event 95 | pid_pname_set_event(pid, NULL); 96 | 97 | if (status != STATUS_SUCCESS) 98 | return FILTER_DENY; // deny it! 99 | } 100 | 101 | /* TDI_CREATE related stuff */ 102 | 103 | if (ea != NULL) { 104 | /* 105 | * We have FILE_FULL_EA_INFORMATION 106 | */ 107 | 108 | PDEVICE_OBJECT devobj; 109 | int ipproto; 110 | 111 | devobj = get_original_devobj(irps->DeviceObject, &ipproto); 112 | if (devobj == NULL) { 113 | KdPrint(("[tdi_fw] tdi_create: unknown device object 0x%x!\n", irps->DeviceObject)); 114 | return FILTER_DENY; 115 | } 116 | // NOTE: for RawIp you can extract protocol number from irps->FileObject->FileName 117 | 118 | if (ea->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH && 119 | memcmp(ea->EaName, TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH) == 0) { 120 | 121 | PIRP query_irp; 122 | 123 | /* 124 | * This is creation of address object 125 | */ 126 | 127 | KdPrint(("[tdi_fw] tdi_create: devobj 0x%x; addrobj 0x%x\n", 128 | irps->DeviceObject, 129 | irps->FileObject)); 130 | 131 | status = ot_add_fileobj(irps->DeviceObject, irps->FileObject, FILEOBJ_ADDROBJ, ipproto, NULL); 132 | if (status != STATUS_SUCCESS) { 133 | KdPrint(("[tdi_fw] tdi_create: ot_add_fileobj: 0x%x\n", status)); 134 | return FILTER_DENY; 135 | } 136 | 137 | // while we're on PASSIVE_LEVEL build control IRP for completion 138 | query_irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION, 139 | devobj, irps->FileObject, NULL, NULL); 140 | if (query_irp == NULL) { 141 | KdPrint(("[tdi_fw] tdi_create: TdiBuildInternalDeviceControlIrp\n")); 142 | return FILTER_DENY; 143 | } 144 | 145 | /* set IRP completion & context for completion */ 146 | 147 | completion->routine = tdi_create_addrobj_complete; 148 | completion->context = query_irp; 149 | 150 | } else if (ea->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH && 151 | memcmp(ea->EaName, TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH) == 0) { 152 | 153 | /* 154 | * This is creation of connection object 155 | */ 156 | 157 | CONNECTION_CONTEXT conn_ctx = *(CONNECTION_CONTEXT *) 158 | (ea->EaName + ea->EaNameLength + 1); 159 | 160 | KdPrint(("[tdi_fw] tdi_create: devobj 0x%x; connobj 0x%x; conn_ctx 0x%x\n", 161 | irps->DeviceObject, 162 | irps->FileObject, 163 | conn_ctx)); 164 | 165 | status = ot_add_fileobj(irps->DeviceObject, irps->FileObject, 166 | FILEOBJ_CONNOBJ, ipproto, conn_ctx); 167 | 168 | if (status != STATUS_SUCCESS) { 169 | KdPrint(("[tdi_fw] tdi_create: ot_add_fileobj: 0x%x\n", status)); 170 | return FILTER_DENY; 171 | } 172 | } 173 | 174 | } else { 175 | /* 176 | * This is creation of control object 177 | */ 178 | 179 | KdPrint(("[tdi_fw] tdi_create(pid:%u): devobj 0x%x; Control Object: 0x%x\n", 180 | pid, irps->DeviceObject, irps->FileObject)); 181 | } 182 | 183 | return FILTER_ALLOW; 184 | } 185 | 186 | /* this completion routine queries address and port from address object */ 187 | NTSTATUS 188 | tdi_create_addrobj_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 189 | { 190 | NTSTATUS status; 191 | PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(Irp); 192 | PIRP query_irp = (PIRP)Context; 193 | PDEVICE_OBJECT devobj; 194 | TDI_CREATE_ADDROBJ2_CTX *ctx = NULL; 195 | PMDL mdl = NULL; 196 | 197 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete: devobj 0x%x; addrobj 0x%x\n", 198 | DeviceObject, irps->FileObject)); 199 | 200 | if (Irp->IoStatus.Status != STATUS_SUCCESS) { 201 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete: status 0x%x\n", Irp->IoStatus.Status)); 202 | 203 | status = Irp->IoStatus.Status; 204 | goto done; 205 | } 206 | 207 | // query addrobj address:port 208 | 209 | ctx = (TDI_CREATE_ADDROBJ2_CTX *)malloc_np(sizeof(TDI_CREATE_ADDROBJ2_CTX)); 210 | if (ctx == NULL) { 211 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete: malloc_np\n")); 212 | 213 | status = STATUS_INSUFFICIENT_RESOURCES; 214 | goto done; 215 | } 216 | ctx->fileobj = irps->FileObject; 217 | 218 | ctx->tai = (TDI_ADDRESS_INFO *)malloc_np(TDI_ADDRESS_INFO_MAX); 219 | if (ctx->tai == NULL) { 220 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete: malloc_np!\n")); 221 | 222 | status = STATUS_INSUFFICIENT_RESOURCES; 223 | goto done; 224 | } 225 | 226 | mdl = IoAllocateMdl(ctx->tai, TDI_ADDRESS_INFO_MAX, FALSE, FALSE, NULL); 227 | if (mdl == NULL) { 228 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete: IoAllocateMdl!\n")); 229 | 230 | status = STATUS_INSUFFICIENT_RESOURCES; 231 | goto done; 232 | } 233 | MmBuildMdlForNonPagedPool(mdl); 234 | 235 | devobj = get_original_devobj(DeviceObject, NULL); // use original devobj! 236 | if (devobj == NULL) { 237 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete: get_original_devobj!\n")); 238 | 239 | status = STATUS_INVALID_PARAMETER; 240 | goto done; 241 | } 242 | 243 | TdiBuildQueryInformation(query_irp, devobj, irps->FileObject, 244 | tdi_create_addrobj_complete2, ctx, 245 | TDI_QUERY_ADDRESS_INFO, mdl); 246 | 247 | status = IoCallDriver(devobj, query_irp); 248 | query_irp = NULL; 249 | mdl = NULL; 250 | ctx = NULL; 251 | 252 | if (status != STATUS_SUCCESS) { 253 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete: IoCallDriver: 0x%x\n", status)); 254 | goto done; 255 | } 256 | 257 | status = STATUS_SUCCESS; 258 | 259 | done: 260 | // cleanup 261 | if (mdl != NULL) 262 | IoFreeMdl(mdl); 263 | 264 | if (ctx != NULL) { 265 | if (ctx->tai != NULL) 266 | free(ctx->tai); 267 | free(ctx); 268 | } 269 | 270 | if (query_irp != NULL) 271 | IoCompleteRequest(query_irp, IO_NO_INCREMENT); 272 | 273 | Irp->IoStatus.Status = status; 274 | 275 | if (status != STATUS_PENDING) { 276 | // tdi_create failed - remove fileobj from hash 277 | ot_del_fileobj(irps->FileObject, NULL); 278 | } 279 | 280 | return tdi_generic_complete(DeviceObject, Irp, Context); 281 | } 282 | 283 | /* this completion routine gets address and port from reply to TDI_QUERY_ADDRESS_INFO */ 284 | NTSTATUS 285 | tdi_create_addrobj_complete2(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 286 | { 287 | NTSTATUS status; 288 | TDI_CREATE_ADDROBJ2_CTX *ctx = (TDI_CREATE_ADDROBJ2_CTX *)Context; 289 | TA_ADDRESS *addr = ctx->tai->Address.Address; 290 | struct ot_entry *ote_addr; 291 | KIRQL irql; 292 | int ipproto; 293 | 294 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete2: address: %x:%u\n", 295 | ntohl(((TDI_ADDRESS_IP *)(addr->Address))->in_addr), 296 | ntohs(((TDI_ADDRESS_IP *)(addr->Address))->sin_port))); 297 | 298 | // save address 299 | 300 | ote_addr = ot_find_fileobj(ctx->fileobj, &irql); 301 | if (ote_addr == NULL) { 302 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete2: ot_find_fileobj(0x%x)\n", 303 | ctx->fileobj)); 304 | status = STATUS_OBJECT_NAME_NOT_FOUND; 305 | goto done; 306 | } 307 | 308 | if (addr->AddressLength > sizeof(ote_addr->local_addr)) { 309 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete2: address too long! (%u)\n", 310 | addr->AddressLength)); 311 | status = STATUS_BUFFER_OVERFLOW; 312 | goto done; 313 | } 314 | memcpy(ote_addr->local_addr, addr, addr->AddressLength); 315 | 316 | if (ote_addr->ipproto != IPPROTO_TCP) { 317 | // set "LISTEN" state for this addrobj 318 | status = add_listen(ote_addr); 319 | if (status != STATUS_SUCCESS) { 320 | KdPrint(("[tdi_fw] tdi_create_addrobj_complete2: add_listen: 0x%x!\n", status)); 321 | goto done; 322 | } 323 | } 324 | 325 | status = STATUS_SUCCESS; 326 | done: 327 | if (ote_addr != NULL) 328 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 329 | 330 | // cleanup MDL to avoid unlocking pages from NonPaged pool 331 | if (Irp->MdlAddress != NULL) { 332 | IoFreeMdl(Irp->MdlAddress); 333 | Irp->MdlAddress = NULL; 334 | } 335 | 336 | free(ctx->tai); 337 | free(ctx); 338 | 339 | // success anyway 340 | return STATUS_SUCCESS; 341 | } 342 | 343 | //---------------------------------------------------------------------------- 344 | 345 | /* 346 | * TDI_CLEANUP handler 347 | */ 348 | 349 | int 350 | tdi_cleanup(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 351 | { 352 | NTSTATUS status; 353 | int type; 354 | 355 | // delete fileobj 356 | 357 | status = ot_del_fileobj(irps->FileObject, &type); 358 | if (status != STATUS_SUCCESS) 359 | KdPrint(("[tdi_fw] tdi_cleanup: del_fileobj: 0x%x!\n", status)); 360 | else 361 | KdPrint(("[tdi_fw] tdi_cleanup: fileobj 0x%x, type %d\n", irps->FileObject, type)); 362 | 363 | // success anyway 364 | return FILTER_ALLOW; 365 | } 366 | 367 | //---------------------------------------------------------------------------- 368 | 369 | /* 370 | * TDI_ASSOCIATE_ADDRESS handler 371 | * 372 | * With help of this routine we can get address object by connection object 373 | * and get connection object by connection context and address object 374 | */ 375 | int 376 | tdi_associate_address(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 377 | { 378 | HANDLE addr_handle = ((TDI_REQUEST_KERNEL_ASSOCIATE *)(&irps->Parameters))->AddressHandle; 379 | PFILE_OBJECT addrobj = NULL; 380 | NTSTATUS status; 381 | struct ot_entry *ote_conn = NULL; 382 | KIRQL irql; 383 | int result = FILTER_DENY; 384 | 385 | KdPrint(("[tdi_fw] tdi_associate_address: devobj 0x%x; connobj 0x%x\n", 386 | irps->DeviceObject, irps->FileObject)); 387 | 388 | status = ObReferenceObjectByHandle(addr_handle, GENERIC_READ, NULL, KernelMode, &addrobj, NULL); 389 | if (status != STATUS_SUCCESS) { 390 | KdPrint(("[tdi_fw] tdi_associate_address: ObReferenceObjectByHandle: 0x%x\n", status)); 391 | goto done; 392 | } 393 | 394 | KdPrint(("[tdi_fw] tdi_associate_address: connobj = 0x%x ---> addrobj = 0x%x\n", 395 | irps->FileObject, addrobj)); 396 | 397 | // associate addrobj with connobj 398 | 399 | ote_conn = ot_find_fileobj(irps->FileObject, &irql); 400 | if (ote_conn == NULL) { 401 | KdPrint(("[tdi_fw] tdi_associate_address: ot_find_fileobj(0x%x)\n", irps->FileObject)); 402 | goto done; 403 | } 404 | ote_conn->associated_fileobj = addrobj; 405 | 406 | // add (conn_ctx, addrobj)->connobj 407 | 408 | status = ot_add_conn_ctx(addrobj, ote_conn->conn_ctx, irps->FileObject); 409 | if (status != STATUS_SUCCESS) { 410 | KdPrint(("[tdi_fw] tdi_associate_address: ot_add_conn_ctx: 0x%x\n", status)); 411 | goto done; 412 | } 413 | 414 | result = FILTER_ALLOW; 415 | done: 416 | if (addrobj != NULL) 417 | ObDereferenceObject(addrobj); 418 | 419 | // cleanup 420 | if (ote_conn != NULL) 421 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 422 | 423 | return result; 424 | } 425 | 426 | //---------------------------------------------------------------------------- 427 | 428 | /* 429 | * TDI_DISASSOCIATE_ADDRESS handler 430 | */ 431 | int 432 | tdi_disassociate_address(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 433 | { 434 | struct ot_entry *ote_conn = NULL; 435 | KIRQL irql; 436 | NTSTATUS status; 437 | 438 | KdPrint(("[tdi_fw] tdi_disassociate_address: connobj 0x%x\n", irps->FileObject)); 439 | 440 | // delete connnection object 441 | ote_conn = ot_find_fileobj(irps->FileObject, &irql); 442 | if (ote_conn == NULL) { 443 | KdPrint(("[tdi_fw] tdi_disassociate_address: ot_find_fileobj(0x%x)\n", irps->FileObject)); 444 | goto done; 445 | } 446 | 447 | // delete link of (addrobj, conn_ctx)->connobj 448 | status = ot_del_conn_ctx(ote_conn->associated_fileobj, ote_conn->conn_ctx); 449 | if (status != STATUS_SUCCESS) { 450 | KdPrint(("[tdi_fw] tdi_disassociate_address: ot_del_conn_ctx: 0x%x\n", status)); 451 | goto done; 452 | } 453 | 454 | done: 455 | if (ote_conn != NULL) 456 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 457 | 458 | // success anyway 459 | return FILTER_ALLOW; 460 | } 461 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/disp_sr.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: disp_sr.c,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 14 | 15 | /* 16 | * This file contains TDI_SEND and TDI_RECEIVE handlers 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "dispatch.h" 24 | #include "memtrack.h" 25 | #include "obj_tbl.h" 26 | #include "tdi_fw.h" 27 | 28 | static NTSTATUS tdi_receive_complete( 29 | IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); 30 | 31 | //---------------------------------------------------------------------------- 32 | 33 | /* 34 | * TDI_SEND handler 35 | */ 36 | 37 | int 38 | tdi_send(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 39 | { 40 | TDI_REQUEST_KERNEL_SEND *param = (TDI_REQUEST_KERNEL_SEND *)(&irps->Parameters); 41 | struct ot_entry *ote_conn; 42 | KIRQL irql; 43 | 44 | KdPrint(("[tdi_fw] tdi_send: connobj: 0x%x; SendLength: %u; SendFlags: 0x%x\n", 45 | irps->FileObject, param->SendLength, param->SendFlags)); 46 | 47 | ote_conn = ot_find_fileobj(irps->FileObject, &irql); 48 | if (ote_conn != NULL) { 49 | ULONG bytes = param->SendLength; 50 | 51 | ote_conn->bytes_out += bytes; 52 | 53 | // traffic stats 54 | KeAcquireSpinLockAtDpcLevel(&g_traffic_guard); 55 | 56 | g_traffic[TRAFFIC_TOTAL_OUT] += bytes; 57 | 58 | if (ote_conn->log_disconnect) 59 | g_traffic[TRAFFIC_COUNTED_OUT] += bytes; 60 | 61 | KeReleaseSpinLockFromDpcLevel(&g_traffic_guard); 62 | 63 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 64 | } 65 | 66 | // TODO: process TDI_SEND_AND_DISCONNECT flag (used by IIS for example) 67 | 68 | return FILTER_ALLOW; 69 | } 70 | 71 | //---------------------------------------------------------------------------- 72 | 73 | /* 74 | * TDI_RECEIVE handler 75 | */ 76 | 77 | int 78 | tdi_receive(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 79 | { 80 | TDI_REQUEST_KERNEL_RECEIVE *param = (TDI_REQUEST_KERNEL_RECEIVE *)(&irps->Parameters); 81 | 82 | KdPrint(("[tdi_fw] tdi_receive: connobj: 0x%x; ReceiveLength: %u; ReceiveFlags: 0x%x\n", 83 | irps->FileObject, param->ReceiveLength, param->ReceiveFlags)); 84 | 85 | if (!(param->ReceiveFlags & TDI_RECEIVE_PEEK)) { 86 | completion->routine = tdi_receive_complete; 87 | } 88 | 89 | return FILTER_ALLOW; 90 | } 91 | 92 | NTSTATUS 93 | tdi_receive_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 94 | { 95 | PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(Irp); 96 | struct ot_entry *ote_conn; 97 | KIRQL irql; 98 | 99 | KdPrint(("[tdi_fw] tdi_receive_complete: connobj: 0x%x; status: 0x%x; received: %u\n", 100 | irps->FileObject, Irp->IoStatus.Status, Irp->IoStatus.Information)); 101 | 102 | ote_conn = ot_find_fileobj(irps->FileObject, &irql); 103 | if (ote_conn != NULL) { 104 | ULONG bytes = Irp->IoStatus.Information; 105 | 106 | ote_conn->bytes_in += bytes; 107 | 108 | // traffic stats 109 | KeAcquireSpinLockAtDpcLevel(&g_traffic_guard); 110 | 111 | g_traffic[TRAFFIC_TOTAL_IN] += bytes; 112 | 113 | if (ote_conn->log_disconnect) 114 | g_traffic[TRAFFIC_COUNTED_IN] += bytes; 115 | 116 | KeReleaseSpinLockFromDpcLevel(&g_traffic_guard); 117 | 118 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 119 | } 120 | 121 | return tdi_generic_complete(DeviceObject, Irp, Context); 122 | } 123 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/dispatch.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: dispatch.c,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 14 | 15 | /* 16 | * Dispatch routines for TDI ioctls 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "dispatch.h" 24 | 25 | #if DBG 26 | # define ENTRY(code, fn) {code, fn, #code} 27 | # define LAST_ENTRY {0, NULL, NULL} 28 | #else 29 | # define ENTRY(code, fn) {code, fn} 30 | # define LAST_ENTRY {0, NULL} 31 | #endif 32 | 33 | struct tdi_ioctl g_tdi_ioctls[] = { 34 | ENTRY(TDI_ASSOCIATE_ADDRESS, tdi_associate_address), 35 | ENTRY(TDI_CONNECT, tdi_connect), 36 | ENTRY(TDI_DISASSOCIATE_ADDRESS, tdi_disassociate_address), 37 | ENTRY(TDI_SET_EVENT_HANDLER, tdi_set_event_handler), 38 | ENTRY(TDI_SEND_DATAGRAM, tdi_send_datagram), 39 | ENTRY(TDI_RECEIVE_DATAGRAM, tdi_receive_datagram), 40 | ENTRY(TDI_DISCONNECT, tdi_disconnect), 41 | ENTRY(TDI_SEND, tdi_send), 42 | ENTRY(TDI_RECEIVE, tdi_receive), 43 | #if 1 // for now only deny stubs for security reasons 44 | ENTRY(TDI_ACCEPT, tdi_deny_stub), 45 | ENTRY(TDI_LISTEN, tdi_deny_stub), 46 | #endif 47 | LAST_ENTRY 48 | }; 49 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/dispatch.h: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 2 | // 3 | // $Id: dispatch.h,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 4 | 5 | #ifndef _dispatch_h_ 6 | #define _dispatch_h_ 7 | 8 | // information about completion routine 9 | struct completion { 10 | PIO_COMPLETION_ROUTINE routine; 11 | PVOID context; 12 | }; 13 | 14 | /* 15 | * TDI ioctl dispatcher function 16 | * returns FILTER_xxx 17 | */ 18 | typedef int tdi_ioctl_fn_t(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion); 19 | 20 | // IRP_MJ_CREATE, IRP_MJ_CLEANUP dispatch routines 21 | extern tdi_ioctl_fn_t tdi_create, tdi_cleanup; 22 | 23 | // IRP_MJ_INTERNAL_DEVICE_CONTROL ioctl dispatch routines 24 | extern tdi_ioctl_fn_t 25 | tdi_associate_address, 26 | tdi_connect, 27 | tdi_disassociate_address, 28 | tdi_set_event_handler, 29 | tdi_send_datagram, 30 | tdi_receive_datagram, 31 | tdi_disconnect, 32 | tdi_send, 33 | tdi_receive, 34 | tdi_deny_stub; 35 | 36 | // helper struct for calling of TDI ioctls 37 | struct tdi_ioctl { 38 | UCHAR MinorFunction; 39 | tdi_ioctl_fn_t *fn; 40 | 41 | #if DBG 42 | // for debugging 43 | const char *desc; 44 | #endif 45 | }; 46 | 47 | extern struct tdi_ioctl g_tdi_ioctls[]; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/ev_conn.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: ev_conn.c,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 14 | 15 | /* 16 | * This file contain TDI_EVENT_CONNECT & TDI_EVENT_DISCONNECT handlers 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "conn_state.h" 24 | #include "dispatch.h" 25 | #include "events.h" 26 | #include "memtrack.h" 27 | #include "obj_tbl.h" 28 | #include "sids.h" 29 | #include "tdi_fw.h" 30 | 31 | struct accept_param { 32 | PIO_COMPLETION_ROUTINE old_cr; 33 | PVOID old_context; 34 | PFILE_OBJECT fileobj; 35 | UCHAR old_control; 36 | }; 37 | 38 | static NTSTATUS tdi_evconn_accept_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); 39 | 40 | //---------------------------------------------------------------------------- 41 | 42 | /* 43 | * TDI_EVENT_CONNECT handler 44 | */ 45 | 46 | NTSTATUS 47 | tdi_event_connect( 48 | IN PVOID TdiEventContext, 49 | IN LONG RemoteAddressLength, 50 | IN PVOID RemoteAddress, 51 | IN LONG UserDataLength, 52 | IN PVOID UserData, 53 | IN LONG OptionsLength, 54 | IN PVOID Options, 55 | OUT CONNECTION_CONTEXT *ConnectionContext, 56 | OUT PIRP *AcceptIrp) 57 | { 58 | TDI_EVENT_CONTEXT *ctx = (TDI_EVENT_CONTEXT *)TdiEventContext; 59 | TA_ADDRESS *remote_addr = ((TRANSPORT_ADDRESS *)RemoteAddress)->Address, *local_addr; 60 | struct ot_entry *ote_addr = NULL, *ote_conn = NULL; 61 | KIRQL irql; 62 | struct flt_request request; 63 | struct flt_rule rule; 64 | int result = FILTER_DENY; 65 | NTSTATUS status; 66 | PIO_STACK_LOCATION irps = NULL; 67 | struct accept_param *param = NULL; 68 | 69 | memset(&request, 0, sizeof(request)); 70 | 71 | KdPrint(("[tdi_fw] tdi_event_connect: addrobj 0x%x\n", ctx->fileobj)); 72 | 73 | ote_addr = ot_find_fileobj(ctx->fileobj, &irql); 74 | if (ote_addr == NULL) { 75 | KdPrint(("[tdi_fw] tdi_event_connect: ot_find_fileobj(0x%x)\n", ctx->fileobj)); 76 | goto done; 77 | } 78 | 79 | local_addr = (TA_ADDRESS *)(ote_addr->local_addr); 80 | 81 | KdPrint(("[tdi_fw] tdi_event_connect(pid:%u): %x:%u -> %x:%u\n", 82 | ote_addr->pid, 83 | ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), 84 | ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port), 85 | ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr), 86 | ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port))); 87 | 88 | /* 89 | * request quick filter 90 | */ 91 | 92 | request.struct_size = sizeof(request); 93 | 94 | request.type = TYPE_CONNECT; 95 | request.direction = DIRECTION_IN; 96 | request.proto = IPPROTO_TCP; 97 | request.pid = ote_addr->pid; 98 | 99 | // get user SID & attributes! 100 | if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL) 101 | request.sid_a_size = ote_addr->sid_a_size; 102 | 103 | memcpy(&request.addr.from, &remote_addr->AddressType, sizeof(struct sockaddr)); 104 | memcpy(&request.addr.to, &local_addr->AddressType, sizeof(struct sockaddr)); 105 | request.addr.len = sizeof(struct sockaddr_in); 106 | 107 | result = quick_filter(&request, &rule); 108 | 109 | memcpy(request.log_rule_id, rule.rule_id, RULE_ID_SIZE); 110 | 111 | // log request later 112 | 113 | if (result == FILTER_DENY) 114 | goto done; 115 | 116 | result = FILTER_DENY; 117 | 118 | // leave spinlock before calling original handler 119 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 120 | ote_addr = NULL; 121 | 122 | /* 123 | * run original handler 124 | */ 125 | 126 | status = ((PTDI_IND_CONNECT)(ctx->old_handler)) 127 | (ctx->old_context, RemoteAddressLength, RemoteAddress, 128 | UserDataLength, UserData, OptionsLength, Options, ConnectionContext, 129 | AcceptIrp); 130 | 131 | if (status != STATUS_MORE_PROCESSING_REQUIRED || *AcceptIrp == NULL) { 132 | KdPrint(("[tdi_fw] tdi_event_connect: status from original handler: 0x%x\n", status)); 133 | goto done; 134 | } 135 | 136 | /* 137 | * reinitialize connobj 138 | */ 139 | 140 | irps = IoGetCurrentIrpStackLocation(*AcceptIrp); 141 | KdPrint(("[tdi_fw] tdi_event_connect: connobj 0x%x\n", irps->FileObject)); 142 | 143 | // patch *AcceptIrp to change completion routine 144 | 145 | param = (struct accept_param *)malloc_np(sizeof(*param)); 146 | if (param == NULL) { 147 | KdPrint(("[tdi_fw] tdi_event_connect: malloc_np!\n")); 148 | status = STATUS_INSUFFICIENT_RESOURCES; 149 | goto done; 150 | } 151 | 152 | param->old_cr = irps->CompletionRoutine; 153 | param->old_context = irps->Context; 154 | param->fileobj = irps->FileObject; 155 | 156 | param->old_control = irps->Control; 157 | 158 | // can't use IoSetCompletionRoutine because it uses next not current stack location 159 | irps->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL; 160 | irps->CompletionRoutine = tdi_evconn_accept_complete; 161 | irps->Context = param; 162 | 163 | param = NULL; 164 | 165 | // find connobj for changing 166 | 167 | ote_conn = ot_find_fileobj(irps->FileObject, &irql); 168 | if (ote_conn == NULL) { 169 | KdPrint(("[tdi_fw] tdi_event_connect: ot_find_fileobj(0x%x)\n", irps->FileObject)); 170 | status = STATUS_OBJECT_NAME_NOT_FOUND; 171 | goto done; 172 | } 173 | 174 | ASSERT(ote_conn->type == FILEOBJ_CONNOBJ); 175 | 176 | // connobj must be associated with addrobj! 177 | if (ote_conn->associated_fileobj != ctx->fileobj) { 178 | KdPrint(("[tdi_fw] tdi_event_connect: 0x%x != 0x%x\n", ote_conn->associated_fileobj, ctx->fileobj)); 179 | status = STATUS_INVALID_PARAMETER; 180 | goto done; 181 | } 182 | 183 | // change conn_ctx (if needed) 184 | if (ote_conn->conn_ctx != *ConnectionContext) { 185 | // update (conn_ctx, addrobj)->connobj 186 | 187 | status = ot_del_conn_ctx(ote_conn->associated_fileobj, ote_conn->conn_ctx); 188 | if (status != STATUS_SUCCESS) { 189 | KdPrint(("[tdi_fw] tdi_event_connect: ot_del_conn_ctx: 0x%x\n", status)); 190 | goto done; 191 | } 192 | 193 | ote_conn->conn_ctx = *ConnectionContext; 194 | 195 | status = ot_add_conn_ctx(ote_conn->associated_fileobj, ote_conn->conn_ctx, irps->FileObject); 196 | if (status != STATUS_SUCCESS) { 197 | KdPrint(("[tdi_fw] tdi_event_connect: ot_add_conn_ctx: 0x%x\n", status)); 198 | goto done; 199 | } 200 | 201 | } 202 | 203 | // clear listen & conn entries in connobj (fileobject can be reused) 204 | 205 | ASSERT(ote_conn->listen_entry == NULL); 206 | if (ote_conn->listen_entry != NULL) 207 | del_listen_obj(ote_conn->listen_entry, FALSE); // free build case 208 | 209 | if (ote_conn->conn_entry != NULL) { 210 | 211 | if (ote_conn->ipproto == IPPROTO_TCP && ote_conn->log_disconnect) 212 | log_disconnect(ote_conn); 213 | 214 | del_tcp_conn_obj(ote_conn->conn_entry, FALSE); 215 | } 216 | 217 | // clear bytes count 218 | ote_conn->bytes_in = ote_conn->bytes_out = 0; 219 | 220 | // setup log_disconnect flag from rule 221 | ote_conn->log_disconnect = (rule.log >= RULE_LOG_COUNT); 222 | 223 | // sanity check 224 | if (local_addr->AddressLength != remote_addr->AddressLength) { 225 | KdPrint(("[tdi_fw] tdi_event_connect: different addr lengths! (%u != %u)\n", 226 | local_addr->AddressLength, 227 | remote_addr->AddressLength)); 228 | status = STATUS_INFO_LENGTH_MISMATCH; 229 | goto done; 230 | } 231 | 232 | // associate remote address with connobj 233 | 234 | if (remote_addr->AddressLength > sizeof(ote_conn->remote_addr)) { 235 | KdPrint(("[tdi_fw] tdi_event_connect: address too long! (%u)\n", 236 | remote_addr->AddressLength)); 237 | status = STATUS_BUFFER_TOO_SMALL; 238 | goto done; 239 | } 240 | memcpy(ote_conn->remote_addr, remote_addr, remote_addr->AddressLength); 241 | 242 | // associate local address with connobj 243 | 244 | if (local_addr->AddressLength > sizeof(ote_conn->local_addr)) { 245 | KdPrint(("[tdi_fw] tdi_event_connect: address too long! (%u)\n", 246 | local_addr->AddressLength)); 247 | status = STATUS_BUFFER_TOO_SMALL; 248 | goto done; 249 | } 250 | memcpy(ote_conn->local_addr, local_addr, local_addr->AddressLength); 251 | 252 | // create connection with "SYN_RCVD" state 253 | status = add_tcp_conn(ote_conn, TCP_STATE_SYN_RCVD); 254 | if (status != STATUS_SUCCESS) { 255 | KdPrint(("[tdi_fw] tdi_event_connect: add_tcp_conn: 0x%x\n", status)); 256 | goto done; 257 | } 258 | 259 | result = FILTER_ALLOW; 260 | 261 | done: 262 | // if logging is needed log request 263 | if (rule.log >= RULE_LOG_LOG) { 264 | if (result != FILTER_ALLOW && rule.result == FILTER_ALLOW) { 265 | request.type = TYPE_CONNECT_ERROR; // error has been occured 266 | request.status = status; 267 | } 268 | 269 | log_request(&request); 270 | } 271 | 272 | if (result != FILTER_ALLOW) { 273 | // deny incoming connection 274 | 275 | KdPrint(("[tdi_fw] tdi_event_connect: deny on reason 0x%x\n", status)); 276 | 277 | if (irps != NULL) { 278 | // delete connection 279 | if (ote_conn != NULL && ote_conn->conn_entry != NULL) { 280 | del_tcp_conn_obj(ote_conn->conn_entry, FALSE); 281 | ote_conn->conn_entry = NULL; 282 | } 283 | 284 | // release spinlock before IoCompleteRequest to avoid completion call inside spinlock 285 | if (ote_addr != NULL || ote_conn != NULL) { 286 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 287 | 288 | ote_addr = NULL; 289 | ote_conn = NULL; 290 | } 291 | 292 | // destroy accepted IRP 293 | (*AcceptIrp)->IoStatus.Status = STATUS_UNSUCCESSFUL; 294 | IoCompleteRequest(*AcceptIrp, IO_NO_INCREMENT); 295 | } 296 | 297 | *AcceptIrp = NULL; 298 | status = STATUS_CONNECTION_REFUSED; 299 | } else 300 | status = STATUS_MORE_PROCESSING_REQUIRED; 301 | 302 | // cleanup 303 | if (ote_addr != NULL || ote_conn != NULL) 304 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 305 | if (param != NULL) 306 | free(param); 307 | if (request.sid_a != NULL) 308 | free(request.sid_a); 309 | 310 | return status; 311 | } 312 | 313 | NTSTATUS 314 | tdi_evconn_accept_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 315 | { 316 | PIO_STACK_LOCATION irps = IoGetNextIrpStackLocation(Irp); 317 | struct accept_param *param = (struct accept_param *)Context; 318 | NTSTATUS status = STATUS_SUCCESS; 319 | 320 | KdPrint(("[tdi_fw] tdi_evconn_accept_complete: status 0x%x\n", Irp->IoStatus.Status)); 321 | 322 | if (Irp->IoStatus.Status == STATUS_SUCCESS) { 323 | set_tcp_conn_state(param->fileobj, TCP_STATE_ESTABLISHED_IN); 324 | 325 | // query & update connection local_addr 326 | update_conn_info(irps->DeviceObject, param->fileobj); 327 | 328 | } else 329 | del_tcp_conn(param->fileobj, TRUE); // TRUE because we logged connection in event handler 330 | 331 | // restore routine and context (and even control!) 332 | irps->CompletionRoutine = param->old_cr; 333 | irps->Context = param->old_context; 334 | irps->Control = param->old_control; 335 | 336 | // call original completion (I like this code :-) 337 | 338 | if (param->old_cr != NULL) { 339 | // call old completion (see the old control) 340 | BOOLEAN b_call = FALSE; 341 | 342 | if (Irp->Cancel) { 343 | // cancel 344 | if (param->old_control & SL_INVOKE_ON_CANCEL) 345 | b_call = TRUE; 346 | } else { 347 | if (Irp->IoStatus.Status >= STATUS_SUCCESS) { 348 | // success 349 | if (param->old_control & SL_INVOKE_ON_SUCCESS) 350 | b_call = TRUE; 351 | } else { 352 | // error 353 | if (param->old_control & SL_INVOKE_ON_ERROR) 354 | b_call = TRUE; 355 | } 356 | } 357 | 358 | if (b_call) 359 | status = param->old_cr(DeviceObject, Irp, param->old_context); 360 | } 361 | 362 | free(param); 363 | return status; 364 | } 365 | 366 | //---------------------------------------------------------------------------- 367 | 368 | /* 369 | * TDI_EVENT_DISCONNECT handler 370 | */ 371 | 372 | NTSTATUS 373 | tdi_event_disconnect( 374 | IN PVOID TdiEventContext, 375 | IN CONNECTION_CONTEXT ConnectionContext, 376 | IN LONG DisconnectDataLength, 377 | IN PVOID DisconnectData, 378 | IN LONG DisconnectInformationLength, 379 | IN PVOID DisconnectInformation, 380 | IN ULONG DisconnectFlags) 381 | { 382 | TDI_EVENT_CONTEXT *ctx = (TDI_EVENT_CONTEXT *)TdiEventContext; 383 | PFILE_OBJECT connobj = ot_find_conn_ctx(ctx->fileobj, ConnectionContext); 384 | 385 | KdPrint(("[tdi_fw] tdi_event_disconnect: connobj: 0x%x (flags: 0x%x)\n", 386 | connobj, DisconnectFlags)); 387 | 388 | if (DisconnectFlags & TDI_DISCONNECT_RELEASE) { 389 | int state = get_tcp_conn_state_by_obj(connobj); 390 | 391 | if (state == TCP_STATE_ESTABLISHED_IN || state == TCP_STATE_ESTABLISHED_OUT) 392 | set_tcp_conn_state(connobj, TCP_STATE_CLOSE_WAIT); 393 | else if (state == TCP_STATE_FIN_WAIT2) 394 | set_tcp_conn_state(connobj, TCP_STATE_TIME_WAIT); 395 | else 396 | KdPrint(("[tdi_fw] tdi_event_disconnect: weird conn state: %d\n", state)); 397 | 398 | } else 399 | del_tcp_conn(connobj, TRUE); 400 | 401 | return ((PTDI_IND_DISCONNECT)(ctx->old_handler))(ctx->old_context, ConnectionContext, 402 | DisconnectDataLength, DisconnectData, DisconnectInformationLength, 403 | DisconnectInformation, DisconnectFlags); 404 | } 405 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/ev_dg.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: ev_dg.c,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 14 | 15 | /* 16 | * This file contains TDI_EVENT_RECEIVE_DATAGRAM handler 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "events.h" 24 | #include "filter.h" 25 | #include "memtrack.h" 26 | #include "obj_tbl.h" 27 | #include "sids.h" 28 | #include "tdi_fw.h" 29 | 30 | //---------------------------------------------------------------------------- 31 | 32 | /* 33 | * TDI_EVENT_RECEIVE_DATAGRAM handler 34 | */ 35 | 36 | NTSTATUS tdi_event_receive_datagram( 37 | IN PVOID TdiEventContext, 38 | IN LONG SourceAddressLength, 39 | IN PVOID SourceAddress, 40 | IN LONG OptionsLength, 41 | IN PVOID Options, 42 | IN ULONG ReceiveDatagramFlags, 43 | IN ULONG BytesIndicated, 44 | IN ULONG BytesAvailable, 45 | OUT ULONG *BytesTaken, 46 | IN PVOID Tsdu, 47 | OUT PIRP *IoRequestPacket) 48 | { 49 | TDI_EVENT_CONTEXT *ctx = (TDI_EVENT_CONTEXT *)TdiEventContext; 50 | struct ot_entry *ote_addr = NULL; 51 | KIRQL irql; 52 | TA_ADDRESS *remote_addr, *local_addr; 53 | NTSTATUS status; 54 | int ipproto, result = FILTER_DENY; 55 | struct flt_request request; 56 | struct flt_rule rule; 57 | 58 | // get local address of address object 59 | 60 | memset(&request, 0, sizeof(request)); 61 | ote_addr = ot_find_fileobj(ctx->fileobj, &irql); 62 | if (ote_addr == NULL) { 63 | KdPrint(("[tdi_fw] tdi_receive_datagram: ot_find_fileobj(0x%x)!\n", ctx->fileobj)); 64 | goto done; 65 | } 66 | 67 | KdPrint(("[tdi_fw] tdi_event_receive_datagram: addrobj 0x%x\n", ctx->fileobj)); 68 | 69 | // check device object: UDP or RawIP 70 | if (get_original_devobj(ote_addr->devobj, &ipproto) == NULL || 71 | (ipproto != IPPROTO_UDP && ipproto != IPPROTO_IP)) { 72 | // unknown device object! 73 | KdPrint(("[tdi_fw] tdi_event_receive_datagram: unknown DeviceObject 0x%x!\n", 74 | ote_addr)); 75 | goto done; 76 | } 77 | 78 | local_addr = (TA_ADDRESS *)(ote_addr->local_addr); 79 | remote_addr = ((TRANSPORT_ADDRESS *)SourceAddress)->Address; 80 | 81 | KdPrint(("[tdi_fw] tdi_event_receive_datagram(pid:%u): %x:%u -> %x:%u\n", 82 | ote_addr->pid, 83 | ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), 84 | ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port), 85 | ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr), 86 | ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port))); 87 | 88 | // call quick filter for datagram 89 | request.struct_size = sizeof(request); 90 | 91 | request.type = TYPE_DATAGRAM; 92 | request.direction = DIRECTION_IN; 93 | request.proto = ipproto; 94 | request.pid = ote_addr->pid; 95 | 96 | // get user SID & attributes (can't call get_current_sid_a at DISPATCH_LEVEL) 97 | if ((request.sid_a = copy_sid_a(ote_addr->sid_a, ote_addr->sid_a_size)) != NULL) 98 | request.sid_a_size = ote_addr->sid_a_size; 99 | 100 | memcpy(&request.addr.from, &remote_addr->AddressType, sizeof(struct sockaddr)); 101 | memcpy(&request.addr.to, &local_addr->AddressType, sizeof(struct sockaddr)); 102 | request.addr.len = sizeof(struct sockaddr_in); 103 | 104 | memset(&rule, 0, sizeof(rule)); 105 | 106 | result = quick_filter(&request, &rule); 107 | 108 | memcpy(request.log_rule_id, rule.rule_id, RULE_ID_SIZE); 109 | 110 | if (rule.log >= RULE_LOG_LOG) { 111 | ULONG bytes = BytesAvailable; 112 | 113 | // traffic stats 114 | KeAcquireSpinLockAtDpcLevel(&g_traffic_guard); 115 | 116 | g_traffic[TRAFFIC_TOTAL_IN] += bytes; 117 | 118 | if (rule.log >= RULE_LOG_COUNT) { 119 | request.log_bytes_in = bytes; 120 | 121 | g_traffic[TRAFFIC_COUNTED_IN] += bytes; 122 | 123 | } else 124 | request.log_bytes_in = (ULONG)-1; 125 | 126 | KeReleaseSpinLockFromDpcLevel(&g_traffic_guard); 127 | 128 | log_request(&request); 129 | } 130 | 131 | done: 132 | // cleanup 133 | if (ote_addr != NULL) 134 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 135 | if (request.sid_a != NULL) 136 | free(request.sid_a); 137 | 138 | if (result == FILTER_ALLOW) { 139 | 140 | return ((PTDI_IND_RECEIVE_DATAGRAM)(ctx->old_handler)) 141 | (ctx->old_context, SourceAddressLength, SourceAddress, OptionsLength, 142 | Options, ReceiveDatagramFlags, BytesIndicated, BytesAvailable, BytesTaken, 143 | Tsdu, IoRequestPacket); 144 | 145 | } else 146 | return STATUS_DATA_NOT_ACCEPTED; 147 | } 148 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/ev_recv.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: ev_recv.c,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 14 | 15 | /* 16 | * This file contains TDI_EVENT_RECEIVE and TDI_EVENT_CHAINED_RECEIVE handlers 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "events.h" 24 | #include "memtrack.h" 25 | #include "obj_tbl.h" 26 | #include "tdi_fw.h" 27 | 28 | struct tdi_client_irp_ctx { 29 | PIO_COMPLETION_ROUTINE completion; 30 | PVOID context; 31 | UCHAR old_control; 32 | PFILE_OBJECT connobj; 33 | }; 34 | 35 | static NTSTATUS tdi_client_irp_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); 36 | 37 | //---------------------------------------------------------------------------- 38 | 39 | /* 40 | * TDI_EVENT_RECEIVE handler 41 | */ 42 | 43 | NTSTATUS 44 | tdi_event_receive( 45 | IN PVOID TdiEventContext, 46 | IN CONNECTION_CONTEXT ConnectionContext, 47 | IN ULONG ReceiveFlags, 48 | IN ULONG BytesIndicated, 49 | IN ULONG BytesAvailable, 50 | OUT ULONG *BytesTaken, 51 | IN PVOID Tsdu, 52 | OUT PIRP *IoRequestPacket) 53 | { 54 | TDI_EVENT_CONTEXT *ctx = (TDI_EVENT_CONTEXT *)TdiEventContext; 55 | PFILE_OBJECT connobj = ot_find_conn_ctx(ctx->fileobj, ConnectionContext); 56 | NTSTATUS status; 57 | 58 | KdPrint(("[tdi_fw] tdi_event_receive: addrobj 0x%x; connobj: 0x%x; %u/%u; flags: 0x%x\n", 59 | ctx->fileobj, connobj, BytesIndicated, BytesAvailable, ReceiveFlags)); 60 | 61 | status = ((PTDI_IND_RECEIVE)(ctx->old_handler)) 62 | (ctx->old_context, ConnectionContext, ReceiveFlags, BytesIndicated, 63 | BytesAvailable, BytesTaken, Tsdu, IoRequestPacket); 64 | 65 | KdPrint(("[tdi_fw] tdi_event_receive: status 0x%x; BytesTaken: %u; Irp: 0x%x\n", 66 | status, *BytesTaken, *IoRequestPacket)); 67 | 68 | if (*BytesTaken != 0) { 69 | struct ot_entry *ote_conn; 70 | KIRQL irql; 71 | 72 | ote_conn = ot_find_fileobj(connobj, &irql); 73 | if (ote_conn != NULL) { 74 | ULONG bytes = *BytesTaken; 75 | 76 | ote_conn->bytes_in += bytes; 77 | 78 | // traffic stats 79 | KeAcquireSpinLockAtDpcLevel(&g_traffic_guard); 80 | 81 | g_traffic[TRAFFIC_TOTAL_IN] += bytes; 82 | 83 | if (ote_conn->log_disconnect) 84 | g_traffic[TRAFFIC_COUNTED_IN] += bytes; 85 | 86 | KeReleaseSpinLockFromDpcLevel(&g_traffic_guard); 87 | 88 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 89 | } 90 | } 91 | 92 | /* 93 | if (*IoRequestPacket != NULL) { 94 | // got IRP. replace completion. 95 | struct tdi_client_irp_ctx *new_ctx; 96 | PIO_STACK_LOCATION irps = IoGetCurrentIrpStackLocation(*IoRequestPacket); 97 | 98 | new_ctx = (struct tdi_client_irp_ctx *)malloc_np(sizeof(*new_ctx)); 99 | if (new_ctx != NULL) { 100 | 101 | new_ctx->connobj = connobj; 102 | 103 | if (irps->CompletionRoutine != NULL) { 104 | new_ctx->completion = irps->CompletionRoutine; 105 | new_ctx->context = irps->Context; 106 | new_ctx->old_control = irps->Control; 107 | 108 | } else { 109 | 110 | // we don't use IoSetCompletionRoutine because it uses next not current location 111 | 112 | new_ctx->completion = NULL; 113 | new_ctx->context = NULL; 114 | 115 | } 116 | 117 | irps->CompletionRoutine = tdi_client_irp_complete; 118 | irps->Context = new_ctx; 119 | irps->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | SL_INVOKE_ON_CANCEL; 120 | } 121 | }*/ 122 | 123 | return status; 124 | } 125 | 126 | NTSTATUS 127 | tdi_client_irp_complete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context) 128 | { 129 | struct tdi_client_irp_ctx *ctx = (struct tdi_client_irp_ctx *)Context; 130 | NTSTATUS status; 131 | 132 | KdPrint(("[tdi_fw] tdi_client_irp_complete: status: 0x%x; len: %u\n", 133 | Irp->IoStatus.Status, Irp->IoStatus.Information)); 134 | 135 | if (Irp->IoStatus.Status == STATUS_SUCCESS) { 136 | 137 | struct ot_entry *ote_conn; 138 | KIRQL irql; 139 | 140 | ote_conn = ot_find_fileobj(ctx->connobj, &irql); 141 | if (ote_conn != NULL) { 142 | ULONG bytes = Irp->IoStatus.Information; 143 | 144 | ote_conn->bytes_in += bytes; 145 | 146 | // traffic stats 147 | KeAcquireSpinLockAtDpcLevel(&g_traffic_guard); 148 | 149 | g_traffic[TRAFFIC_TOTAL_IN] += bytes; 150 | 151 | if (ote_conn->log_disconnect) 152 | g_traffic[TRAFFIC_COUNTED_IN] += bytes; 153 | 154 | KeReleaseSpinLockFromDpcLevel(&g_traffic_guard); 155 | 156 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 157 | } 158 | } 159 | 160 | // call original completion 161 | if (ctx->completion != NULL) { 162 | // call old completion (see the old control) 163 | BOOLEAN b_call = FALSE; 164 | 165 | if (Irp->Cancel) { 166 | // cancel 167 | if (ctx->old_control & SL_INVOKE_ON_CANCEL) 168 | b_call = TRUE; 169 | } else { 170 | if (Irp->IoStatus.Status >= STATUS_SUCCESS) { 171 | // success 172 | if (ctx->old_control & SL_INVOKE_ON_SUCCESS) 173 | b_call = TRUE; 174 | } else { 175 | // error 176 | if (ctx->old_control & SL_INVOKE_ON_ERROR) 177 | b_call = TRUE; 178 | } 179 | } 180 | 181 | if (b_call) { 182 | status = (ctx->completion)(DeviceObject, Irp, ctx->context); 183 | 184 | KdPrint(("[tdi_flt] tdi_client_irp_complete: original handler: 0x%x; status: 0x%x\n", 185 | ctx->completion, status)); 186 | 187 | } else 188 | status = STATUS_SUCCESS; 189 | 190 | } 191 | 192 | free(ctx); 193 | return status; 194 | } 195 | 196 | //---------------------------------------------------------------------------- 197 | 198 | /* 199 | * TDI_EVENT_CHAINED_RECEIVE handler 200 | */ 201 | 202 | NTSTATUS 203 | tdi_event_chained_receive( 204 | IN PVOID TdiEventContext, 205 | IN CONNECTION_CONTEXT ConnectionContext, 206 | IN ULONG ReceiveFlags, 207 | IN ULONG ReceiveLength, 208 | IN ULONG StartingOffset, 209 | IN PMDL Tsdu, 210 | IN PVOID TsduDescriptor) 211 | { 212 | TDI_EVENT_CONTEXT *ctx = (TDI_EVENT_CONTEXT *)TdiEventContext; 213 | PFILE_OBJECT connobj = ot_find_conn_ctx(ctx->fileobj, ConnectionContext); 214 | NTSTATUS status; 215 | 216 | KdPrint(("[tdi_fw] tdi_event_chained_receive: addrobj 0x%x; connobj: 0x%x; %u; flags: 0x%x\n", 217 | ctx->fileobj, connobj, ReceiveLength, ReceiveFlags)); 218 | 219 | status = ((PTDI_IND_CHAINED_RECEIVE)(ctx->old_handler)) 220 | (ctx->old_context, ConnectionContext, ReceiveFlags,ReceiveLength , 221 | StartingOffset, Tsdu, TsduDescriptor); 222 | 223 | KdPrint(("[tdi_fw] tdi_event_chained_receive: status 0x%x\n", status)); 224 | 225 | if (status == STATUS_SUCCESS || status == STATUS_PENDING) { 226 | struct ot_entry *ote_conn; 227 | KIRQL irql; 228 | 229 | ote_conn = ot_find_fileobj(connobj, &irql); 230 | if (ote_conn != NULL) { 231 | ULONG bytes = ReceiveLength; 232 | 233 | ote_conn->bytes_in += bytes; 234 | 235 | // traffic stats 236 | KeAcquireSpinLockAtDpcLevel(&g_traffic_guard); 237 | 238 | g_traffic[TRAFFIC_TOTAL_IN] += bytes; 239 | 240 | if (ote_conn->log_disconnect) 241 | g_traffic[TRAFFIC_COUNTED_IN] += bytes; 242 | 243 | KeReleaseSpinLockFromDpcLevel(&g_traffic_guard); 244 | 245 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 246 | } 247 | } 248 | 249 | return status; 250 | } 251 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/events.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: events.c,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 14 | 15 | /* 16 | * Replaced event handlers for TDI events 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "events.h" 24 | #include "memtrack.h" 25 | 26 | // to simplify processing don't use chained handlers for datagrams 27 | struct tdi_event_handler g_tdi_event_handlers[]= { 28 | {TDI_EVENT_CONNECT, tdi_event_connect}, 29 | {TDI_EVENT_DISCONNECT, tdi_event_disconnect}, 30 | {TDI_EVENT_RECEIVE_DATAGRAM, tdi_event_receive_datagram}, 31 | {TDI_EVENT_CHAINED_RECEIVE_DATAGRAM, NULL}, 32 | {TDI_EVENT_RECEIVE, tdi_event_receive}, 33 | {TDI_EVENT_RECEIVE_EXPEDITED, tdi_event_receive}, 34 | {TDI_EVENT_CHAINED_RECEIVE, tdi_event_chained_receive}, 35 | {TDI_EVENT_CHAINED_RECEIVE_EXPEDITED, tdi_event_chained_receive}, 36 | {(ULONG)-1, NULL} 37 | }; 38 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/events.h: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 2 | // 3 | // $Id: events.h,v 1.1 2009/04/28 12:53:27 tanwen Exp $ 4 | 5 | #ifndef _events_h_ 6 | #define _events_h_ 7 | 8 | #include "obj_tbl.h" 9 | 10 | NTSTATUS tdi_event_connect( 11 | IN PVOID TdiEventContext, 12 | IN LONG RemoteAddressLength, 13 | IN PVOID RemoteAddress, 14 | IN LONG UserDataLength, 15 | IN PVOID UserData, 16 | IN LONG OptionsLength, 17 | IN PVOID Options, 18 | OUT CONNECTION_CONTEXT *ConnectionContext, 19 | OUT PIRP *AcceptIrp); 20 | 21 | NTSTATUS tdi_event_disconnect( 22 | IN PVOID TdiEventContext, 23 | IN CONNECTION_CONTEXT ConnectionContext, 24 | IN LONG DisconnectDataLength, 25 | IN PVOID DisconnectData, 26 | IN LONG DisconnectInformationLength, 27 | IN PVOID DisconnectInformation, 28 | IN ULONG DisconnectFlags); 29 | 30 | NTSTATUS tdi_event_receive_datagram( 31 | IN PVOID TdiEventContext, 32 | IN LONG SourceAddressLength, 33 | IN PVOID SourceAddress, 34 | IN LONG OptionsLength, 35 | IN PVOID Options, 36 | IN ULONG ReceiveDatagramFlags, 37 | IN ULONG BytesIndicated, 38 | IN ULONG BytesAvailable, 39 | OUT ULONG *BytesTaken, 40 | IN PVOID Tsdu, 41 | OUT PIRP *IoRequestPacket); 42 | 43 | NTSTATUS tdi_event_receive( 44 | IN PVOID TdiEventContext, 45 | IN CONNECTION_CONTEXT ConnectionContext, 46 | IN ULONG ReceiveFlags, 47 | IN ULONG BytesIndicated, 48 | IN ULONG BytesAvailable, 49 | OUT ULONG *BytesTaken, 50 | IN PVOID Tsdu, 51 | OUT PIRP *IoRequestPacket); 52 | 53 | NTSTATUS tdi_event_chained_receive( 54 | IN PVOID TdiEventContext, 55 | IN CONNECTION_CONTEXT ConnectionContext, 56 | IN ULONG ReceiveFlags, 57 | IN ULONG ReceiveLength, 58 | IN ULONG StartingOffset, 59 | IN PMDL Tsdu, 60 | IN PVOID TsduDescriptor); 61 | 62 | // helper struct for calling one of the handlers 63 | struct tdi_event_handler { 64 | LONG event; 65 | PVOID handler; 66 | }; 67 | 68 | extern struct tdi_event_handler g_tdi_event_handlers[]; 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/filter.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: filter.c,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | /* 16 | * Filtering related routines 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "filter.h" 24 | #include "memtrack.h" 25 | #include "packet.h" 26 | #include "pid_pname.h" 27 | #include "sids.h" 28 | #include "tdi_fw.h" 29 | 30 | // size of cyclic queue for logging 31 | #define REQUEST_QUEUE_SIZE 1024 32 | 33 | /* rules chains (main (first entry) and process-related) */ 34 | static struct { 35 | struct { 36 | struct flt_rule *head; 37 | struct flt_rule *tail; 38 | char *pname; // name of process 39 | BOOLEAN active; // filter chain is active 40 | } chain[MAX_CHAINS_COUNT]; 41 | KSPIN_LOCK guard; 42 | } g_rules; 43 | 44 | /* "ALLOW * * FROM ANY TO ANY" rule */ 45 | static struct flt_rule g_allow_all = { 46 | {0}, 47 | FILTER_ALLOW, 48 | IPPROTO_ANY, 49 | DIRECTION_ANY, 50 | 0, // from 51 | 0, 52 | 0, 53 | 0, 54 | 0, // to 55 | 0, 56 | 0, 57 | 0, 58 | RULE_LOG_LOG, 59 | "", // setup mask before using it! 60 | "startup" // rule for startup only 61 | }; 62 | 63 | /* logging request queue */ 64 | static struct { 65 | struct flt_request *data; 66 | KSPIN_LOCK guard; 67 | ULONG head; /* write to head */ 68 | ULONG tail; /* read from tail */ 69 | HANDLE event_handle; 70 | PKEVENT event; 71 | } g_queue; 72 | 73 | // init 74 | NTSTATUS 75 | filter_init(void) 76 | { 77 | NTSTATUS status; 78 | int i; 79 | 80 | pid_pname_init(); 81 | sids_init(); 82 | 83 | /* rules chain */ 84 | 85 | KeInitializeSpinLock(&g_rules.guard); 86 | for (i = 0; i < MAX_CHAINS_COUNT; i++) { 87 | g_rules.chain[i].head = g_rules.chain[i].tail = NULL; 88 | g_rules.chain[i].pname = NULL; 89 | g_rules.chain[i].active = FALSE; 90 | } 91 | 92 | // setup the first rule "ALLOW * * FROM ANY TO ANY" 93 | 94 | for (i = 0; i < sizeof(g_allow_all.sid_mask); i++) 95 | g_allow_all.sid_mask[i] = (UCHAR)-1; 96 | 97 | g_rules.chain[0].head = malloc_np(sizeof(g_allow_all)); 98 | if (g_rules.chain[0].head == NULL) { 99 | KdPrint(("[tdi_fw] filter_init: malloc_np!\n")); 100 | return STATUS_INSUFFICIENT_RESOURCES; 101 | } 102 | 103 | memcpy(g_rules.chain[0].head, &g_allow_all, sizeof(g_allow_all)); 104 | 105 | g_rules.chain[0].tail = g_rules.chain[0].head; 106 | g_rules.chain[0].active = TRUE; 107 | 108 | /* request queue */ 109 | 110 | KeInitializeSpinLock(&g_queue.guard); 111 | 112 | g_queue.data = (struct flt_request *)malloc_np(sizeof(struct flt_request) * REQUEST_QUEUE_SIZE); 113 | if (g_queue.data == NULL) { 114 | KdPrint(("[tdi_fw] filter_init: malloc_np!\n")); 115 | return STATUS_INSUFFICIENT_RESOURCES; 116 | } 117 | 118 | memset(g_queue.data, 0, sizeof(struct flt_request) * REQUEST_QUEUE_SIZE); 119 | 120 | g_queue.head = g_queue.tail = 0; 121 | 122 | return STATUS_SUCCESS; 123 | } 124 | 125 | // init for user part starting 126 | NTSTATUS 127 | filter_init_2(void) 128 | { 129 | NTSTATUS status; 130 | 131 | if (g_queue.event_handle == NULL) { 132 | UNICODE_STRING str; 133 | OBJECT_ATTRIBUTES oa; 134 | 135 | RtlInitUnicodeString(&str, L"\\BaseNamedObjects\\tdifw_request"); 136 | InitializeObjectAttributes(&oa, &str, 0, NULL, NULL); 137 | 138 | status = ZwCreateEvent(&g_queue.event_handle, EVENT_ALL_ACCESS, &oa, SynchronizationEvent, FALSE); 139 | if (status != STATUS_SUCCESS) { 140 | KdPrint(("[tdi_fw] filter_init_2: ZwCreateEvent: 0x%x\n", status)); 141 | return status; 142 | } 143 | 144 | } 145 | 146 | if (g_queue.event == NULL) { 147 | status = ObReferenceObjectByHandle(g_queue.event_handle, EVENT_ALL_ACCESS, NULL, KernelMode, 148 | &g_queue.event, NULL); 149 | if (status != STATUS_SUCCESS) { 150 | KdPrint(("[tdi_fw] filter_init_2: ObReferenceObjectByHandle: 0x%x\n", status)); 151 | return status; 152 | } 153 | 154 | } 155 | 156 | // try to communicate with packet driver 157 | init_packet(); 158 | 159 | return STATUS_SUCCESS; 160 | } 161 | 162 | // cleanup for user part 163 | void 164 | filter_free_2(void) 165 | { 166 | free_packet(); 167 | 168 | if (g_queue.event != NULL) { 169 | ObDereferenceObject(g_queue.event); 170 | g_queue.event = NULL; 171 | } 172 | if (g_queue.event_handle != NULL) { 173 | ZwClose(g_queue.event_handle); 174 | g_queue.event_handle = NULL; 175 | } 176 | } 177 | 178 | // free 179 | void 180 | filter_free(void) 181 | { 182 | KIRQL irql; 183 | struct plist_entry *ple; 184 | int i; 185 | 186 | // clear all chains 187 | for (i = 0; i < MAX_CHAINS_COUNT; i++) 188 | clear_flt_chain(i); 189 | 190 | /* clear request queue */ 191 | KeAcquireSpinLock(&g_queue.guard, &irql); 192 | for (i = 0; i < REQUEST_QUEUE_SIZE; i++) { 193 | if (g_queue.data[i].pname != NULL) 194 | free(g_queue.data[i].pname); 195 | if (g_queue.data[i].sid_a != NULL) 196 | free(g_queue.data[i].sid_a); 197 | } 198 | free(g_queue.data); 199 | KeReleaseSpinLock(&g_queue.guard, irql); 200 | 201 | set_sid_list(NULL, 0); 202 | pid_pname_free(); 203 | } 204 | 205 | #define CHECK_BIT(char_mask, num) \ 206 | ((char_mask)[(num) / 8] & (1 << ((num) % 8))) 207 | 208 | // quick filter (I mean "synchronous" (can work at DISPATCH_LEVEL)) 209 | 210 | // To work as a library, tan wen changed this function. 211 | 212 | extern int tdifw_filter(struct flt_request *request); 213 | 214 | int quick_filter(struct flt_request *request, struct flt_rule *rule) 215 | { 216 | // In fact, I care nothing about rules. I simply call user's function 217 | // to deciede the result. 218 | struct flt_rule *myrule = rule; 219 | return tdifw_filter(request); 220 | } 221 | 222 | /* 223 | int 224 | quick_filter(struct flt_request *request, struct flt_rule *rule) 225 | { 226 | const struct sockaddr_in *from, *to; 227 | struct flt_rule *r; 228 | struct plist_entry *ple; 229 | KIRQL irql; 230 | int chain, result, sid_id; 231 | 232 | // not IP 233 | if (request->addr.len != sizeof(struct sockaddr_in) || 234 | request->addr.from.sa_family != AF_INET || 235 | request->addr.to.sa_family != AF_INET) 236 | { 237 | KdPrint(("[tdi_fw] quick_filter: not ip addr!\n")); 238 | return FILTER_DENY; 239 | } 240 | 241 | from = (const struct sockaddr_in *)&request->addr.from; 242 | to = (const struct sockaddr_in *)&request->addr.to; 243 | 244 | // default behavior: DENY and LOG 245 | result = FILTER_DENY; 246 | if (rule != NULL) { 247 | memset(rule, 0, sizeof(*rule)); 248 | rule->result = result; 249 | rule->log = TRUE; 250 | strcpy(rule->rule_id, "default"); 251 | } 252 | 253 | chain = pid_pname_get_context(request->pid); 254 | if (!g_rules.chain[chain].active) { 255 | // chain is not active; don't check request 256 | return result; 257 | } 258 | 259 | if (request->sid_a != NULL) 260 | sid_id = get_sid_id(request->sid_a, request->sid_a_size); 261 | else 262 | sid_id = 0; // default sid_id 263 | 264 | // quick filter 265 | KeAcquireSpinLock(&g_rules.guard, &irql); 266 | 267 | #define CHECK_ADDR_PORT(r_addr_from, r_mask_from, r_port_from, r_port2_from, \ 268 | r_addr_to, r_mask_to, r_port_to, r_port2_to) \ 269 | ((r_addr_from & r_mask_from) == (from->sin_addr.s_addr & r_mask_from) && \ 270 | (r_addr_to & r_mask_to) == (to->sin_addr.s_addr & r_mask_to) && \ 271 | (r_port_from == 0 || ((r_port2_from == 0) ? (r_port_from == from->sin_port) : \ 272 | (ntohs(from->sin_port) >= ntohs(r_port_from) && ntohs(from->sin_port) <= ntohs(r_port2_from)))) && \ 273 | (r_port_to == 0 || ((r_port2_to == 0) ? (r_port_to == to->sin_port) : \ 274 | (ntohs(to->sin_port) >= ntohs(r_port_to) && ntohs(to->sin_port) <= ntohs(r_port2_to))))) \ 275 | 276 | // go through rules 277 | for (r = g_rules.chain[chain].head; r != NULL; r = r->next) 278 | // Can anybody understand it? 279 | if ((r->proto == IPPROTO_ANY || r->proto == request->proto) && 280 | ((r->direction != DIRECTION_ANY && 281 | r->direction == request->direction && 282 | CHECK_ADDR_PORT(r->addr_from, r->mask_from, r->port_from, r->port2_from, 283 | r->addr_to, r->mask_to, r->port_to, r->port2_to)) || 284 | (r->direction == DIRECTION_ANY && 285 | ((request->direction == DIRECTION_OUT && 286 | CHECK_ADDR_PORT(r->addr_from, r->mask_from, r->port_from, r->port2_from, 287 | r->addr_to, r->mask_to, r->port_to, r->port2_to)) || 288 | (request->direction == DIRECTION_IN && 289 | CHECK_ADDR_PORT(r->addr_to, r->mask_to, r->port_to, 290 | r->port2_to, r->addr_from, r->mask_from, r->port_from, r->port2_from))))) && 291 | CHECK_BIT(r->sid_mask, sid_id)) 292 | { 293 | result = r->result; 294 | KdPrint(("[tdi_fw] quick_filter: found rule with result: %d\n", result)); 295 | 296 | if (rule != NULL) { 297 | memcpy(rule, r, sizeof(*rule)); 298 | 299 | rule->next = NULL; // useless field 300 | } 301 | 302 | break; 303 | } 304 | 305 | 306 | KeReleaseSpinLock(&g_rules.guard, irql); 307 | 308 | request->result = result; 309 | return result; 310 | } 311 | */ 312 | 313 | // write request to request queue 314 | BOOLEAN 315 | log_request(struct flt_request *request) 316 | { 317 | KIRQL irql, irql2; 318 | ULONG next_head; 319 | char pname_buf[256], *pname; 320 | struct plist_entry *ple; 321 | 322 | if (!g_got_log && request->type == TYPE_RESOLVE_PID) // don't log - no log app 323 | return FALSE; 324 | 325 | KeAcquireSpinLock(&g_queue.guard, &irql); 326 | 327 | next_head = (g_queue.head + 1) % REQUEST_QUEUE_SIZE; 328 | 329 | if (next_head == g_queue.tail) { 330 | // queue overflow: reject one entry from tail 331 | KdPrint(("[tdi_fw] log_request: queue overflow!\n")); 332 | 333 | request->log_skipped = g_queue.data[g_queue.tail].log_skipped + 1; 334 | 335 | // free process name & sid! 336 | if (g_queue.data[g_queue.tail].pname != NULL) 337 | free(g_queue.data[g_queue.tail].pname); 338 | if (g_queue.data[g_queue.tail].sid_a != NULL) 339 | free(g_queue.data[g_queue.tail].sid_a); 340 | 341 | g_queue.tail = (g_queue.tail + 1) % REQUEST_QUEUE_SIZE; 342 | 343 | } else 344 | request->log_skipped = 0; 345 | 346 | memcpy(&g_queue.data[g_queue.head], request, sizeof(struct flt_request)); 347 | 348 | // try to get process name 349 | pname = NULL; 350 | if (request->pid != (ULONG)-1 && 351 | pid_pname_resolve(request->pid, pname_buf, sizeof(pname_buf))) { 352 | 353 | KdPrint(("[tdi_fw] log_request: pid:%u; pname:%s\n", 354 | request->pid, pname_buf)); 355 | 356 | // ala strdup() 357 | pname = (char *)malloc_np(strlen(pname_buf) + 1); 358 | if (pname != NULL) 359 | strcpy(pname, pname_buf); 360 | else 361 | KdPrint(("[tdi_fw] log_request: malloc_np!\n")); 362 | } 363 | 364 | g_queue.data[g_queue.head].pname = pname; 365 | g_queue.head = next_head; 366 | 367 | // don't free sid & attributes 368 | if (request->sid_a != NULL) 369 | request->sid_a = NULL; 370 | 371 | KeReleaseSpinLock(&g_queue.guard, irql); 372 | 373 | // signal to user app 374 | if (g_queue.event != NULL) 375 | KeSetEvent(g_queue.event, IO_NO_INCREMENT, FALSE); 376 | 377 | return TRUE; 378 | } 379 | 380 | // read requests from log queue to buffer 381 | ULONG 382 | get_request(char *buf, ULONG buf_size) 383 | { 384 | ULONG result = 0; 385 | KIRQL irql; 386 | 387 | // sanity check 388 | if (buf_size < sizeof(struct flt_request)) 389 | return 0; 390 | 391 | KeAcquireSpinLock(&g_queue.guard, &irql); 392 | 393 | while (g_queue.head != g_queue.tail) { 394 | ULONG pname_size, sid_a_size; 395 | 396 | if (g_queue.data[g_queue.tail].pname != NULL) 397 | pname_size = strlen(g_queue.data[g_queue.tail].pname) + 1; 398 | else 399 | pname_size = 0; 400 | 401 | if (g_queue.data[g_queue.tail].sid_a != NULL) 402 | sid_a_size = g_queue.data[g_queue.tail].sid_a_size; 403 | else 404 | sid_a_size = 0; 405 | 406 | if (buf_size < sizeof(struct flt_request) + pname_size + sid_a_size) 407 | break; 408 | 409 | memcpy(buf, &g_queue.data[g_queue.tail], sizeof(struct flt_request)); 410 | 411 | if (g_queue.data[g_queue.tail].pname != NULL) { 412 | ((struct flt_request *)buf)->struct_size += pname_size; 413 | 414 | strcpy(buf + sizeof(struct flt_request), g_queue.data[g_queue.tail].pname); 415 | 416 | free(g_queue.data[g_queue.tail].pname); 417 | g_queue.data[g_queue.tail].pname = NULL; 418 | } 419 | 420 | if (g_queue.data[g_queue.tail].sid_a != NULL) { 421 | 422 | // make sid pointer relative only 423 | SID_AND_ATTRIBUTES *sid_a = g_queue.data[g_queue.tail].sid_a; 424 | 425 | sid_a->Sid = (PSID)((char *)(sid_a->Sid) - (char *)sid_a); 426 | 427 | // copy sid_a 428 | memcpy(buf + sizeof(struct flt_request) + pname_size, sid_a, sid_a_size); 429 | 430 | // free sid_a memory 431 | free(sid_a); 432 | g_queue.data[g_queue.tail].sid_a = NULL; 433 | 434 | // increase pname_size and struct size 435 | ((struct flt_request *)buf)->struct_size += sid_a_size; 436 | } 437 | 438 | result += sizeof(struct flt_request) + pname_size + sid_a_size; 439 | buf += sizeof(struct flt_request) + pname_size + sid_a_size; 440 | buf_size -= sizeof(struct flt_request) + pname_size + sid_a_size; 441 | 442 | g_queue.tail = (g_queue.tail + 1) % REQUEST_QUEUE_SIZE; 443 | } 444 | 445 | KdPrint(("[tdi_fw] get_request: copied %u bytes\n", result)); 446 | 447 | KeReleaseSpinLock(&g_queue.guard, irql); 448 | return result; 449 | } 450 | 451 | // add rule to rules chain 452 | NTSTATUS 453 | add_flt_rule(int chain, const struct flt_rule *rule) 454 | { 455 | NTSTATUS status; 456 | struct flt_rule *new_rule; 457 | KIRQL irql; 458 | 459 | // sanity check 460 | if (chain < 0 || chain >= MAX_CHAINS_COUNT) 461 | return STATUS_INVALID_PARAMETER_1; 462 | 463 | KeAcquireSpinLock(&g_rules.guard, &irql); 464 | 465 | new_rule = (struct flt_rule *)malloc_np(sizeof(struct flt_rule)); 466 | if (new_rule == NULL) { 467 | KdPrint(("[tdi_fw] add_flt_rule: malloc_np\n")); 468 | status = STATUS_INSUFFICIENT_RESOURCES; 469 | goto done; 470 | } 471 | 472 | memcpy(new_rule, rule, sizeof(*new_rule)); 473 | 474 | // append 475 | new_rule->next = NULL; 476 | 477 | if (g_rules.chain[chain].tail == NULL) { 478 | g_rules.chain[chain].head = new_rule; 479 | g_rules.chain[chain].tail = new_rule; 480 | } else { 481 | g_rules.chain[chain].tail->next = new_rule; 482 | g_rules.chain[chain].tail = new_rule; 483 | } 484 | 485 | status = STATUS_SUCCESS; 486 | 487 | done: 488 | KeReleaseSpinLock(&g_rules.guard, irql); 489 | return status; 490 | } 491 | 492 | // clear rules chain 493 | NTSTATUS 494 | clear_flt_chain(int chain) 495 | { 496 | struct flt_rule *rule; 497 | KIRQL irql; 498 | 499 | // sanity check 500 | if (chain < 0 || chain >= MAX_CHAINS_COUNT) 501 | return STATUS_INVALID_PARAMETER_1; 502 | 503 | /* rules chain */ 504 | KeAcquireSpinLock(&g_rules.guard, &irql); 505 | 506 | for (rule = g_rules.chain[chain].head; rule != NULL;) { 507 | struct flt_rule *rule2 = rule->next; 508 | free(rule); 509 | rule = rule2; 510 | } 511 | 512 | g_rules.chain[chain].head = NULL; 513 | g_rules.chain[chain].tail = NULL; 514 | 515 | if (g_rules.chain[chain].pname != NULL) { 516 | free(g_rules.chain[chain].pname); 517 | g_rules.chain[chain].pname = NULL; 518 | } 519 | 520 | // deactivate chain 521 | g_rules.chain[chain].active = FALSE; 522 | 523 | KeReleaseSpinLock(&g_rules.guard, irql); 524 | return STATUS_SUCCESS; 525 | } 526 | 527 | // set process name for chain 528 | NTSTATUS 529 | set_chain_pname(int chain, char *pname) 530 | { 531 | KIRQL irql; 532 | NTSTATUS status; 533 | 534 | // sanity check 535 | if (chain < 0 || chain >= MAX_CHAINS_COUNT) 536 | return STATUS_INVALID_PARAMETER_1; 537 | 538 | KdPrint(("[tdi_fw] set_chain_pname: setting name %s for chain %d\n", pname, chain)); 539 | 540 | KeAcquireSpinLock(&g_rules.guard, &irql); 541 | 542 | if (g_rules.chain[chain].pname != NULL) 543 | free(g_rules.chain[chain].pname); 544 | 545 | g_rules.chain[chain].pname = (char *)malloc_np(strlen(pname) + 1); 546 | if (g_rules.chain[chain].pname != NULL) { 547 | // copy pname 548 | strcpy(g_rules.chain[chain].pname, pname); 549 | status = STATUS_SUCCESS; 550 | } else 551 | status = STATUS_INSUFFICIENT_RESOURCES; 552 | 553 | KeReleaseSpinLock(&g_rules.guard, irql); 554 | return status; 555 | } 556 | 557 | // set result of process name by pid resolving 558 | NTSTATUS 559 | set_pid_pname(ULONG pid, char *pname) 560 | { 561 | KIRQL irql; 562 | int i, chain = 0; 563 | 564 | KdPrint(("[tdi_fw] set_pid_pname: setting pname %s for pid %u\n", pname, pid)); 565 | 566 | KeAcquireSpinLock(&g_rules.guard, &irql); 567 | for (i = 0; i < MAX_CHAINS_COUNT; i++) 568 | if (g_rules.chain[i].pname != NULL && 569 | _stricmp(pname, g_rules.chain[i].pname) == 0) { 570 | 571 | KdPrint(("[tdi_fw] set_pid_pname: found chain %d\n", i)); 572 | chain = i; 573 | 574 | break; 575 | } 576 | KeReleaseSpinLock(&g_rules.guard, irql); 577 | 578 | return pid_pname_set(pid, pname, chain); 579 | } 580 | 581 | // activate rules chain 582 | NTSTATUS 583 | activate_flt_chain(int chain) 584 | { 585 | // sanity check 586 | if (chain < 0 || chain >= MAX_CHAINS_COUNT) 587 | return STATUS_INVALID_PARAMETER_1; 588 | 589 | g_rules.chain[chain].active = TRUE; 590 | 591 | return STATUS_SUCCESS; 592 | } 593 | 594 | BOOLEAN 595 | default_chain_only(void) 596 | { 597 | int i; 598 | 599 | if (!g_rules.chain[0].active) 600 | return FALSE; 601 | 602 | for (i = 1; i < MAX_CHAINS_COUNT; i++) 603 | if (g_rules.chain[i].active) 604 | return FALSE; 605 | 606 | return TRUE; 607 | 608 | } 609 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/filter.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: filter.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | #ifndef _filter_h_ 16 | #define _filter_h_ 17 | 18 | #include "ipc.h" 19 | 20 | NTSTATUS filter_init(void); 21 | NTSTATUS filter_init_2(void); 22 | 23 | void filter_free(void); 24 | void filter_free_2(void); 25 | 26 | NTSTATUS add_flt_rule(int chain, const struct flt_rule *rule); 27 | NTSTATUS clear_flt_chain(int chain); 28 | NTSTATUS activate_flt_chain(int chain); 29 | NTSTATUS set_chain_pname(int chain, char *pname); 30 | NTSTATUS set_pid_pname(ULONG pid, char *pname); 31 | 32 | BOOLEAN default_chain_only(void); 33 | 34 | int quick_filter(struct flt_request *request, struct flt_rule *rule); 35 | 36 | BOOLEAN log_request(struct flt_request *request); 37 | ULONG get_request(char *buf, ULONG buf_size); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/ipc.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: ipc.c,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | /* 16 | * This file contain replaced TDI_EVENT_CONNECT handler 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "conn_state.h" 24 | #include "filter.h" 25 | #include "ipc.h" 26 | #include "sids.h" 27 | #include "tdi_fw.h" 28 | 29 | static void get_traffic_counters(unsigned __int64 *counters); 30 | 31 | NTSTATUS 32 | process_nfo_request(ULONG code, char *buf, ULONG *buf_len, ULONG buf_size) 33 | { 34 | NTSTATUS status; 35 | ULONG len = *buf_len; 36 | *buf_len = 0; 37 | 38 | switch (code) { 39 | 40 | case IOCTL_CMD_ENUM_LISTEN: 41 | // enum listening endpoints 42 | 43 | if (buf_size < sizeof(struct listen_nfo) || buf == NULL) { 44 | status = STATUS_INFO_LENGTH_MISMATCH; 45 | break; 46 | } 47 | 48 | status = enum_listen((struct listen_nfo *)buf, buf_len, buf_size); 49 | break; 50 | 51 | case IOCTL_CMD_ENUM_TCP_CONN: 52 | // enum TCP connections 53 | 54 | if (buf_size < sizeof(struct tcp_conn_nfo) || buf == NULL) { 55 | status = STATUS_INFO_LENGTH_MISMATCH; 56 | break; 57 | } 58 | 59 | status = enum_tcp_conn((struct tcp_conn_nfo *)buf, buf_len, buf_size); 60 | break; 61 | 62 | case IOCTL_CMD_GET_COUNTERS: 63 | // get traffic counters 64 | 65 | if (buf_size < sizeof(g_traffic)) { 66 | status = STATUS_INFO_LENGTH_MISMATCH; 67 | break; 68 | } 69 | 70 | get_traffic_counters((unsigned __int64 *)buf); 71 | 72 | *buf_len = sizeof(g_traffic); 73 | status = STATUS_SUCCESS; 74 | break; 75 | 76 | default: 77 | status = STATUS_NOT_SUPPORTED; 78 | } 79 | 80 | return status; 81 | } 82 | 83 | NTSTATUS 84 | process_request(ULONG code, char *buf, ULONG *buf_len, ULONG buf_size) 85 | { 86 | NTSTATUS status; 87 | ULONG len = *buf_len; 88 | *buf_len = 0; 89 | 90 | switch (code) { 91 | 92 | case IOCTL_CMD_GETREQUEST: 93 | // get data for logging 94 | 95 | if (buf_size < sizeof(struct flt_request) || buf == NULL) { 96 | status = STATUS_INFO_LENGTH_MISMATCH; 97 | break; 98 | } 99 | 100 | *buf_len = get_request(buf, buf_size); 101 | status = STATUS_SUCCESS; 102 | break; 103 | 104 | case IOCTL_CMD_CLEARCHAIN: 105 | // clear rules chain #i 106 | 107 | if (len != sizeof(int) || buf == NULL) { 108 | status = STATUS_INFO_LENGTH_MISMATCH; 109 | break; 110 | } 111 | 112 | status = clear_flt_chain(*(int *)buf); 113 | break; 114 | 115 | case IOCTL_CMD_APPENDRULE: 116 | // append rule to chain #i 117 | 118 | if (len != sizeof(struct flt_rule) || buf == NULL) { 119 | status = STATUS_INFO_LENGTH_MISMATCH; 120 | break; 121 | } 122 | 123 | status = add_flt_rule(((struct flt_rule *)buf)->chain, (struct flt_rule *)buf); 124 | break; 125 | 126 | case IOCTL_CMD_SETCHAINPNAME: 127 | // set chain #i process name 128 | 129 | if (len < sizeof(int) + sizeof(char) || buf == NULL) { 130 | status = STATUS_INFO_LENGTH_MISMATCH; 131 | break; 132 | } 133 | if (buf[len - 1] != '\0') { 134 | status = STATUS_INVALID_PARAMETER; // string must be zero-terminated 135 | break; 136 | } 137 | 138 | status = set_chain_pname(*(int *)buf, buf + sizeof(int)); 139 | break; 140 | 141 | case IOCTL_CMD_SETPNAME: 142 | // set process name for pid 143 | 144 | if (len < sizeof(ULONG) + sizeof(char) || buf == NULL) { 145 | status = STATUS_INFO_LENGTH_MISMATCH; 146 | break; 147 | } 148 | if (buf[len - 1] != '\0') { 149 | status = STATUS_INVALID_PARAMETER; // string must be zero-terminated 150 | break; 151 | } 152 | 153 | status = set_pid_pname(*(ULONG *)buf, buf + sizeof(ULONG)); 154 | break; 155 | 156 | case IOCTL_CMD_ACTIVATECHAIN: 157 | // active rules chain #i 158 | 159 | if (len != sizeof(int) || buf == NULL) { 160 | status = STATUS_INFO_LENGTH_MISMATCH; 161 | break; 162 | } 163 | 164 | status = activate_flt_chain(*(int *)buf); 165 | break; 166 | 167 | case IOCTL_CMD_SET_SIDS: 168 | // set SIDs array 169 | 170 | if (len < sizeof(ULONG)) { 171 | status = STATUS_INFO_LENGTH_MISMATCH; 172 | break; 173 | } 174 | 175 | status = set_sid_list(buf, len); 176 | break; 177 | 178 | case IOCTL_CMD_GET_COUNTERS: 179 | // get traffic counters 180 | 181 | if (buf_size < sizeof(g_traffic)) { 182 | status = STATUS_INFO_LENGTH_MISMATCH; 183 | break; 184 | } 185 | 186 | get_traffic_counters((unsigned __int64 *)buf); 187 | 188 | *buf_len = sizeof(g_traffic); 189 | status = STATUS_SUCCESS; 190 | break; 191 | 192 | default: 193 | status = STATUS_NOT_SUPPORTED; 194 | } 195 | 196 | return status; 197 | } 198 | 199 | void 200 | get_traffic_counters(unsigned __int64 *counters) 201 | { 202 | KIRQL irql; 203 | 204 | KeAcquireSpinLock(&g_traffic_guard, &irql); 205 | memcpy(counters, g_traffic, sizeof(g_traffic)); 206 | KeReleaseSpinLock(&g_traffic_guard, irql); 207 | } 208 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/ipc.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: ipc.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | #ifndef _ipc_h_ 16 | #define _ipc_h_ 17 | 18 | /* ioctls */ 19 | 20 | #define FILE_DEVICE_TDI_FW 0x8e86 21 | 22 | #define IOCTL_CMD_GETREQUEST CTL_CODE(FILE_DEVICE_TDI_FW, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) 23 | #define IOCTL_CMD_CLEARCHAIN CTL_CODE(FILE_DEVICE_TDI_FW, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) 24 | #define IOCTL_CMD_APPENDRULE CTL_CODE(FILE_DEVICE_TDI_FW, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) 25 | #define IOCTL_CMD_SETCHAINPNAME CTL_CODE(FILE_DEVICE_TDI_FW, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) 26 | #define IOCTL_CMD_SETPNAME CTL_CODE(FILE_DEVICE_TDI_FW, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) 27 | #define IOCTL_CMD_ACTIVATECHAIN CTL_CODE(FILE_DEVICE_TDI_FW, 0x806, METHOD_BUFFERED, FILE_ANY_ACCESS) 28 | #define IOCTL_CMD_SET_SIDS CTL_CODE(FILE_DEVICE_TDI_FW, 0x807, METHOD_BUFFERED, FILE_ANY_ACCESS) 29 | 30 | #define FILE_DEVICE_TDI_FW_NFO 0x8e87 31 | 32 | #define IOCTL_CMD_ENUM_LISTEN CTL_CODE(FILE_DEVICE_TDI_FW_NFO, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS) 33 | #define IOCTL_CMD_ENUM_TCP_CONN CTL_CODE(FILE_DEVICE_TDI_FW_NFO, 0x902, METHOD_BUFFERED, FILE_ANY_ACCESS) 34 | #define IOCTL_CMD_GET_COUNTERS CTL_CODE(FILE_DEVICE_TDI_FW_NFO, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS) 35 | 36 | /* 37 | * direction type for filter 38 | * for quick filter: 39 | * if proto == IPPROTO_TCP (DIRECTION_IN - accept connections; DIRECTION_OUT - connect) 40 | * if proto == IPPROTO_UDP (DIRECTION_IN - receive datagram; DIRECTION_OUT - send datagram) 41 | */ 42 | #define DIRECTION_IN 0 43 | #define DIRECTION_OUT 1 44 | #define DIRECTION_ANY -1 45 | 46 | /* filter result */ 47 | enum { 48 | FILTER_ALLOW = 1, 49 | FILTER_DENY, 50 | FILTER_PACKET_LOG, 51 | FILTER_PACKET_BAD, 52 | FILTER_DISCONNECT 53 | }; 54 | 55 | /* types of request */ 56 | enum { 57 | TYPE_CONNECT = 1, 58 | TYPE_DATAGRAM, 59 | TYPE_RESOLVE_PID, 60 | TYPE_CONNECT_ERROR, 61 | TYPE_LISTEN, 62 | TYPE_NOT_LISTEN, 63 | TYPE_CONNECT_CANCELED, 64 | TYPE_CONNECT_RESET, 65 | TYPE_CONNECT_TIMEOUT, 66 | TYPE_CONNECT_UNREACH, 67 | TYPE_PROCESS_CREATE, // add by tan wen 68 | TYPE_PROCESS_TERMINATE // add by tan wen 69 | }; 70 | 71 | #pragma pack(1) 72 | 73 | #define RULE_ID_SIZE 32 74 | 75 | /* 76 | * request for filter 77 | */ 78 | struct flt_request { 79 | int struct_size; /* should be sizeof(flt_request) */ 80 | 81 | int type; /* see TYPE_xxx */ 82 | ULONG status; /* for TYPE_CONNECT_xxx */ 83 | 84 | int result; /* see FILTER_xxx */ 85 | int direction; /* see DIRECTION_xxx */ 86 | int proto; /* see IPPROTO_xxx */ 87 | 88 | ULONG pid; 89 | ULONG sid_a_size; 90 | 91 | /* addr */ 92 | 93 | struct { 94 | struct sockaddr from; 95 | struct sockaddr to; 96 | int len; 97 | } addr; 98 | 99 | /* info from packet filter (valid for FILTER_PACKET_LOG) */ 100 | struct { 101 | int is_broadcast; // 0 or 1 (for now unused) 102 | UCHAR tcp_flags; 103 | UCHAR icmp_type; 104 | UCHAR icmp_code; 105 | int tcp_state; // see TCP_STATE_xxx 106 | } packet; 107 | 108 | /* info for logging */ 109 | 110 | ULONG log_skipped; 111 | ULONG log_bytes_in; 112 | ULONG log_bytes_out; 113 | char log_rule_id[RULE_ID_SIZE]; 114 | 115 | /* for internal use (like private:) */ 116 | 117 | char *pname; 118 | struct _SID_AND_ATTRIBUTES *sid_a; 119 | }; 120 | 121 | // I think 128 is a good number :-) (better than 256 :)) 122 | #define MAX_CHAINS_COUNT 128 123 | 124 | // how many users can be assigned per rule? (MUST: MAX_SIDS_COUNT % 8 == 0 !!!) 125 | #define MAX_SIDS_COUNT 128 126 | 127 | /* 128 | * IP rule for quick filter (addr & port are in network order) 129 | */ 130 | struct flt_rule { 131 | union { 132 | struct flt_rule *next; // for internal use 133 | int chain; // useful for IOCTL_CMD_APPENDRULE 134 | }; 135 | int result; 136 | int proto; 137 | int direction; 138 | ULONG addr_from; 139 | ULONG mask_from; 140 | USHORT port_from; 141 | USHORT port2_from; /* if nonzero use port range from port_from */ 142 | ULONG addr_to; 143 | ULONG mask_to; 144 | USHORT port_to; 145 | USHORT port2_to; /* if nonzero use port range from port_to */ 146 | int log; /* see RULE_LOG_xxx */ 147 | 148 | UCHAR sid_mask[MAX_SIDS_COUNT / 8]; /* SIDs bitmask */ 149 | 150 | char rule_id[RULE_ID_SIZE]; 151 | }; 152 | 153 | #define RULE_LOG_NOLOG 0 154 | #define RULE_LOG_LOG 1 155 | #define RULE_LOG_COUNT 2 156 | 157 | #define IPPROTO_ANY -1 158 | 159 | /* 160 | * Entry for listen info 161 | */ 162 | struct listen_nfo { 163 | int ipproto; 164 | ULONG addr; 165 | USHORT port; 166 | ULONG pid; 167 | }; 168 | 169 | /* 170 | * TCP states 171 | */ 172 | enum { 173 | TCP_STATE_NONE, 174 | TCP_STATE_SYN_SENT, 175 | TCP_STATE_SYN_RCVD, 176 | TCP_STATE_ESTABLISHED_IN, 177 | TCP_STATE_ESTABLISHED_OUT, 178 | TCP_STATE_FIN_WAIT1, 179 | TCP_STATE_FIN_WAIT2, 180 | TCP_STATE_TIME_WAIT, 181 | TCP_STATE_CLOSE_WAIT, 182 | TCP_STATE_LAST_ACK, 183 | TCP_STATE_CLOSED, 184 | 185 | TCP_STATE_MAX 186 | }; 187 | 188 | /* 189 | * Entry for connection info 190 | */ 191 | struct tcp_conn_nfo { 192 | int state; 193 | ULONG laddr; 194 | USHORT lport; 195 | ULONG raddr; 196 | USHORT rport; 197 | ULONG pid; 198 | ULONG bytes_in; 199 | ULONG bytes_out; 200 | }; 201 | 202 | /* 203 | * traffic counters for IOCTL_CMD_GET_COUNTERS 204 | */ 205 | enum { 206 | TRAFFIC_TOTAL_IN, 207 | TRAFFIC_TOTAL_OUT, 208 | TRAFFIC_COUNTED_IN, 209 | TRAFFIC_COUNTED_OUT, 210 | 211 | TRAFFIC_MAX 212 | }; 213 | 214 | 215 | #pragma pack() 216 | 217 | #endif 218 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/memtrack.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: memtrack.c,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | #if DBG 16 | 17 | /* 18 | * Debug NonPaged pool routines (helpers to find memory leaks and pool corruption) 19 | */ 20 | 21 | #include 22 | 23 | #include "memtrack.h" 24 | 25 | #define MAGIC 'TMEM' 26 | #define INT_3 __asm int 3 27 | 28 | struct prefix { 29 | ULONG magic; 30 | struct prefix *next; 31 | struct prefix *prev; 32 | ULONG size; 33 | const char *file; 34 | ULONG line; 35 | char data[]; 36 | }; 37 | 38 | struct postfix { 39 | ULONG size; 40 | ULONG magic; 41 | }; 42 | 43 | static KSPIN_LOCK guard; 44 | static struct prefix *first, *last; 45 | static ULONG count; 46 | 47 | static struct postfix *check(struct prefix *p); 48 | 49 | void 50 | memtrack_init() 51 | { 52 | KeInitializeSpinLock(&guard); 53 | } 54 | 55 | void 56 | memtrack_free() 57 | { 58 | KIRQL irql; 59 | ULONG total = 0; 60 | 61 | KeAcquireSpinLock(&guard, &irql); 62 | 63 | if (first != NULL) { 64 | struct prefix *p; 65 | for (p = first; p; p = p->next) { 66 | check(p); 67 | 68 | KdPrint(("memtrack: memory leak detected! %s:%u (%u bytes)\n", 69 | p->file, p->line, p->size)); 70 | 71 | total += p->size; 72 | } 73 | } 74 | 75 | KeReleaseSpinLock(&guard, irql); 76 | KdPrint(("memtrack: Total memory leakage: %u bytes (%u blocks)\n", total, count)); 77 | 78 | if (total) INT_3; 79 | } 80 | 81 | void * 82 | mt_malloc(ULONG size, const char *file, ULONG line) 83 | { 84 | KIRQL irql; 85 | struct prefix *data; 86 | struct postfix *pd; 87 | 88 | #if 1 89 | // check pool integrity 90 | KeAcquireSpinLock(&guard, &irql); 91 | 92 | for (data = first; data; data = data->next) 93 | check(data); 94 | 95 | for (data = last; data; data = data->prev) 96 | check(data); 97 | 98 | KeReleaseSpinLock(&guard, irql); 99 | #endif 100 | 101 | if (size == 0) { 102 | KdPrint(("memtrack: mt_malloc: size == 0!\n")); 103 | INT_3; 104 | return NULL; 105 | } 106 | 107 | data = (struct prefix *)ExAllocatePool(NonPagedPool, 108 | sizeof(struct prefix) + size + sizeof(struct postfix)); 109 | if (data == NULL) 110 | return NULL; 111 | 112 | data->magic = MAGIC; 113 | data->next = NULL; 114 | data->prev = NULL; 115 | data->size = size; 116 | data->file = file; 117 | data->line = line; 118 | 119 | memset(data->data, 0xcc, size); // fill by 0xcc: new 120 | 121 | pd = (struct postfix *)(data->data + data->size); 122 | 123 | pd->size = size; 124 | pd->magic = MAGIC; 125 | 126 | KeAcquireSpinLock(&guard, &irql); 127 | 128 | if (last) { 129 | last->next = data; 130 | data->prev = last; 131 | last = data; 132 | } 133 | else { 134 | data->prev = NULL; 135 | first = last = data; 136 | } 137 | count++; 138 | 139 | KeReleaseSpinLock(&guard, irql); 140 | return data->data; 141 | } 142 | 143 | void 144 | free(void *ptr) 145 | { 146 | KIRQL irql; 147 | struct prefix *data = (struct prefix *)((char *)ptr - sizeof(struct prefix)); 148 | struct postfix *pd = check(data); 149 | 150 | if (pd == NULL) 151 | return; 152 | 153 | KeAcquireSpinLock(&guard, &irql); 154 | 155 | if (data->next != NULL) 156 | data->next->prev = data->prev; 157 | else 158 | last = data->prev; 159 | if (data->prev != NULL) 160 | data->prev->next = data->next; 161 | else 162 | first = data->next; 163 | 164 | memset(data->data, 0xc9, data->size); // fill by 0xc9: free 165 | 166 | data->size = (ULONG)-1; 167 | pd->size = (ULONG)-1; 168 | 169 | count--; 170 | KeReleaseSpinLock(&guard, irql); 171 | 172 | ExFreePool(data); 173 | } 174 | 175 | struct postfix * 176 | check(struct prefix *p) 177 | { 178 | struct postfix *pd; 179 | 180 | if (p->magic != MAGIC) { 181 | KdPrint(("memtrack: check: invalid pre-magic! 0x%x\n", p)); 182 | INT_3; 183 | return NULL; 184 | } 185 | 186 | pd = (struct postfix *)(p->data + p->size); 187 | 188 | if (pd->magic != MAGIC) { 189 | KdPrint(("memtrack: memtrack_free: invalid post-magic! 0x%x\n", pd)); 190 | INT_3; 191 | return NULL; 192 | } 193 | 194 | if (p->size != pd->size) { 195 | KdPrint(("memtrack: memtracl_free: invalid post-size! 0x%x 0x%x\n", p, pd)); 196 | INT_3; 197 | return NULL; 198 | } 199 | 200 | return pd; 201 | } 202 | 203 | 204 | #endif /* DBG */ 205 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/memtrack.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: memtrack.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | #ifndef _memtrack_h_ 16 | #define _memtrack_h_ 17 | 18 | #define MEM_TAG '1VRD' 19 | 20 | #if DBG 21 | 22 | void memtrack_init(void); 23 | void memtrack_free(void); 24 | 25 | void *mt_malloc(ULONG size, const char *file, ULONG line); 26 | 27 | // allocate memory from nonpaged pool 28 | #define malloc_np(size) mt_malloc((size), __FILE__, __LINE__) 29 | 30 | void free(void *ptr); 31 | 32 | // debug macro 33 | #define _TEST_ME_ __asm int 3 34 | 35 | #else /* DBG */ 36 | 37 | #define memtrack_init() 38 | #define memtrack_free() 39 | 40 | #define malloc_np(size) ExAllocatePoolWithTag(NonPagedPool, (size), MEM_TAG) 41 | #define free(ptr) ExFreePool(ptr) 42 | 43 | 44 | #define _TEST_ME_ 45 | 46 | #endif /* DBG */ 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/ndis_hk_ioctl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: ndis_hk_ioctl.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | /** 16 | * @file ndis_hk_ioctl.h 17 | * I/O controls and related definitions for ndis_hk control device 18 | */ 19 | 20 | #ifndef _ndis_hk_ioctl_h_ 21 | #define _ndis_hk_ioctl_h_ 22 | 23 | /* device ioctls (for kernel mode use only; internal) */ 24 | 25 | /** MAGIC number for ndis_hk device (useless) */ 26 | #define FILE_DEVICE_NDIS_HK 0x0000c501 27 | 28 | /** 29 | * Get kernel-mode interface of hooking driver. 30 | * input buffer: (optional) ULONG if_version 31 | * output buffer: struct ndis_hk 32 | */ 33 | #define IOCTL_CMD_GET_KM_IFACE CTL_CODE(FILE_DEVICE_NDIS_HK, 0x801, METHOD_BUFFERED, FILE_READ_DATA) 34 | 35 | /* ndis_hk kernel-mode interface */ 36 | 37 | #if 0 38 | enum { 39 | DIRECTION_IN = 0, /**< input direction of packets (from network to protocol driver) */ 40 | DIRECTION_OUT = 1 /**< output direction of packets (from protocol driver to network) */ 41 | }; 42 | #endif 43 | 44 | /** 45 | * Main filter function to process input (from upper filter) or output (from lower filter) packet. 46 | * 47 | * executed at DISPATCH_LEVEL 48 | * 49 | * return value: FALSE don't pass unchanged packet to receiver 50 | * if (packet_unchanged == FALSE) function MUST return FALSE 51 | * 52 | * if function want to pass the packet to next filter in stack: 53 | * for DIRECTION_IN: self->lower->process_packet(direction, iface, packet, self->lower, packet_unchanged); 54 | * for DIRECTION_OUT: self->upper->process_packet(direction, iface, packet, self->upper, packet_unchanged); 55 | */ 56 | typedef BOOLEAN process_packet_t( 57 | int direction, int iface, PNDIS_PACKET packet, struct filter_nfo *self, 58 | BOOLEAN packet_unchanged); 59 | 60 | /** 61 | * Function to process interface PnP events. 62 | * 63 | * executed at PASSIVE_LEVEL 64 | * 65 | * For details of NetPnpEvent see DDK documentation. 66 | * If return status is not NDIS_STATUS_SUCCESS don't call next handler in chain. 67 | */ 68 | typedef NDIS_STATUS pnp_event_t( 69 | int iface, PNET_PNP_EVENT NetPnPEvent); 70 | 71 | /** Filter information for attach_filter */ 72 | struct filter_nfo { 73 | int size; /*<< size of structure */ 74 | 75 | process_packet_t *process_packet; /**< function to process packet */ 76 | 77 | struct filter_nfo *upper; /**< upper filter (process input) */ 78 | struct filter_nfo *lower; /**< lower filter (process output) */ 79 | 80 | void *param; /**< place for caller's static param */ 81 | 82 | pnp_event_t *pnp_event; /**< PnP event callback */ 83 | }; 84 | 85 | #ifndef NDIS_HK_INTERFACE_VER 86 | /** the latest NDIS_HK_INTERFACE_VER */ 87 | # define NDIS_HK_INTERFACE_VER 2 88 | #endif 89 | 90 | /** ndis_hk kernel-mode interface */ 91 | struct ndis_hk_interface { 92 | ULONG version; /**< should be NDIS_HK_INTERFACE_VER */ 93 | 94 | /** 95 | * Get list of adapters 96 | * @param buf output buffer for adapter names 97 | * @param buf_size size in wchar_t of buf (can be 0) 98 | * @return number of wchar_t has to be in buffer 99 | * if greater than buf_size only partial information has been copied 100 | * @see get_adapter_list 101 | */ 102 | int (*get_adapter_list)(wchar_t *buf, int buf_size); 103 | 104 | /** 105 | * Attach or remove filter 106 | * @param flt information about packet filter 107 | * @param add TRUE - attach filter; FALSE - remove filter 108 | * @param to_top TRUE - for attaching to top of stack (useless with add == FALSE) 109 | * @see attach_filter 110 | */ 111 | void (*attach_filter)(struct filter_nfo *flt, BOOLEAN add, BOOLEAN to_top); 112 | 113 | #if NDIS_HK_INTERFACE_VER > 1 114 | 115 | /** 116 | * NDIS request on hooked adapter 117 | * @param iface interface index 118 | * @param req request (see DDK documentation) 119 | * @return status 120 | */ 121 | NDIS_STATUS (*ndis_request)(int iface, NDIS_REQUEST *req); 122 | 123 | #endif 124 | 125 | #if NDIS_HK_INTERFACE_VER > 2 126 | // add future definitions here... 127 | #endif 128 | }; 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/net.h: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 2 | // 3 | // $Id: net.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 4 | 5 | #ifndef _net_h_ 6 | #define _net_h_ 7 | 8 | /* 9 | * network definitions 10 | */ 11 | 12 | #pragma pack(1) 13 | 14 | struct ether_hdr { 15 | UCHAR ether_dhost[6]; 16 | UCHAR ether_shost[6]; 17 | USHORT ether_type; 18 | }; 19 | 20 | #define ETHERTYPE_IP 0x0800 /* IP protocol */ 21 | 22 | #define IP_DF 0x4000 /* dont fragment flag */ 23 | #define IP_MF 0x2000 /* more fragments flag */ 24 | #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ 25 | 26 | struct ip_hdr { 27 | UCHAR ip_hl:4; /* header length */ 28 | UCHAR ip_v:4; /* version */ 29 | UCHAR ip_tos; /* type of service */ 30 | USHORT ip_len; /* total length */ 31 | USHORT ip_id; /* identification */ 32 | USHORT ip_off; /* fragment offset field */ 33 | UCHAR ip_ttl; /* time to live */ 34 | UCHAR ip_p; /* protocol */ 35 | USHORT ip_sum; /* checksum */ 36 | ULONG ip_src; /* source address */ 37 | ULONG ip_dst; /* dest address */ 38 | }; 39 | 40 | struct icmp_hdr { 41 | UCHAR icmp_type; /* type of message */ 42 | UCHAR icmp_code; /* type sub code */ 43 | USHORT icmp_cksum; /* ones complement cksum of struct */ 44 | }; 45 | 46 | struct udp_hdr { 47 | USHORT uh_sport; /* source port */ 48 | USHORT uh_dport; /* destination port */ 49 | USHORT uh_ulen; /* udp length */ 50 | USHORT uh_sum; /* udp checksum */ 51 | }; 52 | 53 | #define TH_FIN 0x01 54 | #define TH_SYN 0x02 55 | #define TH_RST 0x04 56 | #define TH_PUSH 0x08 57 | #define TH_ACK 0x10 58 | #define TH_URG 0x20 59 | 60 | struct tcp_hdr { 61 | USHORT th_sport; /* source port */ 62 | USHORT th_dport; /* destination port */ 63 | ULONG th_seq; /* sequence number */ 64 | ULONG th_ack; /* acknowledgement number */ 65 | 66 | UCHAR th_x2:4; /* (unused) */ 67 | UCHAR th_off:4; /* data offset */ 68 | UCHAR th_flags; 69 | 70 | USHORT th_win; /* window */ 71 | USHORT th_sum; /* checksum */ 72 | USHORT th_urp; /* urgent pointer */ 73 | }; 74 | 75 | #pragma pack() 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/obj_tbl.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: obj_tbl.c,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | /* 16 | * Working with connection objects, address objects and links between them 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | #include "conn_state.h" 24 | #include "memtrack.h" 25 | #include "obj_tbl.h" 26 | #include "sids.h" 27 | #include "tdi_fw.h" 28 | 29 | // for searching objects information by file object 30 | 31 | #define HASH_SIZE 0x1000 32 | #define CALC_HASH(fileobj) (((ULONG)(fileobj) >> 5) % HASH_SIZE) 33 | 34 | static struct ot_entry **g_ot_hash; 35 | KSPIN_LOCK g_ot_hash_guard; 36 | 37 | // for searching connection objects by address object & connection context 38 | 39 | struct ctx_entry { 40 | struct ctx_entry *next; 41 | PFILE_OBJECT addrobj; 42 | CONNECTION_CONTEXT conn_ctx; 43 | PFILE_OBJECT connobj; 44 | }; 45 | 46 | static struct ctx_entry **g_cte_hash; 47 | KSPIN_LOCK g_cte_hash_guard; 48 | 49 | //---------------------------------------------------------------------------- 50 | 51 | NTSTATUS 52 | ot_init(void) 53 | { 54 | g_ot_hash = (struct ot_entry **)malloc_np(sizeof(*g_ot_hash) * HASH_SIZE); 55 | if (g_ot_hash == NULL) { 56 | KdPrint(("[tdi_fw] ot_init: malloc_np\n")); 57 | return STATUS_INSUFFICIENT_RESOURCES; 58 | } 59 | memset(g_ot_hash, 0, sizeof(*g_ot_hash) * HASH_SIZE); 60 | 61 | KeInitializeSpinLock(&g_ot_hash_guard); 62 | 63 | g_cte_hash = (struct ctx_entry **)malloc_np(sizeof(*g_cte_hash) * HASH_SIZE); 64 | if (g_cte_hash == NULL) { 65 | KdPrint(("[tdi_fw] ot_init: malloc_np\n")); 66 | free(g_ot_hash); 67 | return STATUS_INSUFFICIENT_RESOURCES; 68 | } 69 | memset(g_cte_hash, 0, sizeof(*g_cte_hash) * HASH_SIZE); 70 | 71 | KeInitializeSpinLock(&g_cte_hash_guard); 72 | 73 | return STATUS_SUCCESS; 74 | } 75 | 76 | void 77 | ot_free(void) 78 | { 79 | KIRQL irql; 80 | int i; 81 | struct ot_entry *ote; 82 | 83 | if (g_ot_hash == NULL) 84 | return; // have nothing to do 85 | 86 | // do cleanup for address & connection objects 87 | for (i = 0; i < HASH_SIZE; i++) { 88 | 89 | for (;;) { // do it again and again 90 | PFILE_OBJECT connobj = NULL, event_addrobj = NULL; 91 | PVOID event_handler = NULL, event_context = NULL; 92 | int event_type; 93 | PDEVICE_OBJECT devobj = NULL; 94 | 95 | KeAcquireSpinLock(&g_ot_hash_guard, &irql); 96 | 97 | for (ote = g_ot_hash[i]; ote != NULL; ote = ote->next) { 98 | 99 | if (ote->fileobj == NULL) 100 | continue; // skip processed items 101 | 102 | #ifdef _USE_TDI_HOOKING 103 | devobj = ote->devobj; 104 | #else 105 | devobj = get_original_devobj(ote->devobj, NULL); 106 | #endif 107 | 108 | if (ote->type == FILEOBJ_ADDROBJ) { 109 | // find at least one event handler & remove it @ PASSIVE level 110 | int j; 111 | 112 | event_addrobj = ote->fileobj; 113 | 114 | for (j = 0; j < MAX_EVENT; j++) 115 | if (ote->ctx[j].old_handler != NULL) { 116 | 117 | event_type = j; 118 | event_handler = ote->ctx[j].old_handler; 119 | event_context = ote->ctx[j].old_context; 120 | 121 | KdPrint(("[tdi_fw] ot_free: got event handler to restore (addrobj: 0x%x; type: %d; handler: 0x%x; context: 0x%x\n", 122 | event_addrobj, 123 | event_type, 124 | event_handler, 125 | event_context)); 126 | 127 | ote->ctx[j].old_handler = NULL; 128 | 129 | break; 130 | } 131 | 132 | if (event_handler != NULL) 133 | break; 134 | 135 | KdPrint(("[tdi_fw] ot_free: no event handlers for addrobj: 0x%x\n", 136 | ote->fileobj)); 137 | 138 | // remove this addrobj from "LISTEN" state 139 | if (ote->listen_entry != NULL) { 140 | del_listen_obj(ote->listen_entry, FALSE); 141 | ote->listen_entry = NULL; 142 | } 143 | 144 | // no event handlers 145 | ote->fileobj = NULL; 146 | 147 | } else if (ote->type == FILEOBJ_CONNOBJ) { 148 | // check connobj is connected (remote addr is not 0) 149 | TA_ADDRESS *remote_addr = (TA_ADDRESS *)(ote->remote_addr); 150 | 151 | if (((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr == 0) { 152 | KdPrint(("[tdi_fw] ot_free: connobj 0x%x is not connected\n", connobj)); 153 | 154 | } else { 155 | // disconnect this connection using TDI_DISCONNECT @ PASSIVE level 156 | connobj = ote->fileobj; 157 | 158 | KdPrint(("[tdi_fw] ot_free: got connobj 0x%x (%x:%x) to disconnect\n", 159 | connobj, 160 | ((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr, 161 | ((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port)); 162 | } 163 | 164 | // remove this connobj from "CONNECTED" state 165 | if (ote->conn_entry != NULL) { 166 | del_tcp_conn_obj(ote->conn_entry, FALSE); 167 | ote->conn_entry = NULL; 168 | 169 | // TODO: check if state TCP_STATE_TIME_WAIT don't delete it 170 | } 171 | 172 | // skip this object next time 173 | ote->fileobj = NULL; 174 | } 175 | } 176 | 177 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 178 | 179 | // we're at PASSIVE level 180 | 181 | if (event_handler != NULL) { 182 | // set old event handler 183 | PIRP query_irp; 184 | NTSTATUS status; 185 | 186 | KdPrint(("[tdi_fw] ot_free: got event handler to restore (addrobj: 0x%x; type: %d; handler: 0x%x; context: 0x%x\n", 187 | event_addrobj, 188 | event_type, 189 | event_handler, 190 | event_context)); 191 | 192 | query_irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, 193 | devobj, event_addrobj, NULL, NULL); 194 | if (query_irp == NULL) { 195 | KdPrint(("[tdi_fw] ot_free: TdiBuildInternalDeviceControlIrp\n")); 196 | continue; 197 | } 198 | 199 | TdiBuildSetEventHandler(query_irp, devobj, event_addrobj, NULL, NULL, 200 | event_type, event_handler, event_context); 201 | 202 | status = IoCallDriver(devobj, query_irp); 203 | if (status != STATUS_SUCCESS) 204 | KdPrint(("[tdi_fw] ot_free: IoCallDriver(set_event_handler): 0x%x\n", status)); 205 | 206 | } else if (connobj != NULL) { 207 | // disconnect connection 208 | PIRP query_irp; 209 | NTSTATUS status; 210 | 211 | KdPrint(("[tdi_fw] ot_free: disconnecting connobj 0x%x\n", connobj)); 212 | 213 | query_irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT, 214 | devobj, connobj, NULL, NULL); 215 | if (query_irp == NULL) { 216 | KdPrint(("[tdi_fw] ot_free: TdiBuildInternalDeviceControlIrp\n")); 217 | continue; 218 | } 219 | 220 | // using TDI_DISCONNECT_RELEASE to make ClientEventDisconnect to be called 221 | TdiBuildDisconnect(query_irp, devobj, connobj, NULL, NULL, NULL, 222 | TDI_DISCONNECT_RELEASE, NULL, NULL); 223 | 224 | status = IoCallDriver(devobj, query_irp); 225 | if (status != STATUS_SUCCESS) 226 | KdPrint(("[tdi_fw] ot_free: IoCallDriver(disconnect): 0x%x\n", status)); 227 | 228 | } else { 229 | 230 | // no objects to process. break! 231 | 232 | break; 233 | } 234 | } 235 | } 236 | 237 | // clear it! 238 | KeAcquireSpinLock(&g_ot_hash_guard, &irql); 239 | 240 | for (i = 0; i < HASH_SIZE; i++) { 241 | struct ot_entry *ote = g_ot_hash[i]; 242 | while (ote != NULL) { 243 | struct ot_entry *ote2 = ote->next; 244 | 245 | KdPrint(("[tdi_fw] ot_free: Warning! fileobj 0x%x type %d exists!\n", 246 | ote->fileobj, ote->type)); 247 | 248 | if (ote->sid_a != NULL) 249 | free(ote->sid_a); 250 | free(ote); 251 | 252 | ote = ote2; 253 | } 254 | } 255 | free(g_ot_hash); 256 | g_ot_hash = NULL; 257 | 258 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 259 | 260 | // and cleanup cte_hash 261 | if (g_cte_hash != NULL) { 262 | KeAcquireSpinLock(&g_cte_hash_guard, &irql); 263 | 264 | for (i = 0; i < HASH_SIZE; i++) { 265 | struct ctx_entry *cte = g_cte_hash[i]; 266 | while (cte) { 267 | struct ctx_entry *cte2 = cte->next; 268 | free(cte); 269 | cte = cte2; 270 | } 271 | } 272 | free(g_cte_hash); 273 | g_cte_hash = NULL; 274 | 275 | KeReleaseSpinLock(&g_cte_hash_guard, irql); 276 | } 277 | } 278 | 279 | //---------------------------------------------------------------------------- 280 | 281 | NTSTATUS 282 | ot_add_fileobj(PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj, int fileobj_type, int ipproto, 283 | CONNECTION_CONTEXT conn_ctx) // must be called at PASSIVE_LEVEL! 284 | { 285 | ULONG hash = CALC_HASH(fileobj); 286 | KIRQL irql; 287 | struct ot_entry *ote; 288 | NTSTATUS status; 289 | int i; 290 | SID_AND_ATTRIBUTES *sid_a; 291 | ULONG sid_a_size; 292 | 293 | if (fileobj == NULL) 294 | return STATUS_INVALID_PARAMETER_2; 295 | 296 | // while we're at PASSIVE_LEVEL get SID & attributes 297 | sid_a = get_current_sid_a(&sid_a_size); 298 | 299 | KeAcquireSpinLock(&g_ot_hash_guard, &irql); 300 | 301 | for (ote = g_ot_hash[hash]; ote != NULL; ote = ote->next) 302 | if (ote->fileobj == fileobj) 303 | break; 304 | 305 | if (ote == NULL) { 306 | ote = (struct ot_entry *)malloc_np(sizeof(*ote)); 307 | if (ote == NULL) { 308 | KdPrint(("[tdi_fw] ot_add_fileobj: malloc_np\n")); 309 | status = STATUS_INSUFFICIENT_RESOURCES; 310 | goto done; 311 | } 312 | memset(ote, 0, sizeof(*ote)); 313 | 314 | ote->next = g_ot_hash[hash]; 315 | g_ot_hash[hash] = ote; 316 | 317 | ote->fileobj = fileobj; 318 | for (i = 0; i < MAX_EVENT; i++) 319 | ote->ctx[i].fileobj = fileobj; 320 | 321 | } else { 322 | KdPrint(("[tdi_fw] ot_add_fileobj: reuse fileobj 0x%x\n", fileobj)); 323 | 324 | ot_cleanup_ote(ote); 325 | } 326 | 327 | ote->signature = 'OTE '; 328 | ote->pid = (ULONG)PsGetCurrentProcessId(); 329 | 330 | // save SID & attributes 331 | ote->sid_a = sid_a; 332 | ote->sid_a_size = sid_a_size; 333 | sid_a = NULL; 334 | 335 | ote->devobj = devobj; 336 | 337 | ote->type = fileobj_type; 338 | ote->ipproto = ipproto; 339 | ote->conn_ctx = conn_ctx; 340 | 341 | status = STATUS_SUCCESS; 342 | 343 | done: 344 | // cleanup 345 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 346 | if (sid_a != NULL) 347 | free(sid_a); 348 | 349 | return status; 350 | } 351 | 352 | NTSTATUS 353 | ot_del_fileobj(PFILE_OBJECT fileobj, int *fileobj_type) 354 | { 355 | ULONG hash = CALC_HASH(fileobj); 356 | KIRQL irql; 357 | struct ot_entry *ote, *prev_ote; 358 | NTSTATUS status; 359 | 360 | if (fileobj == NULL) 361 | return STATUS_INVALID_PARAMETER_1; 362 | 363 | KeAcquireSpinLock(&g_ot_hash_guard, &irql); 364 | 365 | prev_ote = NULL; 366 | for (ote = g_ot_hash[hash]; ote; ote = ote->next) { 367 | if (ote->fileobj == fileobj) 368 | break; 369 | prev_ote = ote; 370 | } 371 | 372 | if (ote == NULL) { 373 | KdPrint(("[tdi_fw] ot_del_fileobj: fileobj 0x%x not found!\n", fileobj)); 374 | status = STATUS_OBJECT_NAME_NOT_FOUND; 375 | goto done; 376 | } 377 | 378 | if (ote->type == FILEOBJ_ADDROBJ && ote->listen_entry != NULL) 379 | del_listen_obj(ote->listen_entry, FALSE); 380 | else if (ote->type == FILEOBJ_CONNOBJ && ote->conn_entry != NULL) { 381 | if (ote->ipproto == IPPROTO_TCP && ote->log_disconnect) 382 | log_disconnect(ote); 383 | 384 | del_tcp_conn_obj(ote->conn_entry, FALSE); 385 | } 386 | 387 | if (fileobj_type != NULL) 388 | *fileobj_type = ote->type; 389 | 390 | if (prev_ote != NULL) 391 | prev_ote->next = ote->next; 392 | else 393 | g_ot_hash[hash] = ote->next; 394 | 395 | if (ote->sid_a != NULL) 396 | free(ote->sid_a); 397 | 398 | free(ote); 399 | 400 | status = STATUS_SUCCESS; 401 | 402 | done: 403 | KeReleaseSpinLock(&g_ot_hash_guard, irql); 404 | 405 | return status; 406 | } 407 | 408 | struct ot_entry * 409 | ot_find_fileobj(PFILE_OBJECT fileobj, KIRQL *irql) 410 | { 411 | ULONG hash = CALC_HASH(fileobj); 412 | struct ot_entry *ote; 413 | 414 | if (fileobj == NULL) 415 | return NULL; 416 | 417 | if (irql != NULL) 418 | KeAcquireSpinLock(&g_ot_hash_guard, irql); 419 | 420 | for (ote = g_ot_hash[hash]; ote != NULL; ote = ote->next) 421 | if (ote->fileobj == fileobj) 422 | break; 423 | 424 | if (ote == NULL) { 425 | KdPrint(("[tdi_fw] ot_find_fileobj: fileobj 0x%x not found!\n", fileobj)); 426 | if (irql != NULL) 427 | KeReleaseSpinLock(&g_ot_hash_guard, *irql); 428 | } 429 | 430 | return ote; 431 | } 432 | 433 | void 434 | ot_cleanup_ote(struct ot_entry *ote) 435 | { 436 | struct ot_entry *saved_next; 437 | PFILE_OBJECT saved_fileobj; 438 | unsigned int i; 439 | 440 | // set all fields to zero except "next" and "fileobj" (cleanup listen/conn_entry if any) 441 | 442 | saved_next = ote->next; 443 | saved_fileobj = ote->fileobj; 444 | 445 | if (ote->type == FILEOBJ_ADDROBJ && ote->listen_entry != NULL) { 446 | 447 | del_listen_obj(ote->listen_entry, FALSE); 448 | 449 | } else if (ote->type == FILEOBJ_CONNOBJ && ote->conn_entry != NULL) { 450 | if (ote->ipproto == IPPROTO_TCP && ote->log_disconnect) 451 | log_disconnect(ote); 452 | 453 | del_tcp_conn_obj(ote->conn_entry, FALSE); 454 | } 455 | 456 | memset(ote, 0, sizeof(*ote)); 457 | 458 | ote->next = saved_next; 459 | ote->fileobj = saved_fileobj; 460 | 461 | // restore fileobjs 462 | for (i = 0; i < MAX_EVENT; i++) 463 | ote->ctx[i].fileobj = saved_fileobj; 464 | 465 | } 466 | 467 | //---------------------------------------------------------------------------- 468 | 469 | #define CALC_HASH_2(addrobj, conn_ctx) CALC_HASH((ULONG)(addrobj) ^ (ULONG)(conn_ctx)) 470 | 471 | NTSTATUS 472 | ot_add_conn_ctx(PFILE_OBJECT addrobj, CONNECTION_CONTEXT conn_ctx, PFILE_OBJECT connobj) 473 | { 474 | ULONG hash = CALC_HASH_2(addrobj, conn_ctx); 475 | KIRQL irql; 476 | struct ctx_entry *cte; 477 | NTSTATUS status; 478 | 479 | KeAcquireSpinLock(&g_cte_hash_guard, &irql); 480 | 481 | for (cte = g_cte_hash[hash]; cte != NULL; cte = cte->next) 482 | if (cte->addrobj == addrobj && cte->conn_ctx == conn_ctx) 483 | break; 484 | 485 | if (cte == NULL) { 486 | KdPrint(("[tdi_fw] ot_add_fileobj: reuse addrobj 0x%x, conn_ctx 0x%x\n", 487 | addrobj, conn_ctx)); 488 | 489 | cte = (struct ctx_entry *)malloc_np(sizeof(*cte)); 490 | if (cte == NULL) { 491 | KdPrint(("[tdi_fw] ot_add_conn_ctx: malloc_np\n")); 492 | status = STATUS_INSUFFICIENT_RESOURCES; 493 | goto done; 494 | } 495 | cte->next = g_cte_hash[hash]; 496 | g_cte_hash[hash] = cte; 497 | 498 | cte->addrobj = addrobj; 499 | cte->conn_ctx = conn_ctx; 500 | } 501 | 502 | cte->connobj = connobj; 503 | 504 | status = STATUS_SUCCESS; 505 | done: 506 | 507 | KeReleaseSpinLock(&g_cte_hash_guard, irql); 508 | return status; 509 | } 510 | 511 | NTSTATUS 512 | ot_del_conn_ctx(PFILE_OBJECT addrobj, CONNECTION_CONTEXT conn_ctx) 513 | { 514 | ULONG hash = CALC_HASH_2(addrobj, conn_ctx); 515 | KIRQL irql; 516 | struct ctx_entry *cte, *prev_cte; 517 | NTSTATUS status; 518 | 519 | KeAcquireSpinLock(&g_cte_hash_guard, &irql); 520 | 521 | prev_cte = NULL; 522 | for (cte = g_cte_hash[hash]; cte != NULL; cte = cte->next) { 523 | if (cte->addrobj == addrobj && cte->conn_ctx == conn_ctx) 524 | break; 525 | prev_cte = cte; 526 | } 527 | 528 | if (cte == NULL) { 529 | KdPrint(("[tdi_fw] ot_del_conn_ctx: addrobj 0x%x not found!\n", addrobj)); 530 | status = STATUS_OBJECT_NAME_NOT_FOUND; 531 | goto done; 532 | } 533 | 534 | if (prev_cte != NULL) 535 | prev_cte->next = cte->next; 536 | else 537 | g_cte_hash[hash] = cte->next; 538 | 539 | free(cte); 540 | 541 | status = STATUS_SUCCESS; 542 | done: 543 | 544 | KeReleaseSpinLock(&g_cte_hash_guard, irql); 545 | return status; 546 | } 547 | 548 | PFILE_OBJECT 549 | ot_find_conn_ctx(PFILE_OBJECT addrobj, CONNECTION_CONTEXT conn_ctx) 550 | { 551 | ULONG hash = CALC_HASH_2(addrobj, conn_ctx); 552 | KIRQL irql; 553 | struct ctx_entry *cte; 554 | PFILE_OBJECT result = NULL; 555 | 556 | KeAcquireSpinLock(&g_cte_hash_guard, &irql); 557 | 558 | for (cte = g_cte_hash[hash]; cte != NULL; cte = cte->next) 559 | if (cte->addrobj == addrobj && cte->conn_ctx == conn_ctx) { 560 | result = cte->connobj; 561 | break; 562 | } 563 | 564 | KeReleaseSpinLock(&g_cte_hash_guard, irql); 565 | return result; 566 | } 567 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/obj_tbl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: obj_tbl.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | #ifndef _obj_tbl_h_ 16 | #define _obj_tbl_h_ 17 | 18 | #include "filter.h" 19 | 20 | NTSTATUS ot_init(void); 21 | void ot_free(void); 22 | 23 | #define FILEOBJ_CONTROLOBJ 0 24 | #define FILEOBJ_ADDROBJ 1 25 | #define FILEOBJ_CONNOBJ 2 26 | 27 | NTSTATUS ot_add_fileobj( 28 | PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj, int fileobj_type, int ipproto, 29 | CONNECTION_CONTEXT conn_ctx); 30 | 31 | NTSTATUS ot_del_fileobj( 32 | PFILE_OBJECT fileobj, int *fileobj_type); 33 | 34 | // maximum length of TDI_ADDRESS_TYPE_* 35 | #define TDI_ADDRESS_MAX_LENGTH TDI_ADDRESS_LENGTH_OSI_TSAP 36 | #define TA_ADDRESS_MAX (sizeof(TA_ADDRESS) - 1 + TDI_ADDRESS_MAX_LENGTH) 37 | #define TDI_ADDRESS_INFO_MAX (sizeof(TDI_ADDRESS_INFO) - 1 + TDI_ADDRESS_MAX_LENGTH) 38 | 39 | // max event index 40 | #ifdef TDI_EVENT_ERROR_EX 41 | // 2k 42 | # define MAX_EVENT (TDI_EVENT_ERROR_EX + 1) 43 | #else 44 | // NT4 45 | # define MAX_EVENT (TDI_EVENT_CHAINED_RECEIVE_EXPEDITED + 1) 46 | #endif 47 | 48 | /* replaced context */ 49 | typedef struct { 50 | PFILE_OBJECT fileobj; /* address object */ 51 | PVOID old_handler; /* old event handler */ 52 | PVOID old_context; /* old event handler context */ 53 | } TDI_EVENT_CONTEXT; 54 | 55 | struct ot_entry { 56 | ULONG signature; 57 | struct ot_entry *next; 58 | 59 | ULONG pid; 60 | 61 | struct _SID_AND_ATTRIBUTES *sid_a; 62 | ULONG sid_a_size; 63 | 64 | PDEVICE_OBJECT devobj; 65 | PFILE_OBJECT fileobj; 66 | PFILE_OBJECT associated_fileobj; 67 | 68 | int type; 69 | int ipproto; 70 | 71 | TDI_EVENT_CONTEXT ctx[MAX_EVENT]; 72 | UCHAR local_addr[TA_ADDRESS_MAX]; 73 | UCHAR remote_addr[TA_ADDRESS_MAX]; 74 | 75 | CONNECTION_CONTEXT conn_ctx; 76 | 77 | struct listen_entry *listen_entry; // for address object 78 | struct conn_entry *conn_entry; // for connection object 79 | 80 | // traffic count for connection object 81 | ULONG bytes_out; 82 | ULONG bytes_in; 83 | 84 | BOOLEAN log_disconnect; 85 | }; 86 | 87 | struct ot_entry *ot_find_fileobj(PFILE_OBJECT fileobj, KIRQL *irql); 88 | // Note: don't forget KeReleaseSpinLock(&g_ot_hash_guard, irql); 89 | 90 | extern KSPIN_LOCK g_ot_hash_guard; 91 | 92 | void ot_cleanup_ote(struct ot_entry *ote); 93 | 94 | 95 | NTSTATUS ot_add_conn_ctx( 96 | PFILE_OBJECT addrobj, CONNECTION_CONTEXT conn_ctx, PFILE_OBJECT connobj); 97 | 98 | NTSTATUS ot_del_conn_ctx( 99 | PFILE_OBJECT addrobj, CONNECTION_CONTEXT conn_ctx); 100 | 101 | PFILE_OBJECT ot_find_conn_ctx( 102 | PFILE_OBJECT addrobj, CONNECTION_CONTEXT conn_ctx); 103 | 104 | 105 | struct _SID_AND_ATTRIBUTES *get_current_sid_a(ULONG *sid_a_size); 106 | struct _SID_AND_ATTRIBUTES *copy_sid_a(struct _SID_AND_ATTRIBUTES *sid_a, ULONG sid_a_size); 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/packet.h: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 2 | // 3 | // $Id: packet.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 4 | 5 | #ifndef _packet_h_ 6 | #define _packet_h_ 7 | 8 | NTSTATUS init_packet(void); 9 | void free_packet(void); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/pid_pname.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: pid_pname.c,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | /* 16 | * Get process name by its pid and all related routines 17 | */ 18 | 19 | #include 20 | 21 | #include "memtrack.h" 22 | #include "pid_pname.h" 23 | #include "sock.h" // add by tan wen 24 | #include "ipc.h" // add by tan wen 25 | 26 | /* process list entry */ 27 | struct plist_entry { 28 | struct plist_entry *next; 29 | 30 | // id & name 31 | ULONG pid; 32 | char *pname; 33 | KEVENT *pname_event; 34 | 35 | int context; 36 | }; 37 | 38 | /* process list */ 39 | static struct { 40 | struct plist_entry *head; 41 | struct plist_entry *tail; 42 | KSPIN_LOCK guard; 43 | } g_plist; 44 | 45 | static struct plist_entry *add_ple(ULONG pid, KIRQL *irql); 46 | static struct plist_entry *find_ple(ULONG pid, KIRQL *irql, struct plist_entry **prev); 47 | 48 | static VOID ProcessNotifyProc(IN HANDLE ParentId, IN HANDLE ProcessId, IN BOOLEAN Create); 49 | 50 | void 51 | pid_pname_init(void) 52 | { 53 | KeInitializeSpinLock(&g_plist.guard); 54 | g_plist.head = g_plist.tail = NULL; 55 | 56 | PsSetCreateProcessNotifyRoutine(ProcessNotifyProc, FALSE); 57 | } 58 | 59 | // free plist 60 | void 61 | pid_pname_free(void) 62 | { 63 | KIRQL irql; 64 | struct plist_entry *ple; 65 | 66 | PsSetCreateProcessNotifyRoutine(ProcessNotifyProc, TRUE); 67 | 68 | KeAcquireSpinLock(&g_plist.guard, &irql); 69 | for (ple = g_plist.head; ple != NULL;) { 70 | struct plist_entry *ple2 = ple->next; 71 | if (ple->pname != NULL) 72 | free(ple->pname); 73 | free(ple); 74 | ple = ple2; 75 | } 76 | g_plist.head = g_plist.tail = NULL; 77 | KeReleaseSpinLock(&g_plist.guard, irql); 78 | } 79 | 80 | // try to get pname by pid 81 | BOOLEAN 82 | pid_pname_resolve(ULONG pid, char *buf, int buf_size) 83 | { 84 | BOOLEAN result; 85 | KIRQL irql; 86 | struct plist_entry *ple = find_ple(pid, &irql, NULL); 87 | 88 | if (ple == NULL) 89 | return FALSE; 90 | 91 | if (ple->pname != NULL) { 92 | if (buf_size > 0) { 93 | strncpy(buf, ple->pname, buf_size); 94 | buf[buf_size - 1] = '\0'; 95 | } 96 | result = TRUE; 97 | } else 98 | result = FALSE; 99 | 100 | KeReleaseSpinLock(&g_plist.guard, irql); 101 | return result; 102 | } 103 | 104 | // set pname_event by pid 105 | NTSTATUS 106 | pid_pname_set_event(ULONG pid, KEVENT *event) 107 | { 108 | KIRQL irql; 109 | struct plist_entry *ple = find_ple(pid, &irql, NULL); 110 | 111 | if (ple == NULL) { 112 | // try to add 113 | ple = add_ple(pid, &irql); 114 | if (ple == NULL) 115 | return STATUS_INSUFFICIENT_RESOURCES; 116 | } 117 | 118 | ple->pname_event = event; 119 | 120 | KeReleaseSpinLock(&g_plist.guard, irql); 121 | return STATUS_SUCCESS; 122 | } 123 | 124 | NTSTATUS 125 | pid_pname_set(ULONG pid, const char *pname, int context) 126 | { 127 | KIRQL irql; 128 | struct plist_entry *ple = find_ple(pid, &irql, NULL); 129 | NTSTATUS status; 130 | 131 | if (ple == NULL) { 132 | // try to add 133 | ple = add_ple(pid, &irql); 134 | if (ple == NULL) 135 | return STATUS_INSUFFICIENT_RESOURCES; 136 | } 137 | 138 | if (ple->pname == NULL) { 139 | ple->pname = (char *)malloc_np(strlen(pname) + 1); 140 | if (ple->pname != NULL) { 141 | strcpy(ple->pname, pname); 142 | status = STATUS_SUCCESS; 143 | } else { 144 | KdPrint(("[tdi_fw] set_pid_name: malloc_np!\n")); 145 | status = STATUS_INSUFFICIENT_RESOURCES; 146 | } 147 | 148 | // and signal event we have name! (almost) 149 | if (ple->pname_event != NULL) 150 | KeSetEvent(ple->pname_event, IO_NO_INCREMENT, FALSE); 151 | 152 | } else 153 | status = STATUS_SUCCESS; // already got pname 154 | 155 | 156 | ple->context = context; 157 | 158 | KeReleaseSpinLock(&g_plist.guard, irql); 159 | return status; 160 | } 161 | 162 | int 163 | pid_pname_get_context(ULONG pid) 164 | { 165 | KIRQL irql; 166 | int context; 167 | struct plist_entry *ple = find_ple(pid, &irql, NULL); 168 | if (ple == NULL) 169 | return 0; 170 | 171 | context = ple->context; 172 | 173 | KeReleaseSpinLock(&g_plist.guard, irql); 174 | return context; 175 | } 176 | 177 | 178 | struct plist_entry * 179 | add_ple(ULONG pid, KIRQL *irql) 180 | { 181 | struct plist_entry *ple; 182 | 183 | if (irql != NULL) 184 | KeAcquireSpinLock(&g_plist.guard, irql); 185 | 186 | // add new entry to g_plist 187 | ple = (struct plist_entry *)malloc_np(sizeof(*ple)); 188 | if (ple != NULL) { 189 | memset(ple, 0, sizeof(*ple)); 190 | ple->pid = pid; 191 | 192 | // append 193 | if (g_plist.tail != NULL) { 194 | g_plist.tail->next = ple; 195 | g_plist.tail = ple; 196 | } else 197 | g_plist.head = g_plist.tail = ple; 198 | 199 | } else { 200 | KdPrint(("[tdi_fw] add_ple: malloc_np!\n")); 201 | 202 | if (irql != NULL) 203 | KeReleaseSpinLock(&g_plist.guard, *irql); 204 | } 205 | 206 | return ple; 207 | } 208 | 209 | struct plist_entry * 210 | find_ple(ULONG pid, KIRQL *irql, struct plist_entry **prev) 211 | { 212 | struct plist_entry *ple, *prev_ple; 213 | 214 | if (irql != NULL) 215 | KeAcquireSpinLock(&g_plist.guard, irql); 216 | 217 | prev_ple = NULL; 218 | for (ple = g_plist.head; ple != NULL; ple = ple->next) { 219 | if (ple->pid == pid) { 220 | if (prev != NULL) 221 | *prev = prev_ple; 222 | return ple; 223 | } 224 | prev_ple = ple; 225 | } 226 | 227 | if (irql != NULL) 228 | KeReleaseSpinLock(&g_plist.guard, *irql); 229 | 230 | return NULL; 231 | } 232 | 233 | 234 | // notify routine on process creation or removing 235 | extern int tdifw_filter(struct flt_request *request); 236 | 237 | VOID 238 | ProcessNotifyProc(IN HANDLE ParentId, IN HANDLE ProcessId, IN BOOLEAN Create) 239 | { 240 | KIRQL irql; 241 | struct plist_entry *ple, *prev_ple; 242 | struct flt_request request = { 0 }; //< add by tan wen 243 | 244 | request.pid = (ULONG)ProcessId; 245 | 246 | if (Create) { 247 | 248 | // add by tan wen 249 | request.type = TYPE_PROCESS_CREATE; 250 | tdifw_filter(&request); 251 | 252 | KdPrint(("[tdi_fw] ProcessNotifyProc: create process with pid:%u\n", ProcessId)); 253 | 254 | add_ple((ULONG)ProcessId, &irql); 255 | KeReleaseSpinLock(&g_plist.guard, irql); 256 | 257 | } else { 258 | 259 | request.type = TYPE_PROCESS_TERMINATE; 260 | tdifw_filter(&request); 261 | 262 | // remove entry from plist 263 | 264 | KdPrint(("[tdi_fw] ProcessNotifyProc: remove process with pid:%u\n", ProcessId)); 265 | 266 | ple = find_ple((ULONG)ProcessId, &irql, &prev_ple); 267 | if (ple == NULL) 268 | return; 269 | 270 | if (prev_ple != NULL) 271 | prev_ple->next = ple->next; 272 | else 273 | g_plist.head = ple->next; 274 | 275 | if (ple->next == NULL) 276 | g_plist.tail = prev_ple; 277 | 278 | if (ple->pname != NULL) { 279 | KdPrint(("[tdi_fw] ProcessNotifyProc: pname was %s\n", ple->pname)); 280 | free(ple->pname); 281 | } 282 | 283 | free(ple); 284 | KeReleaseSpinLock(&g_plist.guard, irql); 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/pid_pname.h: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 2 | // 3 | // $Id: pid_pname.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 4 | 5 | #ifndef _pid_pname_h_ 6 | #define _pid_pname_h_ 7 | 8 | void pid_pname_init(void); 9 | void pid_pname_free(void); 10 | 11 | BOOLEAN pid_pname_resolve(ULONG pid, char *buf, int buf_size); 12 | 13 | NTSTATUS pid_pname_set_event(ULONG pid, KEVENT *event); 14 | 15 | NTSTATUS pid_pname_set(ULONG pid, const char *pname, int context); 16 | int pid_pname_get_context(ULONG pid); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/sids.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: sids.c,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | /* 16 | * Working with SID bitmasks 17 | */ 18 | 19 | #include 20 | #include "sock.h" 21 | 22 | #include "ipc.h" 23 | #include "memtrack.h" 24 | #include "sids.h" 25 | #include "tdi_fw.h" 26 | 27 | struct sid_nfo { 28 | ULONG sid_len; 29 | char sid_data[]; 30 | }; 31 | 32 | static struct { 33 | char *buf; 34 | struct sid_nfo *list[MAX_SIDS_COUNT]; 35 | int count; 36 | KSPIN_LOCK guard; 37 | } g_sids; 38 | 39 | void 40 | sids_init(void) 41 | { 42 | KeInitializeSpinLock(&g_sids.guard); 43 | } 44 | 45 | NTSTATUS 46 | set_sid_list(char *buf, ULONG size) 47 | { 48 | KIRQL irql; 49 | NTSTATUS status; 50 | ULONG pos; 51 | int i; 52 | 53 | KeAcquireSpinLock(&g_sids.guard, &irql); 54 | 55 | // first, free information 56 | if (g_sids.buf != NULL) { 57 | free(g_sids.buf); 58 | g_sids.buf = NULL; 59 | } 60 | memset(g_sids.list, 0, sizeof(g_sids.list)); 61 | g_sids.count = 0; 62 | 63 | if (size != 0) { 64 | // copy buffer 65 | g_sids.buf = (char *)malloc_np(size); 66 | if (g_sids.buf == NULL) { 67 | KdPrint(("[tdi_fw] set_sid_list: malloc_np!\n")); 68 | status = STATUS_INSUFFICIENT_RESOURCES; 69 | goto done; 70 | } 71 | memcpy(g_sids.buf, buf, size); 72 | 73 | // parse buffer and find struct sid_nfo 74 | for (pos = 0, i = 0; pos + sizeof(struct sid_nfo) < size && i < MAX_SIDS_COUNT; i++) { 75 | struct sid_nfo *nfo = (struct sid_nfo *)&g_sids.buf[pos]; 76 | 77 | if (pos + sizeof(*nfo) + nfo->sid_len > size) 78 | break; 79 | 80 | g_sids.list[i] = nfo; 81 | 82 | pos += sizeof(*nfo) + nfo->sid_len; 83 | } 84 | 85 | g_sids.count = i; 86 | 87 | if (pos == size) 88 | status = STATUS_SUCCESS; 89 | else 90 | status = STATUS_INVALID_PARAMETER; 91 | } else 92 | status = STATUS_SUCCESS; 93 | 94 | done: 95 | KeReleaseSpinLock(&g_sids.guard, irql); 96 | return status; 97 | } 98 | 99 | #define SeLengthSid(sid) (8 + 4 * ((unsigned char *)(sid))[1]) 100 | 101 | int 102 | get_sid_id(struct _SID_AND_ATTRIBUTES *sid_a, ULONG sid_a_size) 103 | { 104 | // doing linear search (optimize?) 105 | KIRQL irql; 106 | int i, result = 0; 107 | 108 | KdPrint(("[tdi_fw] get_sid_id: (sid_size = %u/%u)\n", 109 | SeLengthSid(sid_a->Sid), sid_a_size)); 110 | 111 | KeAcquireSpinLock(&g_sids.guard, &irql); 112 | 113 | for (i = 1; i < g_sids.count; i++) { 114 | // comparing sids byte by byte (can't call RtlEqualSid() due to DISPATCH_LEVEL) 115 | 116 | KdPrint(("[tdi_fw] get_sid_id: sid #%d size %u\n", i, SeLengthSid((PSID)g_sids.list[i]->sid_data))); 117 | 118 | if (SeLengthSid(sid_a->Sid) == SeLengthSid((PSID)g_sids.list[i]->sid_data) && 119 | memcmp(sid_a->Sid, (PSID)g_sids.list[i]->sid_data, SeLengthSid(sid_a->Sid)) == 0) { 120 | result = i; 121 | break; 122 | } 123 | } 124 | 125 | KeReleaseSpinLock(&g_sids.guard, irql); 126 | 127 | KdPrint(("[tdi_fw] get_sid_id: %d\n", result)); 128 | return result; 129 | } 130 | 131 | #define CURRENT_THREAD (HANDLE)-2 132 | #define CURRENT_PROCESS (HANDLE)-1 133 | 134 | #define TOKEN_QUERY 0x0008 135 | 136 | struct _SID_AND_ATTRIBUTES * 137 | get_current_sid_a(ULONG *sid_a_size) // must be called at PASSIVE_LEVEL! 138 | { 139 | NTSTATUS status; 140 | HANDLE token; 141 | ULONG size; 142 | SID_AND_ATTRIBUTES *sid_a; 143 | 144 | *sid_a_size = 0; 145 | 146 | // open thread token 147 | status = ZwOpenThreadToken(CURRENT_THREAD, TOKEN_QUERY, FALSE, &token); 148 | if (status == STATUS_NO_TOKEN) { 149 | // open process token 150 | status = ZwOpenProcessToken(CURRENT_PROCESS, TOKEN_QUERY, &token); 151 | } 152 | if (status != STATUS_SUCCESS) { 153 | KdPrint(("[tdi_fw] get_current_sid_a: ZwOpen{Thread|Process}Token: 0x%x!\n")); 154 | return NULL; 155 | } 156 | 157 | size = sizeof(*sid_a) + 100; // default size 158 | 159 | sid_a = (SID_AND_ATTRIBUTES *)malloc_np(size); 160 | if (sid_a == NULL) { 161 | KdPrint(("[tdi_fw] get_current_sid_a: malloc_np!\n")); 162 | goto done; 163 | } 164 | 165 | status = ZwQueryInformationToken(token, TokenUser, sid_a, size, &size); 166 | if (status == STATUS_BUFFER_TOO_SMALL) { 167 | free(sid_a); 168 | 169 | sid_a = (SID_AND_ATTRIBUTES *)malloc_np(size); 170 | if (sid_a == NULL) { 171 | KdPrint(("[tdi_fw] get_current_sid_a: malloc_np!\n")); 172 | goto done; 173 | } 174 | 175 | status = ZwQueryInformationToken(token, TokenUser, sid_a, size, &size); 176 | } 177 | if (status != STATUS_SUCCESS) { 178 | KdPrint(("[tdi_fw] get_current_sid_a: ZwQueryInformationToken: 0x%x!\n")); 179 | 180 | free(sid_a); 181 | sid_a = NULL; 182 | goto done; 183 | } 184 | 185 | // got sid & attributes! 186 | 187 | *sid_a_size = size; 188 | 189 | done: 190 | ZwClose(token); 191 | return sid_a; 192 | } 193 | 194 | struct _SID_AND_ATTRIBUTES * 195 | copy_sid_a(SID_AND_ATTRIBUTES *sid_a, ULONG sid_a_size) 196 | { 197 | SID_AND_ATTRIBUTES *result; 198 | 199 | if (sid_a == NULL) 200 | return NULL; 201 | 202 | result = (SID_AND_ATTRIBUTES *)malloc_np(sid_a_size); 203 | if (result == NULL) 204 | return NULL; 205 | 206 | memcpy(result, sid_a, sid_a_size); 207 | 208 | result->Sid = (char *)result + ((char *)(sid_a->Sid) - (char *)sid_a); 209 | 210 | return result; 211 | } 212 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/sids.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: sids.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | #ifndef _sids_h_ 16 | #define _sids_h_ 17 | 18 | /* SID stuff */ 19 | 20 | struct _SID_AND_ATTRIBUTES *get_current_sid_a(ULONG *sid_a_size); 21 | struct _SID_AND_ATTRIBUTES *copy_sid_a(struct _SID_AND_ATTRIBUTES *sid_a, ULONG sid_a_size); 22 | 23 | void sids_init(void); 24 | 25 | int get_sid_id(struct _SID_AND_ATTRIBUTES *sid_a, ULONG sid_a_size); 26 | 27 | /* size can be NULL; buf is ULONG sid_len; SID ... */ 28 | NTSTATUS set_sid_list(char *buf, ULONG size); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/sock.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: sock.c,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | /* 16 | * Some helpers from sockets 17 | */ 18 | 19 | #include 20 | #include 21 | #include "sock.h" 22 | 23 | u_long 24 | ntohl (u_long netlong) 25 | { 26 | u_long result = 0; 27 | ((char *)&result)[0] = ((char *)&netlong)[3]; 28 | ((char *)&result)[1] = ((char *)&netlong)[2]; 29 | ((char *)&result)[2] = ((char *)&netlong)[1]; 30 | ((char *)&result)[3] = ((char *)&netlong)[0]; 31 | return result; 32 | } 33 | 34 | u_short 35 | ntohs (u_short netshort) 36 | { 37 | u_short result = 0; 38 | ((char *)&result)[0] = ((char *)&netshort)[1]; 39 | ((char *)&result)[1] = ((char *)&netshort)[0]; 40 | return result; 41 | } 42 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/sock.h: -------------------------------------------------------------------------------- 1 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 2 | // 3 | // $Id: sock.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 4 | 5 | #ifndef _sock_h_ 6 | #define _sock_h_ 7 | 8 | /*--- some declarations from winsock.h ---*/ 9 | 10 | /* 11 | * Basic system type definitions, taken from the BSD file sys/types.h. 12 | */ 13 | typedef unsigned char u_char; 14 | typedef unsigned short u_short; 15 | typedef unsigned int u_int; 16 | typedef unsigned long u_long; 17 | 18 | // some socket functions 19 | 20 | u_long ntohl(u_long netlong); 21 | u_short ntohs(u_short netshort); 22 | 23 | u_long htonl(u_long netlong); 24 | u_short htons(u_short netshort); 25 | 26 | /* 27 | * Protocols 28 | */ 29 | #define IPPROTO_IP 0 /* dummy for IP */ 30 | #define IPPROTO_ICMP 1 /* control message protocol */ 31 | #define IPPROTO_TCP 6 /* tcp */ 32 | #define IPPROTO_UDP 17 /* user datagram protocol */ 33 | 34 | /* 35 | * Structure used by kernel to store most 36 | * addresses. 37 | */ 38 | struct sockaddr { 39 | u_short sa_family; /* address family */ 40 | char sa_data[14]; /* up to 14 bytes of direct address */ 41 | }; 42 | 43 | /* 44 | * Internet address (old style... should be updated) 45 | */ 46 | struct in_addr { 47 | union { 48 | struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; 49 | struct { u_short s_w1,s_w2; } S_un_w; 50 | u_long S_addr; 51 | } S_un; 52 | #define s_addr S_un.S_addr 53 | /* can be used for most tcp & ip code */ 54 | #define s_host S_un.S_un_b.s_b2 55 | /* host on imp */ 56 | #define s_net S_un.S_un_b.s_b1 57 | /* network */ 58 | #define s_imp S_un.S_un_w.s_w2 59 | /* imp */ 60 | #define s_impno S_un.S_un_b.s_b4 61 | /* imp # */ 62 | #define s_lh S_un.S_un_b.s_b3 63 | /* logical host */ 64 | }; 65 | 66 | /* 67 | * Socket address, internet style. 68 | */ 69 | struct sockaddr_in { 70 | short sin_family; 71 | u_short sin_port; 72 | struct in_addr sin_addr; 73 | char sin_zero[8]; 74 | }; 75 | 76 | /* 77 | * Address families. 78 | */ 79 | #define AF_INET 2 /* internetwork: UDP, TCP, etc. */ 80 | 81 | #define INADDR_ANY (u_long)0x00000000 82 | #define INADDR_LOOPBACK 0x7f000001 83 | #define INADDR_BROADCAST (u_long)0xffffffff 84 | #define INADDR_NONE 0xffffffff 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/tdi_fw.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002-2005 Vladislav Goncharov. 2 | * 3 | * Redistribution and use in source forms, with and without modification, 4 | * are permitted provided that this entire comment appears intact. 5 | * 6 | * Redistribution in binary form may occur without any restrictions. 7 | * 8 | * This software is provided ``AS IS'' without any warranties of any kind. 9 | */ 10 | 11 | // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 12 | // 13 | // $Id: tdi_fw.h,v 1.1 2009/04/28 12:53:28 tanwen Exp $ 14 | 15 | #ifndef _tdi_fw_h_ 16 | #define _tdi_fw_h_ 17 | 18 | extern PDEVICE_OBJECT g_tcpfltobj, g_udpfltobj, g_ipfltobj; 19 | 20 | #ifndef USE_TDI_HOOKING 21 | // original (unhooked) device objects when don't using TDI hooking 22 | extern PDEVICE_OBJECT g_tcpoldobj, g_udpoldobj, g_ipoldobj; 23 | #endif 24 | 25 | extern BOOLEAN g_got_log; 26 | 27 | NTSTATUS tdi_dispatch_complete( 28 | PDEVICE_OBJECT devobj, PIRP irp, int filter, PIO_COMPLETION_ROUTINE cr, PVOID context); 29 | 30 | NTSTATUS tdi_generic_complete( 31 | IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context); 32 | 33 | PDEVICE_OBJECT get_original_devobj(PDEVICE_OBJECT flt_devobj, int *proto); 34 | 35 | // should be in ipc.h 36 | NTSTATUS process_request(ULONG code, char *buf, ULONG *buf_len, ULONG buf_size); 37 | NTSTATUS process_nfo_request(ULONG code, char *buf, ULONG *buf_len, ULONG buf_size); 38 | 39 | // used for incoming or outgoing connections 40 | void update_conn_info(PDEVICE_OBJECT devobj, PFILE_OBJECT connobj); 41 | 42 | // traffic counters 43 | extern unsigned __int64 g_traffic[TRAFFIC_MAX]; 44 | extern KSPIN_LOCK g_traffic_guard; 45 | 46 | /* some Native API prototypes */ 47 | 48 | NTKERNELAPI 49 | NTSTATUS 50 | ObReferenceObjectByName ( 51 | IN PUNICODE_STRING ObjectName, 52 | IN ULONG Attributes, 53 | IN PACCESS_STATE PassedAccessState OPTIONAL, 54 | IN ACCESS_MASK DesiredAccess OPTIONAL, 55 | IN POBJECT_TYPE ObjectType OPTIONAL, 56 | IN KPROCESSOR_MODE AccessMode, 57 | IN OUT PVOID ParseContext OPTIONAL, 58 | OUT PVOID *Object 59 | ); 60 | 61 | NTSTATUS 62 | NTAPI 63 | ZwCreateEvent ( 64 | OUT PHANDLE EventHandle, 65 | IN ACCESS_MASK DesiredAccess, 66 | IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, 67 | IN EVENT_TYPE EventType, 68 | IN BOOLEAN InitialState 69 | ); 70 | 71 | NTSTATUS 72 | NTAPI 73 | ZwOpenThreadToken ( 74 | IN HANDLE ThreadHandle, 75 | IN ACCESS_MASK DesiredAccess, 76 | IN BOOLEAN OpenAsSelf, 77 | OUT PHANDLE TokenHandle 78 | ); 79 | 80 | NTSTATUS 81 | NTAPI 82 | ZwOpenProcessToken ( 83 | IN HANDLE ProcessHandle, 84 | IN ACCESS_MASK DesiredAccess, 85 | OUT PHANDLE TokenHandle 86 | ); 87 | 88 | typedef enum _TOKEN_INFORMATION_CLASS { 89 | TokenUser = 1, 90 | TokenGroups, 91 | TokenPrivileges, 92 | TokenOwner, 93 | TokenPrimaryGroup, 94 | TokenDefaultDacl, 95 | TokenSource, 96 | TokenType, 97 | TokenImpersonationLevel, 98 | TokenStatistics, 99 | TokenRestrictedSids 100 | } TOKEN_INFORMATION_CLASS; 101 | 102 | NTSTATUS 103 | NTAPI 104 | ZwQueryInformationToken ( 105 | IN HANDLE TokenHandle, 106 | IN TOKEN_INFORMATION_CLASS TokenInformationClass, 107 | OUT PVOID TokenInformation, 108 | IN ULONG Length, 109 | OUT PULONG ResultLength 110 | ); 111 | 112 | typedef enum _TOKEN_TYPE { 113 | TokenPrimary = 1, 114 | TokenImpersonation 115 | } TOKEN_TYPE; 116 | 117 | typedef struct _SID_AND_ATTRIBUTES { 118 | PSID Sid; 119 | ULONG Attributes; 120 | } SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES; 121 | 122 | typedef struct _TOKEN_USER { 123 | SID_AND_ATTRIBUTES User; 124 | } TOKEN_USER, *PTOKEN_USER; 125 | 126 | NTSTATUS 127 | NTAPI 128 | ZwWaitForSingleObject( 129 | IN HANDLE hObject, 130 | IN BOOLEAN bAlertable, 131 | IN PLARGE_INTEGER Timeout 132 | ); 133 | 134 | /* for compilation under NT4 DDK */ 135 | 136 | #ifndef EVENT_ALL_ACCESS 137 | # define EVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3) 138 | #endif 139 | 140 | #ifndef IoSkipCurrentIrpStackLocation 141 | # define IoSkipCurrentIrpStackLocation(Irp) \ 142 | (Irp)->CurrentLocation++; \ 143 | (Irp)->Tail.Overlay.CurrentStackLocation++; 144 | #endif 145 | 146 | extern POBJECT_TYPE IoDriverObjectType; 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /sys/tdi_fw/src/tdi_fw_lib.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file tdi_fw_lib 3 | * @author tan wen 4 | * @brief I add this file to simplise the including of tdi_fw.lib's 5 | * header file. tdi_fw.lib is a library based on tdi_fw. You 6 | * can link this library to build a tdi filter driver easily. 7 | */ 8 | 9 | #ifndef _TDI_FW_LIB_HEADER_ 10 | #define _TDI_FW_LIB_HEADER_ 11 | 12 | #include 13 | #include 14 | #include "net.h" 15 | #include "sock.h" 16 | #include "ipc.h" 17 | 18 | /** If you use tdi_fw.lib to build your tdi filter driver, you must write 19 | * tdifw_driver_entry(), tdifw_driver_unload(), tdifw_user_device_dispatch(), 20 | * tdifw_filter(). You can't change these function's name or use their name 21 | * to define other functions or vals. These functions' prototypes are as below. 22 | */ 23 | 24 | /** tdifw_driver_entry is just like DriverEntry. tdi_fw.lib already havs the 25 | * function which named DriverEntry. So when you is using tdi_fw.lib to develop 26 | * a tdi neckwork filter, use tdifw_driver_entry instead. Don't to set driver's 27 | * dispatch function here. tdi_fw has used them. But if you create any device 28 | * here, you may use tdifw_register_user_device() to resigter them. When any 29 | * irp is sending to your devices, tdifw_user_device_dispatch() will be called. 30 | * You can dispatch your irp here. 31 | */ 32 | extern NTSTATUS 33 | tdifw_driver_entry( 34 | IN PDRIVER_OBJECT theDriverObject, 35 | IN PUNICODE_STRING theRegistryPath); 36 | 37 | /** tdifw_driver_unload is just like DriverUnload. It will be called when this 38 | * driver is unloading. Delete all devices you created and free memory you 39 | * allocated here. 40 | */ 41 | extern VOID 42 | tdifw_driver_unload( 43 | IN PDRIVER_OBJECT DriverObject); 44 | 45 | /** tdifw_user_device_dispatch() will be called when any device which you 46 | * have created and used tdifw_register_user_device() to register got any 47 | * irp. You should complete any such irp here. Don't passthru. 48 | */ 49 | extern NTSTATUS tdifw_user_device_dispatch( 50 | IN PDEVICE_OBJECT DeviceObject, IN PIRP irp); 51 | 52 | /** These function will be call when any network event happends. You can choose 53 | * interested event to filter. return FLT_ALLOW to passthru or FLT_DENY to 54 | * refuse this event. See the strcut flt_request for more details. 55 | */ 56 | extern int tdifw_filter(struct flt_request *request); 57 | 58 | BOOLEAN tdifw_register_user_device(PDEVICE_OBJECT dev); 59 | 60 | #endif // _TDI_FW_LIB_HEADER_ 61 | -------------------------------------------------------------------------------- /sys/tdi_fw/tdi_fw.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; tdi_fw.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class= 8 | ClassGuid= 9 | Provider= 10 | DriverVer= 11 | CatalogFile= 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | 16 | 17 | [SourceDisksNames] 18 | 1 = %DiskName%,,,"" 19 | 20 | [SourceDisksFiles] 21 | 22 | 23 | [Manufacturer] 24 | %ManufacturerName%=Standard,NT$ARCH$ 25 | 26 | [Standard.NT$ARCH$] 27 | 28 | 29 | [Strings] 30 | ManufacturerName="" 31 | ClassName="" 32 | DiskName="tdi_fw Source Disk" 33 | -------------------------------------------------------------------------------- /sys/tdi_fw/tdi_fw.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Win8.1 Debug 6 | Win32 7 | 8 | 9 | Win8.1 Release 10 | Win32 11 | 12 | 13 | Win8 Debug 14 | Win32 15 | 16 | 17 | Win8 Release 18 | Win32 19 | 20 | 21 | Win7 Debug 22 | Win32 23 | 24 | 25 | Win7 Release 26 | Win32 27 | 28 | 29 | Win8.1 Debug 30 | x64 31 | 32 | 33 | Win8.1 Release 34 | x64 35 | 36 | 37 | Win8 Debug 38 | x64 39 | 40 | 41 | Win8 Release 42 | x64 43 | 44 | 45 | Win7 Debug 46 | x64 47 | 48 | 49 | Win7 Release 50 | x64 51 | 52 | 53 | 54 | {E41842B6-3E8B-476C-AA59-BBC98BCFA547} 55 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 56 | v4.5 57 | 11.0 58 | Win8.1 Debug 59 | Win32 60 | tdi_fw 61 | 62 | 63 | 64 | WindowsV6.3 65 | true 66 | WindowsKernelModeDriver8.1 67 | Driver 68 | WDM 69 | 70 | 71 | WindowsV6.3 72 | false 73 | WindowsKernelModeDriver8.1 74 | Driver 75 | WDM 76 | 77 | 78 | Windows8 79 | true 80 | WindowsKernelModeDriver8.1 81 | Driver 82 | WDM 83 | 84 | 85 | Windows8 86 | false 87 | WindowsKernelModeDriver8.1 88 | Driver 89 | WDM 90 | 91 | 92 | Windows7 93 | true 94 | WindowsKernelModeDriver8.1 95 | StaticLibrary 96 | WDM 97 | 98 | 99 | Windows7 100 | false 101 | WindowsKernelModeDriver8.1 102 | StaticLibrary 103 | WDM 104 | 105 | 106 | WindowsV6.3 107 | true 108 | WindowsKernelModeDriver8.1 109 | Driver 110 | WDM 111 | 112 | 113 | WindowsV6.3 114 | false 115 | WindowsKernelModeDriver8.1 116 | Driver 117 | WDM 118 | 119 | 120 | Windows8 121 | true 122 | WindowsKernelModeDriver8.1 123 | Driver 124 | WDM 125 | 126 | 127 | Windows8 128 | false 129 | WindowsKernelModeDriver8.1 130 | Driver 131 | WDM 132 | 133 | 134 | Windows7 135 | true 136 | WindowsKernelModeDriver8.1 137 | Driver 138 | WDM 139 | 140 | 141 | Windows7 142 | false 143 | WindowsKernelModeDriver8.1 144 | Driver 145 | WDM 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | DbgengKernelDebugger 157 | 158 | 159 | DbgengKernelDebugger 160 | 161 | 162 | DbgengKernelDebugger 163 | 164 | 165 | DbgengKernelDebugger 166 | 167 | 168 | DbgengKernelDebugger 169 | 170 | 171 | DbgengKernelDebugger 172 | .lib 173 | 174 | 175 | DbgengKernelDebugger 176 | 177 | 178 | DbgengKernelDebugger 179 | 180 | 181 | DbgengKernelDebugger 182 | 183 | 184 | DbgengKernelDebugger 185 | 186 | 187 | DbgengKernelDebugger 188 | 189 | 190 | DbgengKernelDebugger 191 | 192 | 193 | 194 | Level3 195 | 196 | 197 | 198 | 199 | false 200 | USE_PACKET_ENGINE;CAN_UNLOAD;%(PreprocessorDefinitions) 201 | 202 | 203 | 204 | 205 | Level3 206 | 207 | 208 | 209 | 210 | false 211 | USE_PACKET_ENGINE;CAN_UNLOAD;%(PreprocessorDefinitions) 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | -------------------------------------------------------------------------------- /sys/tdi_fw/tdi_fw.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | 65 | 66 | Source Files 67 | 68 | 69 | Source Files 70 | 71 | 72 | Source Files 73 | 74 | 75 | Source Files 76 | 77 | 78 | Source Files 79 | 80 | 81 | Source Files 82 | 83 | 84 | Source Files 85 | 86 | 87 | Source Files 88 | 89 | 90 | Source Files 91 | 92 | 93 | Source Files 94 | 95 | 96 | Source Files 97 | 98 | 99 | Source Files 100 | 101 | 102 | Source Files 103 | 104 | 105 | Source Files 106 | 107 | 108 | Source Files 109 | 110 | 111 | Source Files 112 | 113 | 114 | Source Files 115 | 116 | 117 | Source Files 118 | 119 | 120 | Source Files 121 | 122 | 123 | Source Files 124 | 125 | 126 | --------------------------------------------------------------------------------