├── .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 |
--------------------------------------------------------------------------------