├── .gitattributes ├── .gitignore ├── CONTRIBUTING.rst ├── COPYING ├── COPYRIGHT.GPL ├── COPYRIGHT.MIT ├── DigiCert-High-Assurance-EV-Root-CA.crt ├── MSCV-VSClass3.cer ├── README.md ├── build-pia.bat ├── buildtap.py ├── installer ├── ShellLink.dll ├── icon.ico ├── install-whirl.bmp ├── tap-windows6.nsi └── wow.nsh ├── paths.py ├── sign ├── .gitignore ├── Create-DriverSubmission.ps1 ├── Cross-Sign.ps1 ├── Extract-DriverSubmission.ps1 ├── Sign-File.ps1 ├── Sign-Tap6.conf.ps1 ├── Verify-Path.ps1 └── tap-windows6.ddf ├── src ├── OemVista.inf.in ├── adapter.c ├── adapter.h ├── config.h.in ├── constants.h ├── device.c ├── device.h ├── dhcp.c ├── dhcp.h ├── endian.h ├── error.c ├── error.h ├── hexdump.h ├── lock.h ├── macinfo.c ├── macinfo.h ├── mem.c ├── mem.h ├── oidrequest.c ├── proto.h ├── prototypes.h ├── resource.rc ├── rxpath.c ├── tap-windows.h ├── tap-windows6.vcxproj.filters ├── tap-windows6.vcxproj.in ├── tap.h ├── tapdrvr.c ├── txpath.c └── types.h └── version.m4 /.gitattributes: -------------------------------------------------------------------------------- 1 | *.yml text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Packaging and distribution outputs 3 | dist/** 4 | *.pyc 5 | *.tar.gz 6 | tap-windows-*.exe 7 | 8 | # builttap.py-generated files 9 | src/config.h 10 | src/tap-windows6.vcxproj 11 | src/OemVista.inf 12 | 13 | # Visual Studio and MSBuild files 14 | src/tap-windows6.sln 15 | src/Release 16 | src/Debug 17 | src/x64 18 | src/arm64 19 | .vs 20 | 21 | /setup.inf 22 | /setup.rpt 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | Contributing to tap-windows6 2 | ============================ 3 | 4 | To contribute to tap-windows6 please send your patches to openvpn-devel mailing 5 | list: 6 | 7 | - https://lists.sourceforge.net/lists/listinfo/openvpn-devel 8 | 9 | The subject line should look like this: 10 | 11 | [PATCH: tap-windows6] summary of the patch 12 | 13 | To avoid merging issues patches should be created with git-format-patch or sent 14 | using git-send-email. The easiest way to add the subject line prefix is to use 15 | this option: 16 | 17 | --subject-prefix='PATCH: tap-windows6' 18 | 19 | Patches that do not modify the actual driver code can be sent as GitHub pull 20 | requests. Try to split large patches into small, atomic pieces to make reviews 21 | and merging easier. 22 | 23 | If you want quick feedback on a patch, you can visit the #openvpn-devel channel 24 | on Freenode. Note that you need to be logged in to join the channel: 25 | 26 | - http://freenode.net/faq.shtml#nicksetup 27 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | tap-windows6 license 2 | -------------------- 3 | 4 | The source and object code of the tap-windows6 project 5 | is Copyright (C) 2002-2014 OpenVPN Technologies, Inc. The 6 | NSIS installer is Copyright (C) 2014 OpenVPN Technologies, 7 | Inc. and (C) 2012 Alon Bar-Lev. Both are released under the 8 | GPL version 2. See COPYRIGHT.GPL for the full GPL license. 9 | The licensors also make the following statement borrowed 10 | from the SPICE project: 11 | 12 | With respect to binaries built using the Microsoft(R) 13 | Windows Driver Kit (WDK), GPLv2 does not extend to any code 14 | contained in or derived from the WDK ("WDK Code"). As to 15 | WDK Code, by using or distributing such binaries you agree 16 | to be bound by the Microsoft Software License Terms for the 17 | WDK. All WDK Code is considered by the GPLv2 licensors to 18 | qualify for the special exception stated in section 3 of 19 | GPLv2 (commonly known as the system library exception). 20 | 21 | The tap-windows.h file has been released under the MIT 22 | license (see COPYRIGHT.MIT) as well as under GPLv2 (see 23 | COPYRIGHT.GPL). This has been done to allow the use of the 24 | header file in non-GPLv2 compatible projects. 25 | 26 | 27 | Modifications are Copyright (C) 2019 London Trust Media, Inc. 28 | and released under the GPL version 2. 29 | -------------------------------------------------------------------------------- /COPYRIGHT.GPL: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /COPYRIGHT.MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright © 2014 OpenVPN Technologies, Inc. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the “Software”), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /DigiCert-High-Assurance-EV-Root-CA.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFOzCCAyOgAwIBAgIKYSBNtAAAAAAAJzANBgkqhkiG9w0BAQUFADB/MQswCQYD 3 | VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe 4 | MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3Nv 5 | ZnQgQ29kZSBWZXJpZmljYXRpb24gUm9vdDAeFw0xMTA0MTUxOTQ1MzNaFw0yMTA0 6 | MTUxOTU1MzNaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx 7 | GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRpZ2lDZXJ0IEhp 8 | Z2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw 9 | ggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD1ZQ0Z6IKHLBfaaZAscS3 10 | so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80ltcZF+Y7arpl/DpIT4T2JR 11 | vvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46OFBbdzEbjbPHJEWap6xt 12 | ABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZdHFMsfpjNGgYWpGhz0DQE 13 | E1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdmt4i3ePLKCqg4qwpkwr9m 14 | XZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjgcswgcgwEQYDVR0gBAowCDAG 15 | BgRVHSAAMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSx 16 | PsNpA/i/RwHUmCYaCALvY2QrwzAfBgNVHSMEGDAWgBRi+wohW39DbhHaCVRQa/XS 17 | lnHxnjBVBgNVHR8ETjBMMEqgSKBGhkRodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v 18 | cGtpL2NybC9wcm9kdWN0cy9NaWNyb3NvZnRDb2RlVmVyaWZSb290LmNybDANBgkq 19 | hkiG9w0BAQUFAAOCAgEAIIzBWe1vnGstwUo+dR1FTEFQHL2A6tmwkosGKhM/Uxae 20 | VjlqimO2eCR59X24uUehCpbC9su9omafBuGs0nkJDv083KwCDHCvPxvseH7U60sF 21 | YCbZc2GRIe2waGPglxKrb6AS7dmf0tonPLPkVvnR1IEPcb1CfKaJ3M3VvZWiq/GT 22 | EX3orDEpqF1mcEGd/HXJ1bMaOSrQhQVQi6yRysSTy3GlnaSUb1gM+m4gxAgxtYWd 23 | foH50j3KWxiFbAqG7CIJG6V0NE9/KLyVSqsdtpiwXQmkd3Z+76eOXYT2GCTL0W2m 24 | w6GcwhB1gP+dMv3mz0M6gvfOj+FyKptit1/tlRo5XC+UbUi3AV8zL7vcLXM0iQRC 25 | ChyLefmj+hfv+qEaEN/gssGV61wMBZc7NT4YiE3bbL8kiY3Ivdifezk6JKDV39Hz 26 | ShqX9qZveh+wkKmzrAE5kdNht2TxPlc4A6/OetK1kPWu3DmZ1bY8l+2myxbHfWsq 27 | TJCU5kxU/R7NIOzOaJyHWOlhYL7rDsnVGX2f6Xi9DqwhdQePqW7gjGoqa5zj52W8 28 | vC08bdwE3GdFNjKvBIG8qABuYUyVxVzUjo6fL8EydL29EWUDB83vt14CV9qG1Boo 29 | NK+ISbLPpd2CVm9oqhTiWVT+/+ru7+qScCJggeMlI8CfzA9JsjWqWMM6w9kWlBA= 30 | -----END CERTIFICATE----- 31 | -------------------------------------------------------------------------------- /MSCV-VSClass3.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pia-foss/desktop-tap/82d248df771b7fad6892cf0f8b4d898046d69cf2/MSCV-VSClass3.cer -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Building the TAP Adapter for Private Internet Access 2 | 3 | The steps required to build the TAP adapter driver for the Private Internet Access desktop client have been encapsulated into a custom wrapper build script. 4 | 5 | **Note:** Private Internet Access does not require any side components such as `tapinstall.exe`. If you need to acquire these, consult the original [tap-windows6](https://github.com/OpenVPN/tap-windows6) repository. 6 | 7 | ## Prerequisites 8 | 9 | - Python 2.7 (needs to be in your `PATH`) 10 | - Microsoft Windows 10 EWDK (Enterprise Windows Driver Kit) 11 | - Windows code signing EV certificate 12 | 13 | ## Digitally signing the driver 14 | 15 | In order to install drivers on modern versions Windows they need to be digitally signed with an EV (Extended Validation) certificate. To maximize compatibility with older Windows versions, the build script can double-sign the driver with both a SHA1 and a SHA256 certificate. 16 | 17 | Additionally, for Windows 10 a properly EV-signed driver package can be submitted to Microsoft to have its signature replaced with a Microsoft certificate. This will let the driver be installed automatically without requiring an additional user authorization prompt. 18 | 19 | **Note:** The build script digitally signs the drivers as a post-build step; standard tap-windows6 build outputs such as tap6.tar.gz will contain the still-unsigned versions. 20 | 21 | ## Usage 22 | 23 | The build script is configurable in a few ways using environment variables (for convenience when using CI builders): 24 | 25 | - If you installed the EWDK in a subfolder of `C:\EWDK` the build script will pick it up automatically. Otherwise, set the `EWDK` environment variable to point to the EWDK directory. 26 | 27 | - Specify the SHA256 code signing certificate thumbprint with `PIA_TAP_SHA256_CERT`. To double-sign, also specify the SHA1 code signing certificate with `PIA_TAP_SHA1_CERT`. 28 | 29 | - If you are using a certificate from somewhere other than DigiCert, specify the CA certificate with `PIA_TAP_CROSSCERT` and the timestamp server URL with `PIA_TAP_TIMESTAMP`. 30 | 31 | After configuring the environment, merely execute the build script: 32 | 33 | ```shell 34 | > build-pia.bat 35 | ``` 36 | 37 | **Note:** You may run into a certificate error if this is the first time you are building with the EWDK, if it is unable to generate a temporary test certificate while building the drivers. To resolve this, run the build script as administrator the first time (not necessary on subsequent builds). 38 | 39 | After building, the drivers are placed in `dist/i386` and `dist/amd64`, and signed CABs for Microsoft submission are placed in `dist`. 40 | -------------------------------------------------------------------------------- /build-pia.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal EnableDelayedExpansion 3 | pushd %~dp0 4 | 5 | rem Specify these arguments in the environment before calling the script: 6 | rem EWDK = path to EWDK (e.g. C:\EWDK\1804, tries to auto-detect) 7 | rem PIA_TAP_SHA256_CERT = thumbprint of SHA256 EV certificate (needed for installable driver) 8 | rem PIA_TAP_SHA1_CERT = thumbprint of SHA1 EV certificate (optional) 9 | rem PIA_TAP_CROSSCERT = CA certificate file for EV certificate (default: DigiCert EV) 10 | rem PIA_TAP_TIMESTAMP = timestamp server for signing (default: DigiCert) 11 | 12 | if [%PIA_TAP_CROSSCERT%] == [] set "PIA_TAP_CROSSCERT=DigiCert-High-Assurance-EV-Root-CA.crt" 13 | if [%PIA_TAP_TIMESTAMP%] == [] set "PIA_TAP_TIMESTAMP=http://timestamp.digicert.com" 14 | 15 | if [%EWDK%] == [] ( 16 | for /D %%G in ("C:\EWDK\*") do set "EWDK=%%G" 17 | ) 18 | if not exist "%EWDK%" ( 19 | echo Error: EWDK not found. 20 | goto error 21 | ) 22 | echo * Using EWDK in %EWDK% 23 | 24 | call "%EWDK%\BuildEnv\SetupBuildEnv.cmd" 25 | @echo off 26 | 27 | del /Q /F dist 28 | 29 | echo * Building TAP adapter... 30 | rem Patch paths.py with provided/detected EWDK path 31 | powershell -Command "(Get-Content paths.py) -replace '^EWDK\s*=\s*.*', ('EWDK = """"%EWDK%""""').Replace('\','\\') | Out-File -encoding ASCII paths.py" 32 | if %errorlevel% neq 0 goto error 33 | echo. 34 | python buildtap.py -c -b 35 | if %errorlevel% neq 0 goto error 36 | echo. 37 | 38 | if not [%PIA_TAP_SHA256_CERT%] == [] ( 39 | for %%G in (i386,amd64) do ( 40 | for %%H in ("dist\%%G\*.cat") do set "CAT_%%G=%%H" 41 | ) 42 | if not [%PIA_TAP_SHA1_CERT%] == [] ( 43 | echo * Double-signing drivers with SHA1 and SHA256 certificates... 44 | echo * Signing with SHA1... 45 | signtool.exe sign /ac "%PIA_TAP_CROSSCERT%" /fd sha1 /tr "%PIA_TAP_TIMESTAMP%" /td sha1 /sha1 "%PIA_TAP_SHA1_CERT%" "!CAT_i386!" "!CAT_amd64!" 46 | if !errorlevel! neq 0 goto error 47 | echo * Signing with SHA256... 48 | signtool.exe sign /as /ac "%PIA_TAP_CROSSCERT%" /fd sha256 /tr "%PIA_TAP_TIMESTAMP%" /td sha256 /sha1 "%PIA_TAP_SHA256_CERT%" "!CAT_i386!" "!CAT_amd64!" 49 | if !errorlevel! neq 0 goto error 50 | ) else ( 51 | echo * Signing drivers with SHA256 certificate... 52 | signtool.exe sign /ac "%PIA_TAP_CROSSCERT%" /fd sha256 /tr "%PIA_TAP_TIMESTAMP%" /td sha256 /sha1 "%PIA_TAP_SHA256_CERT%" "!CAT_i386!" "!CAT_amd64!" 53 | if !errorlevel! neq 0 goto error 54 | ) 55 | echo * Making CAB files... 56 | for %%G in (i386,amd64) do ( 57 | for %%H in ("!CAT_%%G!") do ( 58 | >"dist\tap-%%G.ddf" ( 59 | echo .option explicit 60 | echo .set CabinetFileCountThreshold=0 61 | echo .set FolderFileCountThreshold=0 62 | echo .set FolderSizeThreshold=0 63 | echo .set MaxCabinetSize=0 64 | echo .set MaxDiskFileCount=0 65 | echo .set MaxDiskSize=0 66 | echo .set Cabinet=on 67 | echo .set Compress=on 68 | echo .set DiskDirectoryTemplate=dist 69 | echo .set DestinationDir=Package 70 | echo .set CabinetNameTemplate=tap-%%G.cab 71 | echo .set SourceDir=dist\%%G 72 | echo OemVista.inf 73 | echo %%~nH.sys 74 | echo %%~nxH 75 | ) 76 | makecab /F "dist\tap-%%G.ddf" >NUL 77 | if !errorlevel! neq 0 ( 78 | set errorlevel=!errorlevel! 79 | del /Q /F "dist\tap-%%G.ddf" 80 | goto error 81 | ) 82 | del /Q /F "dist\tap-%%G.ddf" 83 | ) 84 | ) 85 | echo * Signing CAB files for Microsoft submission... 86 | signtool.exe sign /ac "%PIA_TAP_CROSSCERT%" /fd sha256 /tr "%PIA_TAP_TIMESTAMP%" /td sha256 /sha1 "%PIA_TAP_SHA256_CERT%" "dist\tap-i386.cab" "dist\tap-amd64.cab" 87 | if !errorlevel! neq 0 goto error 88 | 89 | echo. 90 | echo To get Microsoft certified drivers for Windows 10, submit the 91 | echo signed CAB files to the Microsoft Dev Center at: 92 | echo. 93 | echo https://developer.microsoft.com/en-us/dashboard/hardware 94 | echo. 95 | ) else ( 96 | echo * No certificates specified; drivers will not be installable. 97 | ) 98 | 99 | echo * Build successful. 100 | 101 | :end 102 | popd 103 | endlocal 104 | exit /b %errorlevel% 105 | 106 | :error 107 | if %errorlevel% equ 0 ( 108 | set errorlevel=1 109 | ) else ( 110 | echo. 111 | echo Build failed with error %errorlevel%! 112 | ) 113 | goto end 114 | -------------------------------------------------------------------------------- /installer/ShellLink.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pia-foss/desktop-tap/82d248df771b7fad6892cf0f8b4d898046d69cf2/installer/ShellLink.dll -------------------------------------------------------------------------------- /installer/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pia-foss/desktop-tap/82d248df771b7fad6892cf0f8b4d898046d69cf2/installer/icon.ico -------------------------------------------------------------------------------- /installer/install-whirl.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pia-foss/desktop-tap/82d248df771b7fad6892cf0f8b4d898046d69cf2/installer/install-whirl.bmp -------------------------------------------------------------------------------- /installer/tap-windows6.nsi: -------------------------------------------------------------------------------- 1 | ; **************************************************************************** 2 | ; * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. * 3 | ; * Copyright (C) 2012 Alon Bar-Lev * 4 | ; * This program is free software; you can redistribute it and/or modify * 5 | ; * it under the terms of the GNU General Public License version 2 * 6 | ; * as published by the Free Software Foundation. * 7 | ; **************************************************************************** 8 | 9 | ; TAP-Windows install script for Windows, using NSIS 10 | 11 | SetCompressor /SOLID lzma 12 | 13 | !addplugindir . 14 | !include "MUI.nsh" 15 | !include "StrFunc.nsh" 16 | !include "wow.nsh" 17 | !define MULTIUSER_EXECUTIONLEVEL Admin 18 | !include "MultiUser.nsh" 19 | !include FileFunc.nsh 20 | !insertmacro GetParameters 21 | !insertmacro GetOptions 22 | 23 | ${StrLoc} 24 | 25 | ;-------------------------------- 26 | ;Configuration 27 | 28 | ;General 29 | 30 | OutFile "${OUTPUT}" 31 | 32 | ShowInstDetails show 33 | ShowUninstDetails show 34 | 35 | ;Remember install folder 36 | InstallDirRegKey HKLM "SOFTWARE\${PRODUCT_NAME}" "" 37 | 38 | ;-------------------------------- 39 | ;Modern UI Configuration 40 | 41 | Name "${PRODUCT_NAME} ${PRODUCT_VERSION}-I${PRODUCT_TAP_WIN_BUILD}" 42 | 43 | !define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of ${PRODUCT_NAME}, a kernel driver to provide virtual tap device functionality on Windows originally written by James Yonan.\r\n\r\nNote that ${PRODUCT_NAME} will only run on Windows Vista or later.\r\n\r\n\r\n" 44 | 45 | !define MUI_COMPONENTSPAGE_TEXT_TOP "Select the components to install/upgrade. Stop any ${PRODUCT_NAME} processes or the ${PRODUCT_NAME} service if it is running. All DLLs are installed locally." 46 | 47 | !define MUI_COMPONENTSPAGE_SMALLDESC 48 | !define MUI_FINISHPAGE_NOAUTOCLOSE 49 | !define MUI_ABORTWARNING 50 | !define MUI_ICON "icon.ico" 51 | !define MUI_UNICON "icon.ico" 52 | !define MUI_HEADERIMAGE 53 | !define MUI_HEADERIMAGE_BITMAP "install-whirl.bmp" 54 | !define MUI_UNFINISHPAGE_NOAUTOCLOSE 55 | 56 | !insertmacro MUI_PAGE_WELCOME 57 | !insertmacro MUI_PAGE_LICENSE "${IMAGE}\license.txt" 58 | !insertmacro MUI_PAGE_COMPONENTS 59 | !insertmacro MUI_PAGE_DIRECTORY 60 | !insertmacro MUI_PAGE_INSTFILES 61 | !insertmacro MUI_PAGE_FINISH 62 | 63 | !insertmacro MUI_UNPAGE_CONFIRM 64 | !insertmacro MUI_UNPAGE_INSTFILES 65 | !insertmacro MUI_UNPAGE_FINISH 66 | 67 | ;-------------------------------- 68 | ;Languages 69 | 70 | !insertmacro MUI_LANGUAGE "English" 71 | 72 | ;-------------------------------- 73 | ;Language Strings 74 | 75 | LangString DESC_SecTAP ${LANG_ENGLISH} "Install/Upgrade the TAP virtual device driver. Will not interfere with CIPE." 76 | LangString DESC_SecTAPUtilities ${LANG_ENGLISH} "Install the TAP Utilities." 77 | LangString DESC_SecTAPSDK ${LANG_ENGLISH} "Install the TAP SDK." 78 | 79 | ;-------------------------------- 80 | ;Reserve Files 81 | 82 | ;Things that need to be extracted on first (keep these lines before any File command!) 83 | ;Only useful for BZIP2 compression 84 | 85 | ReserveFile "install-whirl.bmp" 86 | 87 | ;-------------------------------- 88 | ;Macros 89 | 90 | !macro SelectByParameter SECT PARAMETER DEFAULT 91 | ${GetOptions} $R0 "/${PARAMETER}=" $0 92 | ${If} ${DEFAULT} == 0 93 | ${If} $0 == 1 94 | !insertmacro SelectSection ${SECT} 95 | ${EndIf} 96 | ${Else} 97 | ${If} $0 != 0 98 | !insertmacro SelectSection ${SECT} 99 | ${EndIf} 100 | ${EndIf} 101 | !macroend 102 | 103 | ;-------------------------------- 104 | ;Installer Sections 105 | 106 | Section /o "TAP Virtual Ethernet Adapter" SecTAP 107 | 108 | SetOverwrite on 109 | 110 | ${If} ${RunningX64} 111 | DetailPrint "We are running on an x86_64 64-bit system." 112 | 113 | SetOutPath "$INSTDIR\bin" 114 | File "${DEVCON64}" 115 | 116 | SetOutPath "$INSTDIR\driver" 117 | File "${IMAGE}\amd64\OemVista.inf" 118 | File "${IMAGE}\amd64\${PRODUCT_TAP_WIN_COMPONENT_ID}.cat" 119 | File "${IMAGE}\amd64\${PRODUCT_TAP_WIN_COMPONENT_ID}.sys" 120 | ${ElseIf} ${RunningArm64} 121 | DetailPrint "We are running on an ARM64 64-bit system." 122 | 123 | SetOutPath "$INSTDIR\bin" 124 | File "${DEVCONARM64}" 125 | 126 | SetOutPath "$INSTDIR\driver" 127 | File "${IMAGE}\arm64\OemVista.inf" 128 | File "${IMAGE}\arm64\${PRODUCT_TAP_WIN_COMPONENT_ID}.cat" 129 | File "${IMAGE}\arm64\${PRODUCT_TAP_WIN_COMPONENT_ID}.sys" 130 | ${ElseIf} ${RunningX86} 131 | DetailPrint "We are running on an x86 32-bit system." 132 | 133 | SetOutPath "$INSTDIR\bin" 134 | File "${DEVCON32}" 135 | 136 | SetOutPath "$INSTDIR\driver" 137 | File "${IMAGE}\i386\OemVista.inf" 138 | File "${IMAGE}\i386\${PRODUCT_TAP_WIN_COMPONENT_ID}.cat" 139 | File "${IMAGE}\i386\${PRODUCT_TAP_WIN_COMPONENT_ID}.sys" 140 | ${Else} 141 | DetailPrint "Native architecture not recognized!" 142 | ${EndIf} 143 | SectionEnd 144 | 145 | Section /o "TAP Utilities" SecTAPUtilities 146 | SetOverwrite on 147 | 148 | # Delete previous start menu 149 | RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}" 150 | 151 | FileOpen $R0 "$INSTDIR\bin\addtap.bat" w 152 | FileWrite $R0 "rem Add a new TAP virtual ethernet adapter$\r$\n" 153 | FileWrite $R0 '"$INSTDIR\bin\${DEVCON_BASENAME}" install "$INSTDIR\driver\OemVista.inf" ${PRODUCT_TAP_WIN_COMPONENT_ID}$\r$\n' 154 | FileWrite $R0 "pause$\r$\n" 155 | FileClose $R0 156 | 157 | FileOpen $R0 "$INSTDIR\bin\deltapall.bat" w 158 | FileWrite $R0 "echo WARNING: this script will delete ALL TAP virtual adapters (use the device manager to delete adapters one at a time)$\r$\n" 159 | FileWrite $R0 "pause$\r$\n" 160 | FileWrite $R0 '"$INSTDIR\bin\${DEVCON_BASENAME}" remove ${PRODUCT_TAP_WIN_COMPONENT_ID}$\r$\n' 161 | FileWrite $R0 "pause$\r$\n" 162 | FileClose $R0 163 | 164 | ; Create shortcuts 165 | CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}\Utilities" 166 | CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Utilities\Add a new TAP virtual ethernet adapter.lnk" "$INSTDIR\bin\addtap.bat" "" 167 | ; set runas admin flag on the addtap link 168 | ShellLink::SetRunAsAdministrator "$SMPROGRAMS\${PRODUCT_NAME}\Utilities\Add a new TAP virtual ethernet adapter.lnk" 169 | Pop $0 170 | ${If} $0 != 0 171 | DetailPrint "Setting RunAsAdmin flag on addtap failed: status = $0" 172 | ${Endif} 173 | CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Utilities\Delete ALL TAP virtual ethernet adapters.lnk" "$INSTDIR\bin\deltapall.bat" "" 174 | ; set runas admin flag on the deltapall link 175 | ShellLink::SetRunAsAdministrator "$SMPROGRAMS\${PRODUCT_NAME}\Utilities\Delete ALL TAP virtual ethernet adapters.lnk" 176 | Pop $0 177 | ${If} $0 != 0 178 | DetailPrint "Setting RunAsAdmin flag on deltapall failed: status = $0" 179 | ${Endif} 180 | SectionEnd 181 | 182 | Section /o "TAP SDK" SecTAPSDK 183 | SetOverwrite on 184 | SetOutPath "$INSTDIR\include" 185 | File "${IMAGE}\include\tap-windows.h" 186 | SectionEnd 187 | 188 | Function .onInit 189 | ${GetParameters} $R0 190 | ClearErrors 191 | 192 | ${IfNot} ${AtLeastWinVista} 193 | MessageBox MB_OK "This package requires at least Windows Vista" 194 | SetErrorLevel 1 195 | Quit 196 | ${EndIf} 197 | 198 | !insertmacro SelectByParameter ${SecTAP} SELECT_TAP 1 199 | !insertmacro SelectByParameter ${SecTAPUtilities} SELECT_UTILITIES 0 200 | !insertmacro SelectByParameter ${SecTAPSDK} SELECT_SDK 0 201 | 202 | !insertmacro MULTIUSER_INIT 203 | SetShellVarContext all 204 | 205 | ${If} ${RunningX64} 206 | SetRegView 64 207 | StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCT_NAME}" 208 | ${Else} 209 | StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCT_NAME}" 210 | ${EndIf} 211 | FunctionEnd 212 | 213 | ;-------------------------------- 214 | ;Dependencies 215 | 216 | Function .onSelChange 217 | ${If} ${SectionIsSelected} ${SecTAPUtilities} 218 | !insertmacro SelectSection ${SecTAP} 219 | ${EndIf} 220 | FunctionEnd 221 | 222 | ;-------------------- 223 | ;Post-install section 224 | 225 | Section -post 226 | 227 | ; Store README, license, icon 228 | SetOverwrite on 229 | SetOutPath $INSTDIR 230 | File "${IMAGE}\license.txt" 231 | File "icon.ico" 232 | 233 | ${If} ${SectionIsSelected} ${SecTAP} 234 | ; 235 | ; install/upgrade TAP driver if selected, using devcon 236 | ; 237 | ; TAP install/update was selected. 238 | ; Should we install or update? 239 | ; If tapinstall error occurred, $R5 will 240 | ; be nonzero. 241 | IntOp $R5 0 & 0 242 | nsExec::ExecToStack '"$INSTDIR\bin\${DEVCON_BASENAME}" hwids ${PRODUCT_TAP_WIN_COMPONENT_ID}' 243 | Pop $R0 # return value/error/timeout 244 | IntOp $R5 $R5 | $R0 245 | DetailPrint "${DEVCON_BASENAME} hwids returned: $R0" 246 | 247 | ; If tapinstall output string contains "${PRODUCT_TAP_WIN_COMPONENT_ID}" we assume 248 | ; that TAP device has been previously installed, 249 | ; therefore we will update, not install. 250 | Push "${PRODUCT_TAP_WIN_COMPONENT_ID}" 251 | Push ">" 252 | Call StrLoc 253 | Pop $R0 254 | 255 | ${If} $R5 == 0 256 | ${If} $R0 == "" 257 | StrCpy $R1 "install" 258 | ${Else} 259 | StrCpy $R1 "update" 260 | ${EndIf} 261 | DetailPrint "TAP $R1 (${PRODUCT_TAP_WIN_COMPONENT_ID}) (May require confirmation)" 262 | nsExec::ExecToLog '"$INSTDIR\bin\${DEVCON_BASENAME}" $R1 "$INSTDIR\driver\OemVista.inf" ${PRODUCT_TAP_WIN_COMPONENT_ID}' 263 | Pop $R0 # return value/error/timeout 264 | ${If} $R0 == "" 265 | IntOp $R0 0 & 0 266 | SetRebootFlag true 267 | DetailPrint "REBOOT flag set" 268 | ${EndIf} 269 | IntOp $R5 $R5 | $R0 270 | DetailPrint "${DEVCON_BASENAME} returned: $R0" 271 | ${EndIf} 272 | 273 | DetailPrint "${DEVCON_BASENAME} cumulative status: $R5" 274 | ${If} $R5 != 0 275 | MessageBox MB_OK "An error occurred installing the TAP device driver." 276 | ${EndIf} 277 | 278 | ; Store install folder in registry 279 | WriteRegStr HKLM SOFTWARE\${PRODUCT_NAME} "" $INSTDIR 280 | ${EndIf} 281 | 282 | ; Create uninstaller 283 | WriteUninstaller "$INSTDIR\Uninstall.exe" 284 | 285 | ; Show up in Add/Remove programs 286 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayName" "${PRODUCT_NAME} ${PRODUCT_VERSION}" 287 | WriteRegExpandStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "UninstallString" "$INSTDIR\Uninstall.exe" 288 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayIcon" "$INSTDIR\icon.ico" 289 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "DisplayVersion" "${PRODUCT_VERSION}" 290 | WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoModify" 1 291 | WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "NoRepair" 1 292 | WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "Publisher" "${PRODUCT_PUBLISHER}" 293 | WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "HelpLink" "https://openvpn.net/index.php/open-source.html" 294 | WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "URLInfoAbout" "https://openvpn.net" 295 | 296 | ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 297 | IntFmt $0 "0x%08X" $0 298 | WriteRegDWORD HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" "EstimatedSize" "$0" 299 | 300 | SectionEnd 301 | 302 | ;-------------------------------- 303 | ;Descriptions 304 | 305 | !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN 306 | !insertmacro MUI_DESCRIPTION_TEXT ${SecTAP} $(DESC_SecTAP) 307 | !insertmacro MUI_DESCRIPTION_TEXT ${SecTAPUtilities} $(DESC_SecTAPUtilities) 308 | !insertmacro MUI_DESCRIPTION_TEXT ${SecTAPSDK} $(DESC_SecTAPSDK) 309 | !insertmacro MUI_FUNCTION_DESCRIPTION_END 310 | 311 | ;-------------------------------- 312 | ;Uninstaller Section 313 | 314 | Function un.onInit 315 | ClearErrors 316 | !insertmacro MULTIUSER_UNINIT 317 | SetShellVarContext all 318 | ${If} ${RunningX64} 319 | SetRegView 64 320 | ${EndIf} 321 | FunctionEnd 322 | 323 | Section "Uninstall" 324 | DetailPrint "TAP REMOVE" 325 | nsExec::ExecToLog '"$INSTDIR\bin\${DEVCON_BASENAME}" remove ${PRODUCT_TAP_WIN_COMPONENT_ID}' 326 | Pop $R0 # return value/error/timeout 327 | DetailPrint "${DEVCON_BASENAME} remove returned: $R0" 328 | 329 | Delete "$INSTDIR\bin\${DEVCON_BASENAME}" 330 | Delete "$INSTDIR\bin\addtap.bat" 331 | Delete "$INSTDIR\bin\deltapall.bat" 332 | 333 | Delete "$INSTDIR\driver\OemVista.inf" 334 | Delete "$INSTDIR\driver\${PRODUCT_TAP_WIN_COMPONENT_ID}.cat" 335 | Delete "$INSTDIR\driver\${PRODUCT_TAP_WIN_COMPONENT_ID}.sys" 336 | 337 | Delete "$INSTDIR\include\tap-windows.h" 338 | 339 | Delete "$INSTDIR\icon.ico" 340 | Delete "$INSTDIR\license.txt" 341 | Delete "$INSTDIR\Uninstall.exe" 342 | 343 | RMDir "$INSTDIR\bin" 344 | RMDir "$INSTDIR\driver" 345 | RMDir "$INSTDIR\include" 346 | RMDir "$INSTDIR" 347 | RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}" 348 | 349 | DeleteRegKey HKLM "SOFTWARE\${PRODUCT_NAME}" 350 | DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" 351 | 352 | SectionEnd 353 | -------------------------------------------------------------------------------- /installer/wow.nsh: -------------------------------------------------------------------------------- 1 | ; --------------------- 2 | ; wow.nsh 3 | ; --------------------- 4 | ; 5 | ; A few simple macros for building installers that need to be aware of whether 6 | ; it is running on the same processor architecture as the OS. 7 | ; 8 | ; RunningX64 checks if the installer is running on an x86_64 64-bit OS. 9 | ; RunningX86 checks if the installer is running on an x86 32-bit OS. 10 | ; RunningARM64 checks if the installer is running on an ARM64 64-bit OS. 11 | ; IsWow64 checks if the native OS and the installer architectures differ. 12 | ; ** Please Note: ** IsWow64 no longer denotes x86_64 hosting x86. 13 | ; 14 | ; ${If} ${RunningX64} 15 | ; MessageBox MB_OK "running on x64" 16 | ; ${EndIf} 17 | ; 18 | ; DisableX64FSRedirection disables file system redirection. 19 | ; EnableX64FSRedirection enables file system redirection. 20 | ; ** Please Note: ** X64 is an incorrect yet backwards-compatible name for this 21 | ; macro. 22 | ; 23 | ; SetOutPath $SYSDIR 24 | ; ${DisableX64FSRedirection} 25 | ; File some.dll # extracts to C:\Windows\System32 26 | ; ${EnableX64FSRedirection} 27 | ; File some.dll # extracts to C:\Windows\SysWOW64 28 | ; 29 | 30 | !ifndef ___WOW__NSH___ 31 | !define ___WOW__NSH___ 32 | 33 | !include LogicLib.nsh 34 | 35 | ; Per https://msdn.microsoft.com/en-us/library/windows/desktop/mt804345(v=vs.85).aspx 36 | ; 0x0 37 | !define IMAGE_FILE_MACHINE_UNKNOWN 0 38 | ; 0x014c 39 | !define IMAGE_FILE_MACHINE_I386 332 40 | ; 0x0200 41 | !define IMAGE_FILE_MACHINE_IA64 512 42 | ; 0x8664 43 | !define IMAGE_FILE_MACHINE_AMD64 34404 44 | ; 0x01c4 (ARM32) 45 | !define IMAGE_FILE_MACHINE_ARMNT 452 46 | ; 0xAA64 47 | !define IMAGE_FILE_MACHINE_ARM64 43620 48 | 49 | Var _Wow_WowHost 50 | Var _Wow_WowGuest 51 | Var _Wow_ReturnValue 52 | Var _Wow_CurrentProcess 53 | 54 | !macro _Wow_GetWowArchitectures LabelPrefix 55 | ; Get the current process handle 56 | System::Call kernel32::GetCurrentProcess()p.s 57 | Pop $_Wow_CurrentProcess 58 | Push $_Wow_CurrentProcess 59 | ; push order is return value, left-to-right output args 60 | System::Call "kernel32::IsWow64Process2(p, *i, *i)i (s., .s, .s).s" 61 | ; Return value 62 | Pop $_Wow_ReturnValue 63 | ; ProcessMachine 64 | Pop $_Wow_WowGuest 65 | ; NativeMachine 66 | Pop $_Wow_WowHost 67 | 68 | ; To get around the fact that functions need un. versions and LogicLib can't be 69 | ; used in macros due to label duplication, this section uses StrCmp and prefixed labels. 70 | ;${If} $_Wow_ReturnValue != 1 71 | StrCmp $_Wow_ReturnValue 1 _Wow_${LabelPrefix}_EndIf0 0 72 | DetailPrint "IsWow64Process2 not available; falling back to IsWow64Process." 73 | ; Either the function call failed or this is an older OS with only IsWow64Process. 74 | ; Fall back and imitate the better function per the MSDN docs. 75 | Push $_Wow_CurrentProcess 76 | System::Call "kernel32::IsWow64Process(p, *i)i (s., .s).s" 77 | Pop $_Wow_ReturnValue 78 | Pop $_Wow_WowGuest 79 | ;${If} $_Wow_WowGuest != 0 80 | StrCmp $_Wow_WowGuest 0 _Wow_${LabelPrefix}_Else1 0 81 | ; This is x86 on AMD64. 82 | StrCpy $_Wow_WowGuest ${IMAGE_FILE_MACHINE_I386} 83 | StrCpy $_Wow_WowHost ${IMAGE_FILE_MACHINE_AMD64} 84 | Goto _Wow_${LabelPrefix}_EndIf1 85 | ;${Else} 86 | _Wow_${LabelPrefix}_Else1: 87 | StrCpy $_Wow_WowGuest ${IMAGE_FILE_MACHINE_UNKNOWN} 88 | ; This is either x86 native or AMD64 native. This is known at script compile time. 89 | !if ${NSIS_PTR_SIZE} > 4 90 | StrCpy $_Wow_WowHost ${IMAGE_FILE_MACHINE_AMD64} 91 | !else 92 | StrCpy $_Wow_WowHost ${IMAGE_FILE_MACHINE_I386} 93 | !endif 94 | ;${EndIf} 95 | _Wow_${LabelPrefix}_EndIf1: 96 | ;${EndIf} 97 | _Wow_${LabelPrefix}_EndIf0: 98 | !macroend 99 | 100 | !define RunningARM64 `"" RunningARM64 ""` 101 | !macro _RunningARM64 _left _right _stayTarget _goTarget 102 | !insertmacro _Wow_GetWowArchitectures ${__COUNTER__} 103 | !insertmacro _= $_Wow_WowHost ${IMAGE_FILE_MACHINE_ARM64} `${_stayTarget}` `${_goTarget}` 104 | !macroend 105 | 106 | !define IsWow64 `"" IsWow64 ""` 107 | !macro _IsWow64 _a _b _t _f 108 | !insertmacro _Wow_GetWowArchitectures ${__COUNTER__} 109 | !insertmacro _!= $_Wow_WowGuest ${IMAGE_FILE_MACHINE_UNKNOWN} `${_t}` `${_f}` 110 | !macroend 111 | 112 | !define RunningX86 `"" RunningX86 ""` 113 | !macro _RunningX86 _a _b _t _f 114 | !insertmacro _Wow_GetWowArchitectures ${__COUNTER__} 115 | !insertmacro _= $_Wow_WowHost ${IMAGE_FILE_MACHINE_I386} `${_t}` `${_f}` 116 | !macroend 117 | 118 | !define RunningX64 `"" RunningX64 ""` 119 | !macro _RunningX64 _a _b _t _f 120 | !insertmacro _Wow_GetWowArchitectures ${__COUNTER__} 121 | !insertmacro _= $_Wow_WowHost ${IMAGE_FILE_MACHINE_AMD64} `${_t}` `${_f}` 122 | !macroend 123 | 124 | ; This currently does not support nested calls because the argument's value is not preservable. 125 | !define DisableX64FSRedirection "!insertmacro DisableX64FSRedirection" 126 | !macro DisableX64FSRedirection 127 | System::Call kernel32::Wow64EnableWow64FsRedirection(i0) 128 | !macroend 129 | 130 | !define EnableX64FSRedirection "!insertmacro EnableX64FSRedirection" 131 | !macro EnableX64FSRedirection 132 | System::Call kernel32::Wow64EnableWow64FsRedirection(i1) 133 | !macroend 134 | 135 | 136 | !endif # !___WOW__NSH___ 137 | -------------------------------------------------------------------------------- /paths.py: -------------------------------------------------------------------------------- 1 | 2 | # Windows 10 EWDK (can just be ISO mount point) 3 | EWDK = "C:\\EWDK\\1804" 4 | 5 | NSIS = "C:\\Program Files (x86)\\NSIS" 6 | -------------------------------------------------------------------------------- /sign/.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.crt 3 | *.pfx 4 | -------------------------------------------------------------------------------- /sign/Create-DriverSubmission.ps1: -------------------------------------------------------------------------------- 1 | # Produce Windows 10 DDF cabined files for attestation signing 2 | Param ( 3 | [string]$DistDir = "${PSScriptRoot}\..\dist", 4 | [String]$DDFTemplate = "${PSScriptRoot}\tap-windows6.ddf", 5 | [String]$CabinetBaseName = "tap-windows6" 6 | ) 7 | 8 | . "${PSScriptRoot}\Verify-Path.ps1" 9 | . "${PSScriptRoot}\Sign-Tap6.conf.ps1" 10 | 11 | Verify-Path $DDFTemplate "tap-windows6 DDF template" 12 | Verify-Path $DistDir "tap-windows6 dist directory" 13 | 14 | foreach ($arch in "i386", "amd64", "arm64") { 15 | $ddf_file = "${CabinetBaseName}-${arch}.ddf" 16 | # makecab.exe can only understand Ascii files 17 | (Get-Content $DDFTemplate) -replace ("%ARCH%", "$arch") -replace ("%CABINETBASENAME%", "$CabinetBaseName")|Out-File $ddf_file -Encoding Ascii 18 | (Get-ChildItem "${DistDir}\${arch}").FullName|Out-File $ddf_file -Append -Encoding Ascii 19 | & makecab.exe /F "${ddf_file}" 20 | "${PSScriptRoot}/Sign-File.ps1 ${ddf_file}" 21 | } -------------------------------------------------------------------------------- /sign/Cross-Sign.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$SourceDir = "${PSScriptRoot}\..\dist", 3 | [switch]$Force, 4 | [switch]$Append 5 | ) 6 | 7 | Function Show-Usage { 8 | Write-Host "Usage: Cross-Sign.ps1 [-SourceDir ] [-Force] [-VerifyOnly] [-Append]" 9 | Write-Host 10 | Write-Host "Example 1: Sign for OpenVPN (OSS)" 11 | Write-Host " Cross-Sign.ps1 -Force" 12 | Write-Host 13 | Write-Host "Example 2: Sign for OpenVPN Connect (Access Server)" 14 | Write-Host " Cross-Sign.ps1 -SourceDir ..\tapoas6 -Force" 15 | Write-Host 16 | Write-Host "Example 3: Append a signature to a signed driver (e.g. for Windows Vista)" 17 | Write-Host " Cross-Sign.ps1 -Append" 18 | Write-Host 19 | } 20 | 21 | . "${PSScriptRoot}\Sign-Tap6.conf.ps1" 22 | . "${PSScriptRoot}\Verify-Path.ps1" 23 | 24 | # Parameter validation 25 | if (! ($SourceDir -and $crosscert)) { 26 | Show-Usage 27 | Exit 1 28 | } 29 | 30 | if ( !($Append) -and !($Force)) { 31 | Write-Host "ERROR: You must use -Force when not using -Append!" 32 | Write-Host 33 | Show-Usage 34 | Exit 1 35 | } 36 | 37 | if ( $Append -and $Force) { 38 | Write-Host "ERROR: Using -Append and -Force are mutually exclusive parameters!" 39 | Write-Host 40 | Show-Usage 41 | Exit 1 42 | } 43 | 44 | # Inf2Cat.exe requires a fully-qualified path 45 | $x86_driver_dir = Resolve-Path "${SourceDir}\i386" 46 | $x64_driver_dir = Resolve-Path "${SourceDir}\amd64" 47 | $arm64_driver_dir = Resolve-Path "${SourceDir}\arm64" 48 | $inf_x86 = "${x86_driver_dir}/OemVista.inf" 49 | $inf_x64 = "${x64_driver_dir}/OemVista.inf" 50 | $inf_arm64 = "${arm64_driver_dir}/OemVista.inf" 51 | # The next two result in a string such as "tap0901" 52 | $x86_driver_basename = (Get-ChildItem $x86_driver_dir -Filter "*.sys").BaseName 53 | $x64_driver_basename = (Get-ChildItem $x64_driver_dir -Filter "*.sys").BaseName 54 | $arm64_driver_basename = (Get-ChildItem $arm64_driver_dir -Filter "*.sys").BaseName 55 | $cat_x86 = "${x86_driver_dir}\${x86_driver_basename}.cat" 56 | $cat_x64 = "${x64_driver_dir}\${x64_driver_basename}.cat" 57 | $cat_arm64 = "${arm64_driver_dir}\${arm64_driver_basename}.cat" 58 | $devcon_x86 = (Get-ChildItem $x86_driver_dir -Filter "*.exe").FullName 59 | $devcon_x64 = (Get-ChildItem $x64_driver_dir -Filter "*.exe").FullName 60 | $devcon_arm64 = (Get-ChildItem $arm64_driver_dir -Filter "*.exe").FullName 61 | $sourcedir_basename = (Get-Item $SourceDir).Basename 62 | $sourcedir_parent = (Get-Item $SourceDir).Parent.FullName 63 | 64 | Verify-Path $inf2cat "Inf2Cat.exe" 65 | Verify-Path $signtool "signtool.exe" 66 | Verify-Path $CrossCert "cross certificate" 67 | Verify-Path $SourceDir "tap-windows6 source directory" 68 | Verify-Path $inf_x86 $inf_x86 69 | Verify-Path $inf_x64 $inf_x64 70 | Verify-Path $devcon_x86 "32-bit devcon/tapinstall.exe" 71 | Verify-Path $devcon_x64 "64-bit devcon/tapinstall.exe" 72 | 73 | if ($VerifyOnly) { 74 | Write-Host "Verification complete" 75 | Exit 0 76 | } 77 | 78 | # Recreate catalogs and catalog signatures if -Force is given 79 | if ($Force) { 80 | foreach ($file in $cat_x86,$cat_x64) { 81 | Remove-Item $file 82 | } 83 | } 84 | 85 | # Generate catalogs 86 | if (Test-Path $cat_x86) { 87 | Write-Host "Catalog file ${cat_X86} is present, not creating it" 88 | } else { 89 | & $Inf2Cat /driver:$x86_driver_dir /os:Vista_X86,Server2008_X86,7_X86 90 | } 91 | 92 | if (Test-Path $cat_x64) { 93 | Write-Host "Catalog file ${cat_X64} is present, not creating it" 94 | } else { 95 | & $Inf2Cat /driver:$x64_driver_dir /os:Vista_X64,Server2008_X64,Server2008R2_X64,7_X64 96 | } 97 | 98 | # Sign the catalogs 99 | foreach ($file in $cat_x86,$cat_x64,$cat_arm64,$devcon_x86,$devcon_x64,$devcon_arm64) { 100 | $not_signed = ((Get-AuthenticodeSignature $file).Status -eq "NotSigned") 101 | 102 | if ( ($not_signed) -or ($Append) ) { 103 | & $signtool sign /v /s My /n $subject /ac $crosscert /as /fd $digest $file 104 | # signtool.exe counterintuitively rejects the /tp 0, claiming that the index is invalid; 105 | # hence we only define /tp if we're adding a second signature. 106 | if ($Append) { 107 | & $signtool timestamp /tr $timestamp /td $digest /tp 1 $file 108 | } else { 109 | & $signtool timestamp /tr $timestamp /td $digest $file 110 | } 111 | } else { 112 | Write-Host "${file} is signed already, not signing it" 113 | } 114 | } -------------------------------------------------------------------------------- /sign/Extract-DriverSubmission.ps1: -------------------------------------------------------------------------------- 1 | # Produce a tap-windows6 dist directory from attestation signed driver packages 2 | Param ( 3 | [parameter(Mandatory = $true, ValueFromPipeline = $true)] $DriverPackage, 4 | [string]$DistDir = "${PSScriptRoot}\..\dist" 5 | ) 6 | 7 | Begin { 8 | # Load configs and modules 9 | . "${PSScriptRoot}\Verify-Path.ps1" 10 | . "${PSScriptRoot}\Sign-Tap6.conf.ps1" 11 | 12 | # Get UNIX epoch-style timestamp for backup filename 13 | $timestamp = (New-TimeSpan -Start (Get-Date "01/01/1970") -End (Get-Date)).TotalSeconds 14 | 15 | # Backup old dist directory 16 | if (Test-Path $DistDir) { 17 | Copy-Item -Recurse $DistDir "${DistDir}.${timestamp}" 18 | } 19 | } 20 | 21 | Process { 22 | # Extract the attestation signed zip file into a temporary directory and 23 | # copy its contents into the "dist" directory, overwriting any existing files 24 | # with the same name. 25 | ForEach ($input in $DriverPackage) { 26 | $fullpath = ($input).FullName 27 | Verify-Path $fullpath "driver package" 28 | $basename = ($input).BaseName 29 | if (Test-Path $basename) { 30 | Remove-Item -Recurse $basename 31 | } 32 | Expand-Archive -Path $fullpath -DestinationPath $basename 33 | Get-ChildItem "${basename}\drivers"|Copy-Item -Force -Recurse -Destination $DistDir 34 | Remove-Item -Recurse $basename 35 | } 36 | } 37 | 38 | End { 39 | # Verify that a signed tapinstall.exe is found 40 | $dist_dirs = ((Get-ChildItem -Path $DistDir -Directory)|Where-Object { $_Name -match "^(amd64|arm64|i386)$" }).FullName 41 | ForEach ($dist_dir in $dist_dirs) { 42 | $tapinstall = "${dist_dir}\tapinstall.exe" 43 | if (! (Test-Path $tapinstall)) { 44 | Write-Host "ERROR: ${tapinstall} not found!" 45 | Exit 1 46 | } else { 47 | if ((Get-AuthenticodeSignature $tapinstall).Status -ne "Valid") { 48 | Write-Host "ERROR: No valid authenticode signature found for ${tapinstall}!" 49 | Exit 1 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /sign/Sign-File.ps1: -------------------------------------------------------------------------------- 1 | # Sign the (installer) file and verify it using non-kernel mode validation 2 | Param ( 3 | [parameter(Mandatory = $true, ValueFromPipeline = $true)] $SourceFile 4 | ) 5 | 6 | Begin { 7 | Function Show-Usage { 8 | Write-Host "Usage: Sign-File.ps1 -SourceFile " 9 | Write-Host 10 | Write-Host "Example 1: Sign tap-windows6 release package" 11 | Write-Host " Sign-File.ps1 -SourceFile ..\tap-windows-9.23.2-I601.exe" 12 | Write-Host 13 | Write-Host "Example 2: sign all cabinet files under disk1" 14 | Write-Host " Get-ChildItem disk1|Sign-File.ps1" 15 | } 16 | 17 | . "${PSScriptRoot}\Sign-Tap6.conf.ps1" 18 | . "${PSScriptRoot}\Verify-Path.ps1" 19 | 20 | Verify-Path $signtool "signtool.exe" 21 | Verify-Path $CrossCert "cross certificate" 22 | 23 | if (! ($crosscert)) { 24 | Show-Usage 25 | Exit 1 26 | } 27 | } 28 | 29 | Process { 30 | ForEach ($input in $SourceFile) { 31 | $fullpath = ($input).FullName 32 | Verify-Path $fullpath "source file" 33 | $not_signed = ((Get-AuthenticodeSignature $fullpath).Status -eq "NotSigned") 34 | if ($not_signed) { 35 | & $signtool sign /v /s My /n $subject /ac $crosscert /fd $digest $fullpath 36 | & $signtool timestamp /tr $timestamp /td $digest $fullpath 37 | & $signtool verify /pa /v $fullpath 38 | } else { 39 | Write-Host "${SourceFile} is signed already, not signing it" 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /sign/Sign-Tap6.conf.ps1: -------------------------------------------------------------------------------- 1 | # Adapt this file to match your system 2 | $ddk_bin = "C:\Program Files (x86)\Windows Kits\10\bin\x86" 3 | $inf2cat = "C:\Program Files (x86)\Windows Kits\10\bin\x86\inf2cat.exe" 4 | $signtool = "C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe" 5 | 6 | # Signtool.exe selects the certificate based on the Subject[name] field. 7 | # This script only searches from under CurrentUser\My certificate store. 8 | # If you have several certificates with matching Subject fields, your only 9 | # choice is to put them in different stores (LocalMachine and CurrentUser) 10 | # and instruct Signtool.exe to use the correct store. If you have three or 11 | # more certificates, then you need to use pfx files and the /f and /p switches 12 | # instead. 13 | $subject = "OpenVPN" 14 | 15 | # The correct cross-certificate is needed for kernel-mode drivers. You can get 16 | # them from here: 17 | # 18 | # 19 | # 20 | # The two settings below are for a Digicert EV code-signing certificate 21 | # 22 | $crosscert = ".\digicert-high-assurance-ev.crt" 23 | $timestamp = "http://timestamp.digicert.com" 24 | 25 | # The digest algorithm to use for the signature as well as the timestamp 26 | $digest = "sha256" 27 | 28 | # Creating tarballs has not been implemented yet, so you can ignore this 29 | $tar = "C:\Program Files\Git\usr\bin\tar.exe" 30 | -------------------------------------------------------------------------------- /sign/Verify-Path.ps1: -------------------------------------------------------------------------------- 1 | Function Verify-Path ([string]$mypath, [string]$msg) { 2 | if ( ! ($mypath)) { 3 | Write-Host "ERROR: empty string defined for ${msg}" 4 | Exit 1 5 | } 6 | if (! (Test-Path $mypath)) { 7 | Write-Host "ERROR: ${msg} not found!" 8 | Exit 1 9 | } 10 | } -------------------------------------------------------------------------------- /sign/tap-windows6.ddf: -------------------------------------------------------------------------------- 1 | ;*** DDF submission template for tap-windows6 2 | ; 3 | .OPTION EXPLICIT ; Generate errors 4 | .Set CabinetFileCountThreshold=0 5 | .Set FolderFileCountThreshold=0 6 | .Set FolderSizeThreshold=0 7 | .Set MaxCabinetSize=0 8 | .Set MaxDiskFileCount=0 9 | .Set MaxDiskSize=0 10 | .Set CompressionType=MSZIP 11 | .Set Cabinet=on 12 | .Set Compress=on 13 | ;Specify file name for new cab file 14 | .Set CabinetNameTemplate=%CABINETBASENAME%-%ARCH%.cab 15 | ;Specify files to be included in cab file 16 | .Set DestinationDir=%ARCH% -------------------------------------------------------------------------------- /src/OemVista.inf.in: -------------------------------------------------------------------------------- 1 | ; **************************************************************************** 2 | ; * Copyright (C) 2002-2014 OpenVPN Technologies, Inc. * 3 | ; * This program is free software; you can redistribute it and/or modify * 4 | ; * it under the terms of the GNU General Public License version 2 * 5 | ; * as published by the Free Software Foundation. * 6 | ; **************************************************************************** 7 | 8 | ; SYNTAX CHECKER 9 | ; cd \WINDDK\3790\tools\chkinf 10 | ; chkinf c:\src\openvpn\tap-win32\i386\oemvista.inf 11 | ; OUTPUT -> file:///c:/WINDDK/3790/tools/chkinf/htm/c%23+src+openvpn+tap-win32+i386+__OemWin2k.htm 12 | 13 | ; INSTALL/REMOVE DRIVER 14 | ; tapinstall install OemVista.inf tapoas 15 | ; tapinstall update OemVista.inf tapoas 16 | ; tapinstall remove tapoas 17 | 18 | ;********************************************************* 19 | ; Note to Developers: 20 | ; 21 | ; If you are bundling the TAP-Windows driver with your app, 22 | ; you should try to rename it in such a way that it will 23 | ; not collide with other instances of TAP-Windows defined 24 | ; by other apps. Multiple versions of the TAP-Windows 25 | ; driver, each installed by different apps, can coexist 26 | ; on the same machine if you follow these guidelines. 27 | ; NOTE: these instructions assume you are editing the 28 | ; generated OemWin2k.inf file, not the source 29 | ; OemWin2k.inf.in file which is preprocessed by winconfig 30 | ; and uses macro definitions from settings.in. 31 | ; 32 | ; (1) Rename all tapXXXX instances in this file to 33 | ; something different (use at least 5 characters 34 | ; for this name!) 35 | ; (2) Change the "!define TAP" definition in openvpn.nsi 36 | ; to match what you changed tapXXXX to. 37 | ; (3) Change TARGETNAME in SOURCES to match what you 38 | ; changed tapXXXX to. 39 | ; (4) Change TAP_COMPONENT_ID in common.h to match what 40 | ; you changed tapXXXX to. 41 | ; (5) Change SZDEPENDENCIES in service.h to match what 42 | ; you changed tapXXXX to. 43 | ; (6) Change DeviceDescription and Provider strings. 44 | ; (7) Change PRODUCT_TAP_WIN_DEVICE_DESCRIPTION in constants.h to what you 45 | ; set DeviceDescription to. 46 | ; 47 | ;********************************************************* 48 | 49 | [Version] 50 | Signature = "$Windows NT$" 51 | CatalogFile = @PRODUCT_TAP_WIN_COMPONENT_ID@.cat 52 | ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} 53 | Provider = %Provider% 54 | Class = Net 55 | 56 | ; This version number should match the version 57 | ; number given in ..\version.m4. 58 | DriverVer=filled in by stampinf 59 | 60 | [Strings] 61 | DeviceDescription = "@PRODUCT_TAP_WIN_DEVICE_DESCRIPTION@" 62 | Provider = "@PRODUCT_TAP_WIN_PROVIDER@" 63 | 64 | ;---------------------------------------------------------------- 65 | ; Manufacturer + Product Section (Done) 66 | ;---------------------------------------------------------------- 67 | [Manufacturer] 68 | %Provider% = @PRODUCT_TAP_WIN_COMPONENT_ID@, NT$ARCH$ 69 | 70 | [@PRODUCT_TAP_WIN_COMPONENT_ID@.NT$ARCH$] 71 | %DeviceDescription% = @PRODUCT_TAP_WIN_COMPONENT_ID@.ndi, root\@PRODUCT_TAP_WIN_COMPONENT_ID@ ; Root enumerated 72 | %DeviceDescription% = @PRODUCT_TAP_WIN_COMPONENT_ID@.ndi, @PRODUCT_TAP_WIN_COMPONENT_ID@ ; Legacy 73 | 74 | ;--------------------------------------------------------------- 75 | ; Driver Section (Done) 76 | ;--------------------------------------------------------------- 77 | 78 | ;----------------- Characteristics ------------ 79 | ; NCF_PHYSICAL = 0x04 80 | ; NCF_VIRTUAL = 0x01 81 | ; NCF_SOFTWARE_ENUMERATED = 0x02 82 | ; NCF_HIDDEN = 0x08 83 | ; NCF_NO_SERVICE = 0x10 84 | ; NCF_HAS_UI = 0x80 85 | ;----------------- Characteristics ------------ 86 | 87 | [@PRODUCT_TAP_WIN_COMPONENT_ID@.ndi] 88 | CopyFiles = @PRODUCT_TAP_WIN_COMPONENT_ID@.driver, @PRODUCT_TAP_WIN_COMPONENT_ID@.files 89 | AddReg = @PRODUCT_TAP_WIN_COMPONENT_ID@.reg 90 | AddReg = @PRODUCT_TAP_WIN_COMPONENT_ID@.params.reg 91 | Characteristics = @PRODUCT_TAP_WIN_CHARACTERISTICS@ 92 | *IfType = 53 ; IF_TYPE_PROP_VIRTUAL 93 | *MediaType = 0x0 ; NdisMedium802_3 94 | *PhysicalMediaType = 0 ; NdisPhysicalMediumUnspecified 95 | 96 | [@PRODUCT_TAP_WIN_COMPONENT_ID@.ndi.Services] 97 | AddService = @PRODUCT_TAP_WIN_COMPONENT_ID@, 2, @PRODUCT_TAP_WIN_COMPONENT_ID@.service 98 | 99 | [@PRODUCT_TAP_WIN_COMPONENT_ID@.reg] 100 | HKR, Ndi, Service, 0, "@PRODUCT_TAP_WIN_COMPONENT_ID@" 101 | HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" 102 | HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" 103 | HKR, , Manufacturer, 0, "%Provider%" 104 | HKR, , ProductName, 0, "%DeviceDescription%" 105 | 106 | [@PRODUCT_TAP_WIN_COMPONENT_ID@.params.reg] 107 | HKR, Ndi\params\MTU, ParamDesc, 0, "MTU" 108 | HKR, Ndi\params\MTU, Type, 0, "int" 109 | HKR, Ndi\params\MTU, Default, 0, "1500" 110 | HKR, Ndi\params\MTU, Optional, 0, "0" 111 | HKR, Ndi\params\MTU, Min, 0, "100" 112 | HKR, Ndi\params\MTU, Max, 0, "1500" 113 | HKR, Ndi\params\MTU, Step, 0, "1" 114 | HKR, Ndi\params\MediaStatus, ParamDesc, 0, "Media Status" 115 | HKR, Ndi\params\MediaStatus, Type, 0, "enum" 116 | HKR, Ndi\params\MediaStatus, Default, 0, "0" 117 | HKR, Ndi\params\MediaStatus, Optional, 0, "0" 118 | HKR, Ndi\params\MediaStatus\enum, "0", 0, "Application Controlled" 119 | HKR, Ndi\params\MediaStatus\enum, "1", 0, "Always Connected" 120 | HKR, Ndi\params\MAC, ParamDesc, 0, "MAC Address" 121 | HKR, Ndi\params\MAC, Type, 0, "edit" 122 | HKR, Ndi\params\MAC, Optional, 0, "1" 123 | HKR, Ndi\params\AllowNonAdmin, ParamDesc, 0, "Non-Admin Access" 124 | HKR, Ndi\params\AllowNonAdmin, Type, 0, "enum" 125 | HKR, Ndi\params\AllowNonAdmin, Default, 0, "1" 126 | HKR, Ndi\params\AllowNonAdmin, Optional, 0, "0" 127 | HKR, Ndi\params\AllowNonAdmin\enum, "0", 0, "Not Allowed" 128 | HKR, Ndi\params\AllowNonAdmin\enum, "1", 0, "Allowed" 129 | 130 | ;---------------------------------------------------------------- 131 | ; Service Section 132 | ;---------------------------------------------------------------- 133 | 134 | ;---------- Service Type ------------- 135 | ; SERVICE_KERNEL_DRIVER = 0x01 136 | ; SERVICE_WIN32_OWN_PROCESS = 0x10 137 | ;---------- Service Type ------------- 138 | 139 | ;---------- Start Mode --------------- 140 | ; SERVICE_BOOT_START = 0x0 141 | ; SERVICE_SYSTEM_START = 0x1 142 | ; SERVICE_AUTO_START = 0x2 143 | ; SERVICE_DEMAND_START = 0x3 144 | ; SERVICE_DISABLED = 0x4 145 | ;---------- Start Mode --------------- 146 | 147 | [@PRODUCT_TAP_WIN_COMPONENT_ID@.service] 148 | DisplayName = %DeviceDescription% 149 | ServiceType = 1 150 | StartType = 3 151 | ErrorControl = 1 152 | LoadOrderGroup = NDIS 153 | ServiceBinary = %12%\@PRODUCT_TAP_WIN_COMPONENT_ID@.sys 154 | 155 | ;----------------------------------------------------------------- 156 | ; File Installation 157 | ;----------------------------------------------------------------- 158 | 159 | ;----------------- Copy Flags ------------ 160 | ; COPYFLG_NOSKIP = 0x02 161 | ; COPYFLG_NOVERSIONCHECK = 0x04 162 | ;----------------- Copy Flags ------------ 163 | 164 | ; SourceDisksNames 165 | ; diskid = description[, [tagfile] [, , subdir]] 166 | ; 1 = "Intel Driver Disk 1",e100bex.sys,, 167 | 168 | [SourceDisksNames] 169 | 1 = %DeviceDescription%, @PRODUCT_TAP_WIN_COMPONENT_ID@.sys 170 | 171 | ; SourceDisksFiles 172 | ; filename_on_source = diskID[, [subdir][, size]] 173 | ; e100bex.sys = 1,, ; on distribution disk 1 174 | 175 | [SourceDisksFiles] 176 | @PRODUCT_TAP_WIN_COMPONENT_ID@.sys = 1 177 | 178 | [DestinationDirs] 179 | @PRODUCT_TAP_WIN_COMPONENT_ID@.files = 11 180 | @PRODUCT_TAP_WIN_COMPONENT_ID@.driver = 12 181 | 182 | [@PRODUCT_TAP_WIN_COMPONENT_ID@.files] 183 | ; TapPanel.cpl,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK 184 | ; cipsrvr.exe,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK 185 | 186 | [@PRODUCT_TAP_WIN_COMPONENT_ID@.driver] 187 | @PRODUCT_TAP_WIN_COMPONENT_ID@.sys,,,6 ; COPYFLG_NOSKIP | COPYFLG_NOVERSIONCHECK 188 | 189 | ;--------------------------------------------------------------- 190 | ; End 191 | ;--------------------------------------------------------------- 192 | -------------------------------------------------------------------------------- /src/adapter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | #ifndef __TAP_ADAPTER_CONTEXT_H_ 25 | #define __TAP_ADAPTER_CONTEXT_H_ 26 | 27 | // Memory allocation tags. 28 | #define TAP_ADAPTER_TAG ((ULONG)'ApaT') // "TapA 29 | #define TAP_RX_NBL_TAG ((ULONG)'RpaT') // "TapR 30 | #define TAP_RX_INJECT_BUFFER_TAG ((ULONG)'IpaT') // "TapI 31 | 32 | #define TAP_MAX_NDIS_NAME_LENGTH 64 // 38 character GUID string plus extra.. 33 | #define TAP_MAX_NDIS_DIAG_NAME_LENGTH 96 // Diag name is a little longer 34 | 35 | // TAP receive indication NBL flag definitions. 36 | #define TAP_RX_NBL_FLAGS NBL_FLAGS_MINIPORT_RESERVED 37 | #define TAP_RX_NBL_FLAGS_CLEAR_ALL(_NBL) ((_NBL)->Flags &= ~TAP_RX_NBL_FLAGS) 38 | #define TAP_RX_NBL_FLAG_SET(_NBL, _F) ((_NBL)->Flags |= ((_F) & TAP_RX_NBL_FLAGS)) 39 | #define TAP_RX_NBL_FLAG_CLEAR(_NBL, _F) ((_NBL)->Flags &= ~((_F) & TAP_RX_NBL_FLAGS)) 40 | #define TAP_RX_NBL_FLAG_TEST(_NBL, _F) (((_NBL)->Flags & ((_F) & TAP_RX_NBL_FLAGS)) != 0) 41 | 42 | #define TAP_RX_NBL_FLAGS_IS_P2P 0x00001000 43 | #define TAP_RX_NBL_FLAGS_IS_INJECTED 0x00002000 44 | 45 | 46 | // True iff the given address was assigned by the local administrator 47 | #define NIC_ADDR_IS_LOCALLY_ADMINISTERED(_addr) \ 48 | (BOOLEAN)(((PUCHAR)(_addr))[0] & ((UCHAR)0x02)) 49 | 50 | // MSDN Ref: http://msdn.microsoft.com/en-us/library/windows/hardware/ff560490(v=vs.85).aspx 51 | typedef 52 | enum _TAP_MINIPORT_ADAPTER_STATE 53 | { 54 | // The Halted state is the initial state of all adapters. When an 55 | // adapter is in the Halted state, NDIS can call the driver's 56 | // MiniportInitializeEx function to initialize the adapter. 57 | MiniportHaltedState, 58 | 59 | // In the Shutdown state, a system shutdown and restart must occur 60 | // before the system can use the adapter again. 61 | MiniportShutdownState, 62 | 63 | // In the Initializing state, a miniport driver completes any 64 | //operations that are required to initialize an adapter. 65 | MiniportInitializingState, 66 | 67 | // Entering the Paused state... 68 | MiniportPausingState, 69 | 70 | // In the Paused state, the adapter does not indicate received 71 | // network data or accept send requests. 72 | MiniportPausedState, 73 | 74 | // In the Running state, a miniport driver performs send and 75 | // receive processing for an adapter. 76 | MiniportRunning, 77 | 78 | // In the Restarting state, a miniport driver completes any 79 | // operations that are required to restart send and receive 80 | // operations for an adapter. 81 | MiniportRestartingState 82 | } TAP_MINIPORT_ADAPTER_STATE, *PTAP_MINIPORT_ADAPTER_STATE; 83 | 84 | // 85 | // Each adapter managed by this driver has a TapAdapter struct. 86 | // ------------------------------------------------------------ 87 | // Since there is a one-to-one relationship between adapter instances 88 | // and device instances this structure is the device extension as well. 89 | // 90 | typedef struct _TAP_ADAPTER_CONTEXT 91 | { 92 | LIST_ENTRY AdapterListLink; 93 | 94 | volatile LONG RefCount; 95 | 96 | NDIS_HANDLE MiniportAdapterHandle; 97 | 98 | NDIS_SPIN_LOCK AdapterLock; // Lock for protection of state and outstanding sends and recvs 99 | 100 | // 101 | // All fields that are protected by the AdapterLock are included 102 | // in the Locked structure to remind us to take the Lock 103 | // before accessing them :) 104 | // 105 | struct 106 | { 107 | TAP_MINIPORT_ADAPTER_STATE AdapterState; 108 | } Locked; 109 | 110 | BOOLEAN ResetInProgress; 111 | 112 | // 113 | // NetCfgInstanceId as UNICODE_STRING 114 | // ---------------------------------- 115 | // This a GUID string provided by NDIS that identifies the adapter instance. 116 | // An example is: 117 | // 118 | // NetCfgInstanceId={410EB49D-2381-4FE7-9B36-498E22619DF0} 119 | // 120 | // Other names are derived from NetCfgInstanceId. For example, MiniportName: 121 | // 122 | // MiniportName=\DEVICE\{410EB49D-2381-4FE7-9B36-498E22619DF0} 123 | // 124 | NDIS_STRING NetCfgInstanceId; 125 | WCHAR NetCfgInstanceIdBuffer[TAP_MAX_NDIS_NAME_LENGTH]; 126 | 127 | # define MINIPORT_INSTANCE_ID(a) ((a)->NetCfgInstanceIdAnsi.Buffer) 128 | ANSI_STRING NetCfgInstanceIdAnsi; // Used occasionally 129 | 130 | ULONG MtuSize; // 1500 byte (typical) 131 | 132 | // TRUE if adapter should always be "connected" even when device node 133 | // is not open by a userspace process. 134 | // 135 | // FALSE if connection state is application controlled. 136 | BOOLEAN MediaStateAlwaysConnected; 137 | 138 | // TRUE if device is "connected". 139 | BOOLEAN LogicalMediaState; 140 | 141 | NDIS_DEVICE_POWER_STATE CurrentPowerState; 142 | 143 | BOOLEAN AllowNonAdmin; 144 | 145 | MACADDR PermanentAddress; // From registry, if available 146 | MACADDR CurrentAddress; 147 | 148 | // Device registration parameters from NdisRegisterDeviceEx. 149 | NDIS_STRING DeviceName; 150 | WCHAR DeviceNameBuffer[TAP_MAX_NDIS_NAME_LENGTH]; 151 | 152 | NDIS_STRING LinkName; 153 | WCHAR LinkNameBuffer[TAP_MAX_NDIS_NAME_LENGTH]; 154 | 155 | NDIS_HANDLE DeviceHandle; 156 | PDEVICE_OBJECT DeviceObject; 157 | BOOLEAN TapDeviceCreated; // WAS: m_TapIsRunning 158 | 159 | PFILE_OBJECT TapFileObject; // Exclusive access 160 | BOOLEAN TapFileIsOpen; // WAS: m_TapOpens 161 | LONG TapFileOpenCount; // WAS: m_NumTapOpens 162 | 163 | NDIS_STRING DiagDeviceName; 164 | WCHAR DiagDeviceNameBuffer[TAP_MAX_NDIS_DIAG_NAME_LENGTH]; 165 | 166 | NDIS_STRING DiagLinkName; 167 | WCHAR DiagLinkNameBuffer[TAP_MAX_NDIS_DIAG_NAME_LENGTH]; 168 | 169 | NDIS_HANDLE DiagDeviceHandle; 170 | PDEVICE_OBJECT DiagDeviceObject; 171 | 172 | // Cancel-Safe read IRP queue. 173 | TAP_IRP_CSQ PendingReadIrpQueue; 174 | 175 | // Queue containing TAP packets representing host send NBs. These are 176 | // waiting to be read by user-mode application. 177 | TAP_PACKET_QUEUE SendPacketQueue; 178 | 179 | // Transmit flow control 180 | KSPIN_LOCK FlowControlLock; 181 | PNET_BUFFER_LIST FlowControlList; 182 | BOOLEAN FlowControlHasPackets; 183 | 184 | // NBL pool for making TAP receive indications. 185 | NDIS_HANDLE ReceiveNblPool; 186 | 187 | volatile LONG ReceiveNblInFlightCount; 188 | #define TAP_WAIT_POLL_LOOP_TIMEOUT 3000 // 3 seconds 189 | NDIS_EVENT ReceiveNblInFlightCountZeroEvent; 190 | 191 | // Info for point-to-point mode 192 | BOOLEAN m_tun; 193 | IPADDR m_localIP; 194 | IPADDR m_remoteNetwork; 195 | IPADDR m_remoteNetmask; 196 | ETH_HEADER m_TapToUser; 197 | ETH_HEADER m_UserToTap; 198 | ETH_HEADER m_UserToTap_IPv6; // same as UserToTap but proto=ipv6 199 | 200 | // Info for DHCP server masquerade 201 | BOOLEAN m_dhcp_enabled; 202 | IPADDR m_dhcp_addr; 203 | ULONG m_dhcp_netmask; 204 | IPADDR m_dhcp_server_ip; 205 | BOOLEAN m_dhcp_server_arp; 206 | MACADDR m_dhcp_server_mac; 207 | ULONG m_dhcp_lease_time; 208 | UCHAR m_dhcp_user_supplied_options_buffer[DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE]; 209 | ULONG m_dhcp_user_supplied_options_buffer_len; 210 | BOOLEAN m_dhcp_received_discover; 211 | ULONG m_dhcp_bad_requests; 212 | 213 | // Multicast list. Fixed size. 214 | ULONG ulMCListSize; 215 | UCHAR MCList[TAP_MAX_MCAST_LIST][MACADDR_SIZE]; 216 | 217 | ULONG PacketFilter; 218 | ULONG ulLookahead; 219 | 220 | ULONG PriorityBehavior; 221 | 222 | // 223 | // Statistics 224 | // ------------------------------------------------------------------------- 225 | // 226 | 227 | // Packet counts 228 | ULONG64 FramesRxDirected; 229 | ULONG64 FramesRxMulticast; 230 | ULONG64 FramesRxBroadcast; 231 | ULONG64 FramesTxDirected; 232 | ULONG64 FramesTxMulticast; 233 | ULONG64 FramesTxBroadcast; 234 | 235 | // Byte counts 236 | ULONG64 BytesRxDirected; 237 | ULONG64 BytesRxMulticast; 238 | ULONG64 BytesRxBroadcast; 239 | ULONG64 BytesTxDirected; 240 | ULONG64 BytesTxMulticast; 241 | ULONG64 BytesTxBroadcast; 242 | 243 | // Count of transmit errors 244 | ULONG TxAbortExcessCollisions; 245 | ULONG TxLateCollisions; 246 | ULONG TxDmaUnderrun; 247 | ULONG TxLostCRS; 248 | ULONG TxOKButDeferred; 249 | ULONG OneRetry; 250 | ULONG MoreThanOneRetry; 251 | ULONG TotalRetries; 252 | ULONG TransmitFailuresOther; 253 | 254 | // Count of receive errors 255 | ULONG RxCrcErrors; 256 | ULONG RxAlignmentErrors; 257 | ULONG RxResourceErrors; 258 | ULONG RxDmaOverrunErrors; 259 | ULONG RxCdtFrames; 260 | ULONG RxRuntErrors; 261 | 262 | #if PACKET_TRUNCATION_CHECK 263 | LONG m_RxTrunc, m_TxTrunc; 264 | #endif 265 | 266 | BOOLEAN m_InterfaceIsRunning; 267 | LONG m_Rx, m_RxErr; 268 | NDIS_MEDIUM m_Medium; 269 | 270 | // Help to tear down the adapter by keeping 271 | // some state information on allocated 272 | // resources. 273 | BOOLEAN m_CalledAdapterFreeResources; 274 | BOOLEAN m_RegisteredAdapterShutdownHandler; 275 | 276 | } TAP_ADAPTER_CONTEXT, *PTAP_ADAPTER_CONTEXT; 277 | 278 | FORCEINLINE 279 | LONG 280 | tapAdapterContextReference( 281 | __in PTAP_ADAPTER_CONTEXT Adapter 282 | ) 283 | { 284 | LONG refCount = NdisInterlockedIncrement(&Adapter->RefCount); 285 | 286 | ASSERT(refCount>1); // Cannot dereference a zombie. 287 | 288 | return refCount; 289 | } 290 | 291 | VOID 292 | tapAdapterContextFree( 293 | __in PTAP_ADAPTER_CONTEXT Adapter 294 | ); 295 | 296 | FORCEINLINE 297 | LONG 298 | tapAdapterContextDereference( 299 | IN PTAP_ADAPTER_CONTEXT Adapter 300 | ) 301 | { 302 | LONG refCount = NdisInterlockedDecrement(&Adapter->RefCount); 303 | ASSERT(refCount >= 0); 304 | if (!refCount) 305 | { 306 | tapAdapterContextFree(Adapter); 307 | } 308 | 309 | return refCount; 310 | } 311 | 312 | _Requires_lock_not_held_(Adapter->AdapterLock) 313 | _Acquires_lock_(Adapter->AdapterLock) 314 | _IRQL_requires_max_(DISPATCH_LEVEL) 315 | _IRQL_saves_global_(SpinLock, Adapter) 316 | _IRQL_raises_(DISPATCH_LEVEL) 317 | VOID 318 | tapAdapterAcquireLock( 319 | __in PTAP_ADAPTER_CONTEXT Adapter, 320 | __in BOOLEAN DispatchLevel 321 | ); 322 | 323 | _Requires_lock_held_(Adapter->AdapterLock) 324 | _Releases_lock_(Adapter->AdapterLock) 325 | _IRQL_restores_global_(SpinLock, Adapter) 326 | _IRQL_requires_(DISPATCH_LEVEL) 327 | VOID 328 | tapAdapterReleaseLock( 329 | __in PTAP_ADAPTER_CONTEXT Adapter, 330 | __in BOOLEAN DispatchLevel 331 | ); 332 | 333 | // Returns with added reference on adapter context. 334 | PTAP_ADAPTER_CONTEXT 335 | tapAdapterContextFromDeviceObject( 336 | __in PDEVICE_OBJECT DeviceObject 337 | ); 338 | 339 | BOOLEAN 340 | tapAdapterReadAndWriteReady( 341 | __in PTAP_ADAPTER_CONTEXT Adapter 342 | ); 343 | 344 | NDIS_STATUS 345 | tapAdapterSendAndReceiveReady( 346 | __in PTAP_ADAPTER_CONTEXT Adapter 347 | ); 348 | 349 | ULONG 350 | tapGetRawPacketFrameType( 351 | __in PTAP_ADAPTER_CONTEXT Adapter, 352 | __in PVOID PacketBuffer, 353 | __in ULONG PacketLength 354 | ); 355 | 356 | ULONG 357 | tapGetNetBufferFrameType( 358 | __in PNET_BUFFER NetBuffer 359 | ); 360 | 361 | ULONG 362 | tapGetNetBufferCountsFromNetBufferList( 363 | __in PNET_BUFFER_LIST NetBufferList, 364 | __out_opt PULONG TotalByteCount // Of all linked NBs 365 | ); 366 | 367 | // Prototypes for standard NDIS miniport entry points 368 | MINIPORT_SET_OPTIONS AdapterSetOptions; 369 | MINIPORT_INITIALIZE AdapterCreate; 370 | MINIPORT_HALT AdapterHalt; 371 | MINIPORT_UNLOAD TapDriverUnload; 372 | MINIPORT_PAUSE AdapterPause; 373 | MINIPORT_RESTART AdapterRestart; 374 | MINIPORT_OID_REQUEST AdapterOidRequest; 375 | MINIPORT_SEND_NET_BUFFER_LISTS AdapterSendNetBufferLists; 376 | MINIPORT_RETURN_NET_BUFFER_LISTS AdapterReturnNetBufferLists; 377 | MINIPORT_CANCEL_SEND AdapterCancelSend; 378 | MINIPORT_CHECK_FOR_HANG AdapterCheckForHangEx; 379 | MINIPORT_RESET AdapterReset; 380 | MINIPORT_DEVICE_PNP_EVENT_NOTIFY AdapterDevicePnpEventNotify; 381 | MINIPORT_SHUTDOWN AdapterShutdownEx; 382 | MINIPORT_CANCEL_OID_REQUEST AdapterCancelOidRequest; 383 | MINIPORT_DIRECT_OID_REQUEST AdapterDirectOidRequest; 384 | MINIPORT_CANCEL_DIRECT_OID_REQUEST AdapterCancelDirectOidRequest; 385 | 386 | #endif // __TAP_ADAPTER_CONTEXT_H_ -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | #define PRODUCT_NAME "@PRODUCT_NAME@" 2 | #define PRODUCT_VERSION "@PRODUCT_VERSION@" 3 | #define PRODUCT_VERSION_RESOURCE @PRODUCT_VERSION_RESOURCE@ 4 | #define PRODUCT_TAP_WIN_COMPONENT_ID "@PRODUCT_TAP_WIN_COMPONENT_ID@" 5 | #define PRODUCT_TAP_WIN_MAJOR @PRODUCT_TAP_WIN_MAJOR@ 6 | #define PRODUCT_TAP_WIN_MINOR @PRODUCT_TAP_WIN_MINOR@ 7 | #define PRODUCT_TAP_WIN_PROVIDER "@PRODUCT_TAP_WIN_PROVIDER@" 8 | #define PRODUCT_TAP_WIN_DEVICE_DESCRIPTION "@PRODUCT_TAP_WIN_DEVICE_DESCRIPTION@" 9 | #define PRODUCT_TAP_WIN_RELDATE "@PRODUCT_TAP_WIN_RELDATE@" 10 | #define PRODUCT_TAP_WIN_REVISION @PRODUCT_TAP_WIN_REVISION@ 11 | #define PRODUCT_TAP_WIN_BUILD @PRODUCT_TAP_WIN_BUILD@ 12 | -------------------------------------------------------------------------------- /src/constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | //==================================================================== 26 | // Product and Version public settings 27 | //==================================================================== 28 | 29 | #define PRODUCT_STRING PRODUCT_TAP_DEVICE_DESCRIPTION 30 | 31 | // 32 | // The major and minor versions should be defined in a central location such 33 | // as a makefile that is preprocessed to insert the current values. 34 | // 35 | 36 | #define TAP_DRIVER_VENDOR_VERSION ((TAP_DRIVER_MAJOR_VERSION << 16) | TAP_DRIVER_MINOR_VERSION) 37 | 38 | // 39 | // Define the NDIS miniport interface version that this driver targets. 40 | // 41 | 42 | #if !defined(NDIS620_MINIPORT) || !defined(NDIS630_MINIPORT) 43 | #error "tap-windows6 only supports NDIS 6.20 and 6.30 at this time" 44 | #endif 45 | 46 | //=========================================================== 47 | // Driver constants 48 | //=========================================================== 49 | 50 | #define ETHERNET_HEADER_SIZE (sizeof (ETH_HEADER)) 51 | #define ETHERNET_MTU 1500 52 | #define ETHERNET_PACKET_SIZE (ETHERNET_MTU + ETHERNET_HEADER_SIZE) 53 | #define DEFAULT_PACKET_LOOKAHEAD (ETHERNET_PACKET_SIZE) 54 | #define VLAN_TAG_SIZE 4 55 | 56 | //=========================================================== 57 | // Medium properties 58 | //=========================================================== 59 | 60 | #define TAP_FRAME_HEADER_SIZE ETHERNET_HEADER_SIZE 61 | #define TAP_FRAME_MAX_DATA_SIZE ETHERNET_MTU 62 | #define TAP_MAX_FRAME_SIZE (TAP_FRAME_HEADER_SIZE + TAP_FRAME_MAX_DATA_SIZE) 63 | #define TAP_MIN_FRAME_SIZE 60 64 | 65 | #define TAP_MEDIUM_TYPE NdisMedium802_3 66 | 67 | //=========================================================== 68 | // Physical adapter properties 69 | //=========================================================== 70 | 71 | // The bus that connects the adapter to the PC. 72 | // (Example: PCI adapters should use NdisInterfacePci). 73 | #define TAP_INTERFACE_TYPE NdisInterfaceInternal 74 | 75 | #define TAP_VENDOR_DESC PRODUCT_TAP_WIN_DEVICE_DESCRIPTION 76 | 77 | // Highest byte is the NIC byte plus three vendor bytes. This is normally 78 | // obtained from the NIC. 79 | #define TAP_VENDOR_ID 0x00FFFFFF 80 | 81 | // If you have physical hardware on 802.3, use NdisPhysicalMedium802_3. 82 | #define TAP_PHYSICAL_MEDIUM NdisPhysicalMediumUnspecified 83 | 84 | // Claim to be 1Gbps duplex 85 | #define MEGABITS_PER_SECOND 1000000ULL 86 | #define TAP_XMIT_SPEED (1000ULL*MEGABITS_PER_SECOND) 87 | #define TAP_RECV_SPEED (1000ULL*MEGABITS_PER_SECOND) 88 | 89 | // Max number of multicast addresses supported in hardware 90 | #define TAP_MAX_MCAST_LIST 32 91 | 92 | #define TAP_MAX_LOOKAHEAD TAP_FRAME_MAX_DATA_SIZE 93 | 94 | // Simulated send/receive buffer size for the virtual device. 95 | #define TAP_BUFFER_SIZE 0x400000 96 | 97 | // Set this value to TRUE if there is a physical adapter. 98 | #define TAP_HAS_PHYSICAL_CONNECTOR FALSE 99 | #define TAP_ACCESS_TYPE NET_IF_ACCESS_BROADCAST 100 | #define TAP_DIRECTION_TYPE NET_IF_DIRECTION_SENDRECEIVE 101 | #define TAP_CONNECTION_TYPE NET_IF_CONNECTION_DEDICATED 102 | 103 | // This value must match the *IfType in the driver .inf file 104 | #define TAP_IFTYPE IF_TYPE_PROP_VIRTUAL 105 | 106 | // 107 | // This is a virtual device, so it can tolerate surprise removal and 108 | // suspend. Ensure the correct flags are set for your hardware. 109 | // 110 | #define TAP_ADAPTER_ATTRIBUTES_FLAGS (\ 111 | NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK | NDIS_MINIPORT_ATTRIBUTES_NDIS_WDM | NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND) 112 | 113 | #define TAP_SUPPORTED_FILTERS ( \ 114 | NDIS_PACKET_TYPE_DIRECTED | \ 115 | NDIS_PACKET_TYPE_MULTICAST | \ 116 | NDIS_PACKET_TYPE_BROADCAST | \ 117 | NDIS_PACKET_TYPE_ALL_LOCAL | \ 118 | NDIS_PACKET_TYPE_PROMISCUOUS | \ 119 | NDIS_PACKET_TYPE_ALL_MULTICAST) 120 | 121 | #define TAP_MAX_MCAST_LIST 32 // Max length of multicast address list 122 | 123 | // 124 | // Specify a bitmask that defines optional properties of the NIC. 125 | // This miniport indicates receive with NdisMIndicateReceiveNetBufferLists 126 | // function. Such a driver should set this NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 127 | // flag. 128 | // 129 | // NDIS_MAC_OPTION_NO_LOOPBACK tells NDIS that NIC has no internal 130 | // loopback support so NDIS will manage loopbacks on behalf of 131 | // this driver. 132 | // 133 | // NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA tells the protocol that 134 | // our receive buffer is not on a device-specific card. If 135 | // NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA is not set, multi-buffer 136 | // indications are copied to a single flat buffer. 137 | // 138 | 139 | #define TAP_MAC_OPTIONS (\ 140 | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | \ 141 | NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | \ 142 | NDIS_MAC_OPTION_NO_LOOPBACK | \ 143 | NDIS_MAC_OPTION_8021P_PRIORITY) 144 | 145 | #define TAP_ADAPTER_CHECK_FOR_HANG_TIME_IN_SECONDS 4 146 | 147 | 148 | // NDIS 6.x miniports must support all counters in OID_GEN_STATISTICS. 149 | #define TAP_SUPPORTED_STATISTICS (\ 150 | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV | \ 151 | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV | \ 152 | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV | \ 153 | NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV | \ 154 | NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS | \ 155 | NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR | \ 156 | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT | \ 157 | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT | \ 158 | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT | \ 159 | NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT | \ 160 | NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR | \ 161 | NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS | \ 162 | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV | \ 163 | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV | \ 164 | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV | \ 165 | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT | \ 166 | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT | \ 167 | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT) 168 | 169 | 170 | #define MINIMUM_MTU 576 // USE TCP Minimum MTU 171 | #define MAXIMUM_MTU 65536 // IP maximum MTU 172 | 173 | #define PACKET_QUEUE_SIZE 64 // tap -> userspace queue size 174 | #define IRP_QUEUE_SIZE 16 // max number of simultaneous i/o operations from userspace 175 | #define INJECT_QUEUE_SIZE 16 // DHCP/ARP -> tap injection queue 176 | 177 | #define TAP_LITTLE_ENDIAN // affects ntohs, htonl, etc. functions 178 | -------------------------------------------------------------------------------- /src/device.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #ifndef __TAP_DEVICE_H_ 26 | #define __TAP_DEVICE_H_ 27 | 28 | //====================================================================== 29 | // TAP Prototypes for standard Win32 device I/O entry points 30 | //====================================================================== 31 | 32 | __drv_dispatchType(IRP_MJ_CREATE) 33 | DRIVER_DISPATCH TapDeviceCreate; 34 | 35 | __drv_dispatchType(IRP_MJ_READ) 36 | DRIVER_DISPATCH TapDeviceRead; 37 | 38 | __drv_dispatchType(IRP_MJ_WRITE) 39 | DRIVER_DISPATCH TapDeviceWrite; 40 | 41 | __drv_dispatchType(IRP_MJ_DEVICE_CONTROL) 42 | DRIVER_DISPATCH TapDeviceControl; 43 | 44 | __drv_dispatchType(IRP_MJ_CLEANUP) 45 | DRIVER_DISPATCH TapDeviceCleanup; 46 | 47 | __drv_dispatchType(IRP_MJ_CLOSE) 48 | DRIVER_DISPATCH TapDeviceClose; 49 | 50 | __drv_dispatchType(IRP_MJ_CREATE) 51 | DRIVER_DISPATCH TapDiagDeviceCreate; 52 | 53 | __drv_dispatchType(IRP_MJ_DEVICE_CONTROL) 54 | DRIVER_DISPATCH TapDiagDeviceControl; 55 | 56 | __drv_dispatchType(IRP_MJ_CLOSE) 57 | DRIVER_DISPATCH TapDiagDeviceClose; 58 | 59 | #endif // __TAP_DEVICE_H_ -------------------------------------------------------------------------------- /src/dhcp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #include "tap.h" 26 | 27 | //========================= 28 | // Code to set DHCP options 29 | //========================= 30 | 31 | VOID 32 | SetDHCPOpt( 33 | __in DHCPMsg *m, 34 | __in void *data, 35 | __in unsigned int len 36 | ) 37 | { 38 | if (!m->overflow) 39 | { 40 | if (m->optlen + len <= DHCP_OPTIONS_BUFFER_SIZE) 41 | { 42 | if (len) 43 | { 44 | NdisMoveMemory (m->msg.options + m->optlen, data, len); 45 | m->optlen += len; 46 | } 47 | } 48 | else 49 | { 50 | m->overflow = TRUE; 51 | } 52 | } 53 | } 54 | 55 | VOID 56 | SetDHCPOpt0( 57 | __in DHCPMsg *msg, 58 | __in int type 59 | ) 60 | { 61 | DHCPOPT0 opt; 62 | opt.type = (UCHAR) type; 63 | SetDHCPOpt (msg, &opt, sizeof (opt)); 64 | } 65 | 66 | VOID 67 | SetDHCPOpt8( 68 | __in DHCPMsg *msg, 69 | __in int type, 70 | __in ULONG data 71 | ) 72 | { 73 | DHCPOPT8 opt; 74 | opt.type = (UCHAR) type; 75 | opt.len = sizeof (opt.data); 76 | opt.data = (UCHAR) data; 77 | SetDHCPOpt (msg, &opt, sizeof (opt)); 78 | } 79 | 80 | VOID 81 | SetDHCPOpt32( 82 | __in DHCPMsg *msg, 83 | __in int type, 84 | __in ULONG data 85 | ) 86 | { 87 | DHCPOPT32 opt; 88 | opt.type = (UCHAR) type; 89 | opt.len = sizeof (opt.data); 90 | opt.data = data; 91 | SetDHCPOpt (msg, &opt, sizeof (opt)); 92 | } 93 | 94 | //============== 95 | // Checksum code 96 | //============== 97 | 98 | USHORT 99 | ip_checksum( 100 | __in const UCHAR *buf, 101 | __in const int len_ip_header 102 | ) 103 | { 104 | USHORT word16; 105 | ULONG sum = 0; 106 | int i; 107 | 108 | // make 16 bit words out of every two adjacent 8 bit words in the packet 109 | // and add them up 110 | for (i = 0; i < len_ip_header - 1; i += 2) 111 | { 112 | word16 = ((buf[i] << 8) & 0xFF00) + (buf[i+1] & 0xFF); 113 | sum += (ULONG) word16; 114 | } 115 | 116 | // take only 16 bits out of the 32 bit sum and add up the carries 117 | while (sum >> 16) 118 | { 119 | sum = (sum & 0xFFFF) + (sum >> 16); 120 | } 121 | 122 | // one's complement the result 123 | return ((USHORT) ~sum); 124 | } 125 | 126 | USHORT 127 | udp_checksum ( 128 | __in const UCHAR *buf, 129 | __in const int len_udp, 130 | __in const UCHAR *src_addr, 131 | __in const UCHAR *dest_addr 132 | ) 133 | { 134 | USHORT word16; 135 | ULONG sum = 0; 136 | int i; 137 | 138 | // make 16 bit words out of every two adjacent 8 bit words and 139 | // calculate the sum of all 16 bit words 140 | for (i = 0; i < len_udp; i += 2) 141 | { 142 | word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_udp) ? (buf[i+1] & 0xFF) : 0); 143 | sum += word16; 144 | } 145 | 146 | // add the UDP pseudo header which contains the IP source and destination addresses 147 | for (i = 0; i < 4; i += 2) 148 | { 149 | word16 =((src_addr[i] << 8) & 0xFF00) + (src_addr[i+1] & 0xFF); 150 | sum += word16; 151 | } 152 | 153 | for (i = 0; i < 4; i += 2) 154 | { 155 | word16 =((dest_addr[i] << 8) & 0xFF00) + (dest_addr[i+1] & 0xFF); 156 | sum += word16; 157 | } 158 | 159 | // the protocol number and the length of the UDP packet 160 | sum += (USHORT) IPPROTO_UDP + (USHORT) len_udp; 161 | 162 | // keep only the last 16 bits of the 32 bit calculated sum and add the carries 163 | while (sum >> 16) 164 | { 165 | sum = (sum & 0xFFFF) + (sum >> 16); 166 | } 167 | 168 | // Take the one's complement of sum 169 | return ((USHORT) ~sum); 170 | } 171 | 172 | //================================ 173 | // Set IP and UDP packet checksums 174 | //================================ 175 | 176 | VOID 177 | SetChecksumDHCPMsg( 178 | __in DHCPMsg *m 179 | ) 180 | { 181 | // Set IP checksum 182 | m->msg.pre.ip.check = htons (ip_checksum ((UCHAR *) &m->msg.pre.ip, sizeof (IPHDR))); 183 | 184 | // Set UDP Checksum 185 | m->msg.pre.udp.check = htons (udp_checksum ((UCHAR *) &m->msg.pre.udp, 186 | sizeof (UDPHDR) + sizeof (DHCP) + m->optlen, 187 | (UCHAR *)&m->msg.pre.ip.saddr, 188 | (UCHAR *)&m->msg.pre.ip.daddr)); 189 | } 190 | 191 | //=================== 192 | // DHCP message tests 193 | //=================== 194 | 195 | int 196 | GetDHCPMessageType( 197 | __in const DHCP *dhcp, 198 | __in const int optlen 199 | ) 200 | { 201 | const UCHAR *p = (UCHAR *) (dhcp + 1); 202 | int i; 203 | 204 | for (i = 0; i < optlen; ++i) 205 | { 206 | const UCHAR type = p[i]; 207 | const int room = optlen - i - 1; 208 | 209 | if (type == DHCP_END) // didn't find what we were looking for 210 | return -1; 211 | else if (type == DHCP_PAD) // no-operation 212 | ; 213 | else if (type == DHCP_MSG_TYPE) // what we are looking for 214 | { 215 | if (room >= 2) 216 | { 217 | if (p[i+1] == 1) // message length should be 1 218 | return p[i+2]; // return message type 219 | } 220 | return -1; 221 | } 222 | else // some other message 223 | { 224 | if (room >= 1) 225 | { 226 | const int len = p[i+1]; // get message length 227 | i += (len + 1); // advance to next message 228 | } 229 | } 230 | } 231 | return -1; 232 | } 233 | 234 | BOOLEAN 235 | DHCPMessageOurs ( 236 | __in const PTAP_ADAPTER_CONTEXT Adapter, 237 | __in const ETH_HEADER *eth, 238 | __in const IPHDR *ip, 239 | __in const UDPHDR *udp, 240 | __in const DHCP *dhcp 241 | ) 242 | { 243 | // Must be UDPv4 protocol 244 | if (!(eth->proto == htons (NDIS_ETH_TYPE_IPV4) && ip->protocol == IPPROTO_UDP)) 245 | { 246 | return FALSE; 247 | } 248 | 249 | // Source MAC must be our adapter 250 | if (!MAC_EQUAL (eth->src, Adapter->CurrentAddress)) 251 | { 252 | return FALSE; 253 | } 254 | 255 | // Dest MAC must be either broadcast or our virtual DHCP server 256 | if (!(ETH_IS_BROADCAST(eth->dest) 257 | || MAC_EQUAL (eth->dest, Adapter->m_dhcp_server_mac))) 258 | { 259 | return FALSE; 260 | } 261 | 262 | // Port numbers must be correct 263 | if (!(udp->dest == htons (BOOTPS_PORT) 264 | && udp->source == htons (BOOTPC_PORT))) 265 | { 266 | return FALSE; 267 | } 268 | 269 | // Hardware address must be MAC addr sized 270 | if (!(dhcp->hlen == sizeof (MACADDR))) 271 | { 272 | return FALSE; 273 | } 274 | 275 | // Hardware address must match our adapter 276 | if (!MAC_EQUAL (eth->src, dhcp->chaddr)) 277 | { 278 | return FALSE; 279 | } 280 | 281 | return TRUE; 282 | } 283 | 284 | 285 | //===================================================== 286 | // Build all of DHCP packet except for DHCP options. 287 | // Assume that *p has been zeroed before we are called. 288 | //===================================================== 289 | 290 | VOID 291 | BuildDHCPPre ( 292 | __in const PTAP_ADAPTER_CONTEXT Adapter, 293 | __inout DHCPPre *p, 294 | __in const ETH_HEADER *eth, 295 | __in const IPHDR *ip, 296 | __in const UDPHDR *udp, 297 | __in const DHCP *dhcp, 298 | __in const int optlen, 299 | __in const int type) 300 | { 301 | // Should we broadcast or direct to a specific MAC / IP address? 302 | const BOOLEAN broadcast = (type == DHCPNAK 303 | || ETH_IS_BROADCAST(eth->dest)); 304 | 305 | // 306 | // Build ethernet header 307 | // 308 | ETH_COPY_NETWORK_ADDRESS (p->eth.src, Adapter->m_dhcp_server_mac); 309 | 310 | if (broadcast) 311 | { 312 | memset(p->eth.dest,0xFF,ETH_LENGTH_OF_ADDRESS); 313 | } 314 | else 315 | { 316 | ETH_COPY_NETWORK_ADDRESS (p->eth.dest, eth->src); 317 | } 318 | 319 | p->eth.proto = htons (NDIS_ETH_TYPE_IPV4); 320 | 321 | // 322 | // Build IP header 323 | // 324 | p->ip.version_len = (4 << 4) | (sizeof (IPHDR) >> 2); 325 | p->ip.tos = 0; 326 | p->ip.tot_len = htons (sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen); 327 | p->ip.id = 0; 328 | p->ip.frag_off = 0; 329 | p->ip.ttl = 16; 330 | p->ip.protocol = IPPROTO_UDP; 331 | p->ip.check = 0; 332 | p->ip.saddr = Adapter->m_dhcp_server_ip; 333 | 334 | if (broadcast) 335 | { 336 | p->ip.daddr = ~0; 337 | } 338 | else 339 | { 340 | p->ip.daddr = Adapter->m_dhcp_addr; 341 | } 342 | 343 | // 344 | // Build UDP header 345 | // 346 | p->udp.source = htons (BOOTPS_PORT); 347 | p->udp.dest = htons (BOOTPC_PORT); 348 | p->udp.len = htons (sizeof (UDPHDR) + sizeof (DHCP) + optlen); 349 | p->udp.check = 0; 350 | 351 | // Build DHCP response 352 | 353 | p->dhcp.op = BOOTREPLY; 354 | p->dhcp.htype = 1; 355 | p->dhcp.hlen = sizeof (MACADDR); 356 | p->dhcp.hops = 0; 357 | p->dhcp.xid = dhcp->xid; 358 | p->dhcp.secs = 0; 359 | p->dhcp.flags = 0; 360 | p->dhcp.ciaddr = 0; 361 | 362 | if (type == DHCPNAK) 363 | { 364 | p->dhcp.yiaddr = 0; 365 | } 366 | else 367 | { 368 | p->dhcp.yiaddr = Adapter->m_dhcp_addr; 369 | } 370 | 371 | p->dhcp.siaddr = Adapter->m_dhcp_server_ip; 372 | p->dhcp.giaddr = 0; 373 | ETH_COPY_NETWORK_ADDRESS (p->dhcp.chaddr, eth->src); 374 | p->dhcp.magic = htonl (0x63825363); 375 | } 376 | 377 | //============================= 378 | // Build specific DHCP messages 379 | //============================= 380 | 381 | VOID 382 | SendDHCPMsg( 383 | __in PTAP_ADAPTER_CONTEXT Adapter, 384 | __in const int type, 385 | __in const ETH_HEADER *eth, 386 | __in const IPHDR *ip, 387 | __in const UDPHDR *udp, 388 | __in const DHCP *dhcp 389 | ) 390 | { 391 | DHCPMsg *pkt; 392 | 393 | if (!(type == DHCPOFFER || type == DHCPACK || type == DHCPNAK)) 394 | { 395 | DEBUGP (("[TAP] SendDHCPMsg: Bad DHCP type: %d\n", type)); 396 | return; 397 | } 398 | 399 | pkt = (DHCPMsg *) MemAlloc (sizeof (DHCPMsg), TRUE); 400 | 401 | if(pkt) 402 | { 403 | //----------------------- 404 | // Build DHCP options 405 | //----------------------- 406 | 407 | // Message Type 408 | SetDHCPOpt8 (pkt, DHCP_MSG_TYPE, type); 409 | 410 | // Server ID 411 | SetDHCPOpt32 (pkt, DHCP_SERVER_ID, Adapter->m_dhcp_server_ip); 412 | 413 | if (type == DHCPOFFER || type == DHCPACK) 414 | { 415 | // Lease Time 416 | SetDHCPOpt32 (pkt, DHCP_LEASE_TIME, htonl (Adapter->m_dhcp_lease_time)); 417 | 418 | // Netmask 419 | SetDHCPOpt32 (pkt, DHCP_NETMASK, Adapter->m_dhcp_netmask); 420 | 421 | // Other user-defined options 422 | SetDHCPOpt ( 423 | pkt, 424 | Adapter->m_dhcp_user_supplied_options_buffer, 425 | Adapter->m_dhcp_user_supplied_options_buffer_len); 426 | } 427 | 428 | // End 429 | SetDHCPOpt0 (pkt, DHCP_END); 430 | 431 | if (!DHCPMSG_OVERFLOW (pkt)) 432 | { 433 | // The initial part of the DHCP message (not including options) gets built here 434 | BuildDHCPPre ( 435 | Adapter, 436 | &pkt->msg.pre, 437 | eth, 438 | ip, 439 | udp, 440 | dhcp, 441 | DHCPMSG_LEN_OPT (pkt), 442 | type); 443 | 444 | SetChecksumDHCPMsg (pkt); 445 | 446 | DUMP_PACKET ("DHCPMsg", 447 | DHCPMSG_BUF (pkt), 448 | DHCPMSG_LEN_FULL (pkt)); 449 | 450 | // Return DHCP response to kernel 451 | IndicateReceivePacket( 452 | Adapter, 453 | DHCPMSG_BUF (pkt), 454 | DHCPMSG_LEN_FULL (pkt) 455 | ); 456 | } 457 | else 458 | { 459 | DEBUGP (("[TAP] SendDHCPMsg: DHCP buffer overflow\n")); 460 | } 461 | 462 | MemFree (pkt, sizeof (DHCPMsg)); 463 | } 464 | } 465 | 466 | //=================================================================== 467 | // Handle a BOOTPS packet produced by the local system to 468 | // resolve the address/netmask of this adapter. 469 | // If we are in TAP_WIN_IOCTL_CONFIG_DHCP_MASQ mode, reply 470 | // to the message. Return TRUE if we processed the passed 471 | // message, so that downstream stages can ignore it. 472 | //=================================================================== 473 | 474 | BOOLEAN 475 | ProcessDHCP( 476 | __in PTAP_ADAPTER_CONTEXT Adapter, 477 | __in const ETH_HEADER *eth, 478 | __in const IPHDR *ip, 479 | __in const UDPHDR *udp, 480 | __in const DHCP *dhcp, 481 | __in int optlen 482 | ) 483 | { 484 | int msg_type; 485 | 486 | // Sanity check IP header 487 | if (!(ntohs (ip->tot_len) == sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen 488 | && (ntohs (ip->frag_off) & IP_OFFMASK) == 0)) 489 | { 490 | return TRUE; 491 | } 492 | 493 | // Does this message belong to us? 494 | if (!DHCPMessageOurs (Adapter, eth, ip, udp, dhcp)) 495 | { 496 | return FALSE; 497 | } 498 | 499 | msg_type = GetDHCPMessageType (dhcp, optlen); 500 | 501 | // Drop non-BOOTREQUEST messages 502 | if (dhcp->op != BOOTREQUEST) 503 | { 504 | return TRUE; 505 | } 506 | 507 | // Drop any messages except DHCPDISCOVER or DHCPREQUEST 508 | if (!(msg_type == DHCPDISCOVER || msg_type == DHCPREQUEST)) 509 | { 510 | return TRUE; 511 | } 512 | 513 | // Should we reply with DHCPOFFER, DHCPACK, or DHCPNAK? 514 | if (msg_type == DHCPREQUEST 515 | && ((dhcp->ciaddr && dhcp->ciaddr != Adapter->m_dhcp_addr) 516 | || !Adapter->m_dhcp_received_discover 517 | || Adapter->m_dhcp_bad_requests >= BAD_DHCPREQUEST_NAK_THRESHOLD)) 518 | { 519 | SendDHCPMsg( 520 | Adapter, 521 | DHCPNAK, 522 | eth, ip, udp, dhcp 523 | ); 524 | } 525 | else 526 | { 527 | SendDHCPMsg( 528 | Adapter, 529 | (msg_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK), 530 | eth, ip, udp, dhcp 531 | ); 532 | } 533 | 534 | // Remember if we received a DHCPDISCOVER 535 | if (msg_type == DHCPDISCOVER) 536 | { 537 | Adapter->m_dhcp_received_discover = TRUE; 538 | } 539 | 540 | // Is this a bad DHCPREQUEST? 541 | if (msg_type == DHCPREQUEST && dhcp->ciaddr && dhcp->ciaddr != Adapter->m_dhcp_addr) 542 | { 543 | ++Adapter->m_dhcp_bad_requests; 544 | } 545 | 546 | return TRUE; 547 | } 548 | 549 | #if DBG 550 | 551 | const char * 552 | message_op_text (int op) 553 | { 554 | switch (op) 555 | { 556 | case BOOTREQUEST: 557 | return "BOOTREQUEST"; 558 | 559 | case BOOTREPLY: 560 | return "BOOTREPLY"; 561 | 562 | default: 563 | return "???"; 564 | } 565 | } 566 | 567 | const char * 568 | message_type_text (int type) 569 | { 570 | switch (type) 571 | { 572 | case DHCPDISCOVER: 573 | return "DHCPDISCOVER"; 574 | 575 | case DHCPOFFER: 576 | return "DHCPOFFER"; 577 | 578 | case DHCPREQUEST: 579 | return "DHCPREQUEST"; 580 | 581 | case DHCPDECLINE: 582 | return "DHCPDECLINE"; 583 | 584 | case DHCPACK: 585 | return "DHCPACK"; 586 | 587 | case DHCPNAK: 588 | return "DHCPNAK"; 589 | 590 | case DHCPRELEASE: 591 | return "DHCPRELEASE"; 592 | 593 | case DHCPINFORM: 594 | return "DHCPINFORM"; 595 | 596 | default: 597 | return "???"; 598 | } 599 | } 600 | 601 | const char * 602 | port_name (int port) 603 | { 604 | switch (port) 605 | { 606 | case BOOTPS_PORT: 607 | return "BOOTPS"; 608 | 609 | case BOOTPC_PORT: 610 | return "BOOTPC"; 611 | 612 | default: 613 | return "unknown"; 614 | } 615 | } 616 | 617 | VOID 618 | DumpDHCP ( 619 | const ETH_HEADER *eth, 620 | const IPHDR *ip, 621 | const UDPHDR *udp, 622 | const DHCP *dhcp, 623 | const int optlen 624 | ) 625 | { 626 | DEBUGP ((" %s", message_op_text (dhcp->op))); 627 | DEBUGP ((" %s ", message_type_text (GetDHCPMessageType (dhcp, optlen)))); 628 | PrIP (ip->saddr); 629 | DEBUGP ((":%s[", port_name (ntohs (udp->source)))); 630 | PrMac (eth->src); 631 | DEBUGP (("] -> ")); 632 | PrIP (ip->daddr); 633 | DEBUGP ((":%s[", port_name (ntohs (udp->dest)))); 634 | PrMac (eth->dest); 635 | DEBUGP (("]")); 636 | if (dhcp->ciaddr) 637 | { 638 | DEBUGP ((" ci=")); 639 | PrIP (dhcp->ciaddr); 640 | } 641 | if (dhcp->yiaddr) 642 | { 643 | DEBUGP ((" yi=")); 644 | PrIP (dhcp->yiaddr); 645 | } 646 | if (dhcp->siaddr) 647 | { 648 | DEBUGP ((" si=")); 649 | PrIP (dhcp->siaddr); 650 | } 651 | if (dhcp->hlen == sizeof (MACADDR)) 652 | { 653 | DEBUGP ((" ch=")); 654 | PrMac (dhcp->chaddr); 655 | } 656 | 657 | DEBUGP ((" xid=0x%08x", ntohl (dhcp->xid))); 658 | 659 | if (ntohl (dhcp->magic) != 0x63825363) 660 | DEBUGP ((" ma=0x%08x", ntohl (dhcp->magic))); 661 | if (dhcp->htype != 1) 662 | DEBUGP ((" htype=%d", dhcp->htype)); 663 | if (dhcp->hops) 664 | DEBUGP ((" hops=%d", dhcp->hops)); 665 | if (ntohs (dhcp->secs)) 666 | DEBUGP ((" secs=%d", ntohs (dhcp->secs))); 667 | if (ntohs (dhcp->flags)) 668 | DEBUGP ((" flags=0x%04x", ntohs (dhcp->flags))); 669 | 670 | // extra stuff 671 | 672 | if (ip->version_len != 0x45) 673 | DEBUGP ((" vl=0x%02x", ip->version_len)); 674 | if (ntohs (ip->tot_len) != sizeof (IPHDR) + sizeof (UDPHDR) + sizeof (DHCP) + optlen) 675 | DEBUGP ((" tl=%d", ntohs (ip->tot_len))); 676 | if (ntohs (udp->len) != sizeof (UDPHDR) + sizeof (DHCP) + optlen) 677 | DEBUGP ((" ul=%d", ntohs (udp->len))); 678 | 679 | if (ip->tos) 680 | DEBUGP ((" tos=0x%02x", ip->tos)); 681 | if (ntohs (ip->id)) 682 | DEBUGP ((" id=0x%04x", ntohs (ip->id))); 683 | if (ntohs (ip->frag_off)) 684 | DEBUGP ((" frag_off=0x%04x", ntohs (ip->frag_off))); 685 | 686 | DEBUGP ((" ttl=%d", ip->ttl)); 687 | DEBUGP ((" ic=0x%04x [0x%04x]", ntohs (ip->check), 688 | ip_checksum ((UCHAR*)ip, sizeof (IPHDR)))); 689 | DEBUGP ((" uc=0x%04x [0x%04x/%d]", ntohs (udp->check), 690 | udp_checksum ((UCHAR *) udp, 691 | sizeof (UDPHDR) + sizeof (DHCP) + optlen, 692 | (UCHAR *) &ip->saddr, 693 | (UCHAR *) &ip->daddr), 694 | optlen)); 695 | 696 | // Options 697 | { 698 | const UCHAR *opt = (UCHAR *) (dhcp + 1); 699 | int i; 700 | 701 | DEBUGP ((" OPT")); 702 | for (i = 0; i < optlen; ++i) 703 | { 704 | const UCHAR data = opt[i]; 705 | DEBUGP ((".%d", data)); 706 | } 707 | } 708 | } 709 | 710 | #endif /* DBG */ 711 | -------------------------------------------------------------------------------- /src/dhcp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | #pragma once 25 | 26 | #pragma pack(1) 27 | 28 | //=================================================== 29 | // How many bad DHCPREQUESTs do we receive before we 30 | // return a NAK? 31 | // 32 | // A bad DHCPREQUEST is defined to be one where the 33 | // requestor doesn't know its IP address. 34 | //=================================================== 35 | 36 | #define BAD_DHCPREQUEST_NAK_THRESHOLD 3 37 | 38 | //============================================== 39 | // Maximum number of DHCP options bytes supplied 40 | //============================================== 41 | 42 | #define DHCP_USER_SUPPLIED_OPTIONS_BUFFER_SIZE 256 43 | #define DHCP_OPTIONS_BUFFER_SIZE 256 44 | 45 | //=================================== 46 | // UDP port numbers of DHCP messages. 47 | //=================================== 48 | 49 | #define BOOTPS_PORT 67 50 | #define BOOTPC_PORT 68 51 | 52 | //=========================== 53 | // The DHCP message structure 54 | //=========================== 55 | 56 | typedef struct { 57 | # define BOOTREQUEST 1 58 | # define BOOTREPLY 2 59 | UCHAR op; /* message op */ 60 | 61 | UCHAR htype; /* hardware address type (e.g. '1' = 10Mb Ethernet) */ 62 | UCHAR hlen; /* hardware address length (e.g. '6' for 10Mb Ethernet) */ 63 | UCHAR hops; /* client sets to 0, may be used by relay agents */ 64 | ULONG xid; /* transaction ID, chosen by client */ 65 | USHORT secs; /* seconds since request process began, set by client */ 66 | USHORT flags; 67 | ULONG ciaddr; /* client IP address, client sets if known */ 68 | ULONG yiaddr; /* 'your' IP address -- server's response to client */ 69 | ULONG siaddr; /* server IP address */ 70 | ULONG giaddr; /* relay agent IP address */ 71 | UCHAR chaddr[16]; /* client hardware address */ 72 | UCHAR sname[64]; /* optional server host name */ 73 | UCHAR file[128]; /* boot file name */ 74 | ULONG magic; /* must be 0x63825363 (network order) */ 75 | } DHCP; 76 | 77 | typedef struct { 78 | ETH_HEADER eth; 79 | IPHDR ip; 80 | UDPHDR udp; 81 | DHCP dhcp; 82 | } DHCPPre; 83 | 84 | typedef struct { 85 | DHCPPre pre; 86 | UCHAR options[DHCP_OPTIONS_BUFFER_SIZE]; 87 | } DHCPFull; 88 | 89 | typedef struct { 90 | unsigned int optlen; 91 | BOOLEAN overflow; 92 | DHCPFull msg; 93 | } DHCPMsg; 94 | 95 | //=================== 96 | // Macros for DHCPMSG 97 | //=================== 98 | 99 | #define DHCPMSG_LEN_BASE(p) (sizeof (DHCPPre)) 100 | #define DHCPMSG_LEN_OPT(p) ((p)->optlen) 101 | #define DHCPMSG_LEN_FULL(p) (DHCPMSG_LEN_BASE(p) + DHCPMSG_LEN_OPT(p)) 102 | #define DHCPMSG_BUF(p) ((UCHAR*) &(p)->msg) 103 | #define DHCPMSG_OVERFLOW(p) ((p)->overflow) 104 | 105 | //======================================== 106 | // structs to hold individual DHCP options 107 | //======================================== 108 | 109 | typedef struct { 110 | UCHAR type; 111 | } DHCPOPT0; 112 | 113 | typedef struct { 114 | UCHAR type; 115 | UCHAR len; 116 | UCHAR data; 117 | } DHCPOPT8; 118 | 119 | typedef struct { 120 | UCHAR type; 121 | UCHAR len; 122 | ULONG data; 123 | } DHCPOPT32; 124 | 125 | #pragma pack() 126 | 127 | //================== 128 | // DHCP Option types 129 | //================== 130 | 131 | #define DHCP_MSG_TYPE 53 /* message type (u8) */ 132 | #define DHCP_PARM_REQ 55 /* parameter request list: c1 (u8), ... */ 133 | #define DHCP_CLIENT_ID 61 /* client ID: type (u8), i1 (u8), ... */ 134 | #define DHCP_IP 50 /* requested IP addr (u32) */ 135 | #define DHCP_NETMASK 1 /* subnet mask (u32) */ 136 | #define DHCP_LEASE_TIME 51 /* lease time sec (u32) */ 137 | #define DHCP_RENEW_TIME 58 /* renewal time sec (u32) */ 138 | #define DHCP_REBIND_TIME 59 /* rebind time sec (u32) */ 139 | #define DHCP_SERVER_ID 54 /* server ID: IP addr (u32) */ 140 | #define DHCP_PAD 0 141 | #define DHCP_END 255 142 | 143 | //==================== 144 | // DHCP Messages types 145 | //==================== 146 | 147 | #define DHCPDISCOVER 1 148 | #define DHCPOFFER 2 149 | #define DHCPREQUEST 3 150 | #define DHCPDECLINE 4 151 | #define DHCPACK 5 152 | #define DHCPNAK 6 153 | #define DHCPRELEASE 7 154 | #define DHCPINFORM 8 155 | 156 | #if DBG 157 | 158 | VOID 159 | DumpDHCP (const ETH_HEADER *eth, 160 | const IPHDR *ip, 161 | const UDPHDR *udp, 162 | const DHCP *dhcp, 163 | const int optlen); 164 | 165 | #endif 166 | -------------------------------------------------------------------------------- /src/endian.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #ifdef TAP_LITTLE_ENDIAN 26 | #define ntohs(x) RtlUshortByteSwap(x) 27 | #define htons(x) RtlUshortByteSwap(x) 28 | #define ntohl(x) RtlUlongByteSwap(x) 29 | #define htonl(x) RtlUlongByteSwap(x) 30 | #else 31 | #define ntohs(x) ((USHORT)(x)) 32 | #define htons(x) ((USHORT)(x)) 33 | #define ntohl(x) ((ULONG)(x)) 34 | #define htonl(x) ((ULONG)(x)) 35 | #endif 36 | -------------------------------------------------------------------------------- /src/error.c: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #include "tap.h" 26 | 27 | //----------------- 28 | // DEBUGGING OUTPUT 29 | //----------------- 30 | 31 | const char *g_LastErrorFilename; 32 | int g_LastErrorLineNumber; 33 | 34 | #if DBG 35 | 36 | DebugOutput g_Debug; 37 | 38 | BOOLEAN 39 | NewlineExists (const char *str, int len) 40 | { 41 | while (len-- > 0) 42 | { 43 | const char c = *str++; 44 | if (c == '\n') 45 | return TRUE; 46 | else if (c == '\0') 47 | break; 48 | } 49 | return FALSE; 50 | } 51 | 52 | VOID 53 | MyDebugInit (unsigned int bufsiz) 54 | { 55 | NdisZeroMemory (&g_Debug, sizeof (g_Debug)); 56 | g_Debug.text = (char *) MemAlloc (bufsiz, FALSE); 57 | 58 | if (g_Debug.text) 59 | { 60 | g_Debug.capacity = bufsiz; 61 | } 62 | } 63 | 64 | VOID 65 | MyDebugFree () 66 | { 67 | if (g_Debug.text) 68 | { 69 | MemFree (g_Debug.text, g_Debug.capacity); 70 | } 71 | 72 | NdisZeroMemory (&g_Debug, sizeof (g_Debug)); 73 | } 74 | 75 | VOID 76 | MyDebugPrint (const unsigned char* format, ...) 77 | { 78 | if (g_Debug.text && g_Debug.capacity > 0 && CAN_WE_PRINT) 79 | { 80 | BOOLEAN owned; 81 | ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned); 82 | if (owned) 83 | { 84 | const int remaining = (int)g_Debug.capacity - (int)g_Debug.out; 85 | 86 | if (remaining > 0) 87 | { 88 | va_list args; 89 | NTSTATUS status; 90 | char *end; 91 | 92 | #ifdef DBG_PRINT 93 | va_start (args, format); 94 | vDbgPrintEx (DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, format, args); 95 | va_end (args); 96 | #endif 97 | va_start (args, format); 98 | status = RtlStringCchVPrintfExA (g_Debug.text + g_Debug.out, 99 | remaining, 100 | &end, 101 | NULL, 102 | STRSAFE_NO_TRUNCATION | STRSAFE_IGNORE_NULLS, 103 | format, 104 | args); 105 | va_end (args); 106 | va_start (args, format); 107 | vDbgPrintEx(DPFLTR_IHVDRIVER_ID , 1, format, args); 108 | va_end (args); 109 | if (status == STATUS_SUCCESS) 110 | g_Debug.out = (unsigned int) (end - g_Debug.text); 111 | else 112 | g_Debug.error = TRUE; 113 | } 114 | else 115 | g_Debug.error = TRUE; 116 | 117 | RELEASE_MUTEX (&g_Debug.lock); 118 | } 119 | else 120 | g_Debug.error = TRUE; 121 | } 122 | } 123 | 124 | BOOLEAN 125 | GetDebugLine ( 126 | __in char *buf, 127 | __in const int len 128 | ) 129 | { 130 | static const char *truncated = "[OUTPUT TRUNCATED]\n"; 131 | BOOLEAN ret = FALSE; 132 | 133 | NdisZeroMemory (buf, len); 134 | 135 | if (g_Debug.text && g_Debug.capacity > 0) 136 | { 137 | BOOLEAN owned; 138 | ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned); 139 | if (owned) 140 | { 141 | int i = 0; 142 | 143 | if (g_Debug.error || NewlineExists (g_Debug.text + g_Debug.in, (int)g_Debug.out - (int)g_Debug.in)) 144 | { 145 | while (i < (len - 1) && g_Debug.in < g_Debug.out) 146 | { 147 | const char c = g_Debug.text[g_Debug.in++]; 148 | if (c == '\n') 149 | break; 150 | buf[i++] = c; 151 | } 152 | if (i < len) 153 | buf[i] = '\0'; 154 | } 155 | 156 | if (!i) 157 | { 158 | if (g_Debug.in == g_Debug.out) 159 | { 160 | g_Debug.in = g_Debug.out = 0; 161 | if (g_Debug.error) 162 | { 163 | const unsigned int tlen = strlen (truncated); 164 | if (tlen < g_Debug.capacity) 165 | { 166 | NdisMoveMemory (g_Debug.text, truncated, tlen+1); 167 | g_Debug.out = tlen; 168 | } 169 | g_Debug.error = FALSE; 170 | } 171 | } 172 | } 173 | else 174 | ret = TRUE; 175 | 176 | RELEASE_MUTEX (&g_Debug.lock); 177 | } 178 | } 179 | return ret; 180 | } 181 | 182 | VOID 183 | PrMac (const MACADDR mac) 184 | { 185 | DEBUGP (("%x:%x:%x:%x:%x:%x", 186 | mac[0], mac[1], mac[2], 187 | mac[3], mac[4], mac[5])); 188 | } 189 | 190 | VOID 191 | PrIP (IPADDR ip_addr) 192 | { 193 | const unsigned char *ip = (const unsigned char *) &ip_addr; 194 | 195 | DEBUGP (("%d.%d.%d.%d", 196 | ip[0], ip[1], ip[2], ip[3])); 197 | } 198 | 199 | const char * 200 | PrIPProto (int proto) 201 | { 202 | switch (proto) 203 | { 204 | case IPPROTO_UDP: 205 | return "UDP"; 206 | 207 | case IPPROTO_TCP: 208 | return "TCP"; 209 | 210 | case IPPROTO_ICMP: 211 | return "ICMP"; 212 | 213 | case IPPROTO_IGMP: 214 | return "IGMP"; 215 | 216 | default: 217 | return "???"; 218 | } 219 | } 220 | 221 | VOID 222 | DumpARP (const char *prefix, const ARP_PACKET *arp) 223 | { 224 | DEBUGP (("%s ARP src=", prefix)); 225 | PrMac (arp->m_MAC_Source); 226 | DEBUGP ((" dest=")); 227 | PrMac (arp->m_MAC_Destination); 228 | DEBUGP ((" OP=0x%04x", 229 | (int)ntohs(arp->m_ARP_Operation))); 230 | DEBUGP ((" M=0x%04x(%d)", 231 | (int)ntohs(arp->m_MAC_AddressType), 232 | (int)arp->m_MAC_AddressSize)); 233 | DEBUGP ((" P=0x%04x(%d)", 234 | (int)ntohs(arp->m_PROTO_AddressType), 235 | (int)arp->m_PROTO_AddressSize)); 236 | 237 | DEBUGP ((" MacSrc=")); 238 | PrMac (arp->m_ARP_MAC_Source); 239 | DEBUGP ((" MacDest=")); 240 | PrMac (arp->m_ARP_MAC_Destination); 241 | 242 | DEBUGP ((" IPSrc=")); 243 | PrIP (arp->m_ARP_IP_Source); 244 | DEBUGP ((" IPDest=")); 245 | PrIP (arp->m_ARP_IP_Destination); 246 | 247 | DEBUGP (("\n")); 248 | } 249 | 250 | struct ethpayload 251 | { 252 | ETH_HEADER eth; 253 | UCHAR payload[DEFAULT_PACKET_LOOKAHEAD]; 254 | }; 255 | 256 | #ifdef ALLOW_PACKET_DUMP 257 | 258 | VOID 259 | DumpPacket2( 260 | __in const char *prefix, 261 | __in const ETH_HEADER *eth, 262 | __in const unsigned char *data, 263 | __in unsigned int len 264 | ) 265 | { 266 | struct ethpayload *ep = (struct ethpayload *) MemAlloc (sizeof (struct ethpayload), TRUE); 267 | if (ep) 268 | { 269 | if (len > DEFAULT_PACKET_LOOKAHEAD) 270 | len = DEFAULT_PACKET_LOOKAHEAD; 271 | ep->eth = *eth; 272 | NdisMoveMemory (ep->payload, data, len); 273 | DumpPacket (prefix, (unsigned char *) ep, sizeof (ETH_HEADER) + len); 274 | MemFree (ep, sizeof (struct ethpayload)); 275 | } 276 | } 277 | 278 | VOID 279 | DumpPacket( 280 | __in const char *prefix, 281 | __in const unsigned char *data, 282 | __in unsigned int len 283 | ) 284 | { 285 | const ETH_HEADER *eth = (const ETH_HEADER *) data; 286 | const IPHDR *ip = (const IPHDR *) (data + sizeof (ETH_HEADER)); 287 | 288 | if (len < sizeof (ETH_HEADER)) 289 | { 290 | DEBUGP (("%s TRUNCATED PACKET LEN=%d\n", prefix, len)); 291 | return; 292 | } 293 | 294 | // ARP Packet? 295 | if (len >= sizeof (ARP_PACKET) && eth->proto == htons (ETH_P_ARP)) 296 | { 297 | DumpARP (prefix, (const ARP_PACKET *) data); 298 | return; 299 | } 300 | 301 | // IPv4 packet? 302 | if (len >= (sizeof (IPHDR) + sizeof (ETH_HEADER)) 303 | && eth->proto == htons (ETH_P_IP) 304 | && IPH_GET_VER (ip->version_len) == 4) 305 | { 306 | const int hlen = IPH_GET_LEN (ip->version_len); 307 | const int blen = len - sizeof (ETH_HEADER); 308 | BOOLEAN did = FALSE; 309 | 310 | DEBUGP (("%s IPv4 %s[%d]", prefix, PrIPProto (ip->protocol), len)); 311 | 312 | if (!(ntohs (ip->tot_len) == blen && hlen <= blen)) 313 | { 314 | DEBUGP ((" XXX")); 315 | return; 316 | } 317 | 318 | // TCP packet? 319 | if (ip->protocol == IPPROTO_TCP 320 | && blen - hlen >= (sizeof (TCPHDR))) 321 | { 322 | const TCPHDR *tcp = (TCPHDR *) (data + sizeof (ETH_HEADER) + hlen); 323 | DEBUGP ((" ")); 324 | PrIP (ip->saddr); 325 | DEBUGP ((":%d", ntohs (tcp->source))); 326 | DEBUGP ((" -> ")); 327 | PrIP (ip->daddr); 328 | DEBUGP ((":%d", ntohs (tcp->dest))); 329 | did = TRUE; 330 | } 331 | 332 | // UDP packet? 333 | else if ((ntohs (ip->frag_off) & IP_OFFMASK) == 0 334 | && ip->protocol == IPPROTO_UDP 335 | && blen - hlen >= (sizeof (UDPHDR))) 336 | { 337 | const UDPHDR *udp = (UDPHDR *) (data + sizeof (ETH_HEADER) + hlen); 338 | 339 | // DHCP packet? 340 | if ((udp->dest == htons (BOOTPC_PORT) || udp->dest == htons (BOOTPS_PORT)) 341 | && blen - hlen >= (sizeof (UDPHDR) + sizeof (DHCP))) 342 | { 343 | const DHCP *dhcp = (DHCP *) (data 344 | + hlen 345 | + sizeof (ETH_HEADER) 346 | + sizeof (UDPHDR)); 347 | 348 | int optlen = len 349 | - sizeof (ETH_HEADER) 350 | - hlen 351 | - sizeof (UDPHDR) 352 | - sizeof (DHCP); 353 | 354 | if (optlen < 0) 355 | optlen = 0; 356 | 357 | DumpDHCP (eth, ip, udp, dhcp, optlen); 358 | did = TRUE; 359 | } 360 | 361 | if (!did) 362 | { 363 | DEBUGP ((" ")); 364 | PrIP (ip->saddr); 365 | DEBUGP ((":%d", ntohs (udp->source))); 366 | DEBUGP ((" -> ")); 367 | PrIP (ip->daddr); 368 | DEBUGP ((":%d", ntohs (udp->dest))); 369 | did = TRUE; 370 | } 371 | } 372 | 373 | if (!did) 374 | { 375 | DEBUGP ((" ipproto=%d ", ip->protocol)); 376 | PrIP (ip->saddr); 377 | DEBUGP ((" -> ")); 378 | PrIP (ip->daddr); 379 | } 380 | 381 | DEBUGP (("\n")); 382 | return; 383 | } 384 | 385 | { 386 | DEBUGP (("%s ??? src=", prefix)); 387 | PrMac (eth->src); 388 | DEBUGP ((" dest=")); 389 | PrMac (eth->dest); 390 | DEBUGP ((" proto=0x%04x len=%d\n", 391 | (int) ntohs(eth->proto), 392 | len)); 393 | } 394 | } 395 | 396 | #endif // ALLOW_PACKET_DUMP 397 | 398 | #endif 399 | -------------------------------------------------------------------------------- /src/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | //----------------- 26 | // DEBUGGING OUTPUT 27 | //----------------- 28 | 29 | extern const char *g_LastErrorFilename; 30 | extern int g_LastErrorLineNumber; 31 | 32 | // Debug info output 33 | #define ALSO_DBGPRINT 1 34 | #define DEBUGP_AT_DISPATCH 1 35 | 36 | // Uncomment line below to allow packet dumps 37 | //#define ALLOW_PACKET_DUMP 1 38 | 39 | #define NOTE_ERROR() \ 40 | { \ 41 | g_LastErrorFilename = __FILE__; \ 42 | g_LastErrorLineNumber = __LINE__; \ 43 | } 44 | 45 | #if DBG 46 | 47 | typedef struct 48 | { 49 | unsigned int in; 50 | unsigned int out; 51 | unsigned int capacity; 52 | char *text; 53 | BOOLEAN error; 54 | MUTEX lock; 55 | } DebugOutput; 56 | 57 | VOID MyDebugPrint (const unsigned char* format, ...); 58 | 59 | VOID PrMac (const MACADDR mac); 60 | 61 | VOID PrIP (IPADDR ip_addr); 62 | 63 | #ifdef ALLOW_PACKET_DUMP 64 | 65 | VOID 66 | DumpPacket( 67 | __in const char *prefix, 68 | __in const unsigned char *data, 69 | __in unsigned int len 70 | ); 71 | 72 | DumpPacket2( 73 | __in const char *prefix, 74 | __in const ETH_HEADER *eth, 75 | __in const unsigned char *data, 76 | __in unsigned int len 77 | ); 78 | 79 | #else 80 | #define DUMP_PACKET(prefix, data, len) 81 | #define DUMP_PACKET2(prefix, eth, data, len) 82 | #endif 83 | 84 | #define CAN_WE_PRINT (DEBUGP_AT_DISPATCH || KeGetCurrentIrql () < DISPATCH_LEVEL) 85 | 86 | #if ALSO_DBGPRINT 87 | #define DEBUGP(fmt) { MyDebugPrint fmt; if (CAN_WE_PRINT) DbgPrint fmt; } 88 | #else 89 | #define DEBUGP(fmt) { MyDebugPrint fmt; } 90 | #endif 91 | 92 | #ifdef ALLOW_PACKET_DUMP 93 | 94 | #define DUMP_PACKET(prefix, data, len) \ 95 | DumpPacket (prefix, data, len) 96 | 97 | #define DUMP_PACKET2(prefix, eth, data, len) \ 98 | DumpPacket2 (prefix, eth, data, len) 99 | 100 | #endif 101 | 102 | BOOLEAN 103 | GetDebugLine ( 104 | __in char *buf, 105 | __in const int len 106 | ); 107 | 108 | #else 109 | 110 | #define DEBUGP(fmt) 111 | #define DUMP_PACKET(prefix, data, len) 112 | #define DUMP_PACKET2(prefix, eth, data, len) 113 | 114 | #endif 115 | -------------------------------------------------------------------------------- /src/hexdump.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #ifndef HEXDUMP_DEFINED 26 | #define HEXDUMP_DEFINED 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | //===================================================================================== 33 | // Debug Routines 34 | //===================================================================================== 35 | 36 | #ifndef NDIS_MINIPORT_DRIVER 37 | # include 38 | # include 39 | # include 40 | # include 41 | # include 42 | 43 | # ifndef DEBUGP 44 | # define DEBUGP(fmt) { DbgMessage fmt; } 45 | # endif 46 | 47 | extern VOID (*DbgMessage)(char *p_Format, ...); 48 | 49 | VOID DisplayDebugString (char *p_Format, ...); 50 | #endif 51 | 52 | //=================================================================================== 53 | // Reporting / Debugging 54 | //=================================================================================== 55 | #define IfPrint(c) (c >= 32 && c < 127 ? c : '.') 56 | 57 | VOID HexDump (unsigned char *p_Buffer, unsigned long p_Size); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/lock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | typedef struct 26 | { 27 | volatile long count; 28 | } MUTEX; 29 | 30 | #define MUTEX_SLEEP_TIME 10000 // microseconds 31 | 32 | #define INIT_MUTEX(m) { (m)->count = 0; } 33 | 34 | #define ACQUIRE_MUTEX_BLOCKING(m) \ 35 | { \ 36 | while (NdisInterlockedIncrement (&((m)->count)) != 1) \ 37 | { \ 38 | NdisInterlockedDecrement(&((m)->count)); \ 39 | NdisMSleep(MUTEX_SLEEP_TIME); \ 40 | } \ 41 | } 42 | 43 | #define RELEASE_MUTEX(m) \ 44 | { \ 45 | NdisInterlockedDecrement(&((m)->count)); \ 46 | } 47 | 48 | #define ACQUIRE_MUTEX_NONBLOCKING(m, result) \ 49 | { \ 50 | if (NdisInterlockedIncrement (&((m)->count)) != 1) \ 51 | { \ 52 | NdisInterlockedDecrement(&((m)->count)); \ 53 | result = FALSE; \ 54 | } \ 55 | else \ 56 | { \ 57 | result = TRUE; \ 58 | } \ 59 | } 60 | 61 | #define ACQUIRE_MUTEX_ADAPTIVE(m, result) \ 62 | { \ 63 | result = TRUE; \ 64 | while (NdisInterlockedIncrement (&((m)->count)) != 1) \ 65 | { \ 66 | NdisInterlockedDecrement(&((m)->count)); \ 67 | if (KeGetCurrentIrql () < DISPATCH_LEVEL) \ 68 | NdisMSleep(MUTEX_SLEEP_TIME); \ 69 | else \ 70 | { \ 71 | result = FALSE; \ 72 | break; \ 73 | } \ 74 | } \ 75 | } 76 | -------------------------------------------------------------------------------- /src/macinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | 26 | #include "tap.h" 27 | 28 | int 29 | HexStringToDecimalInt (const int p_Character) 30 | { 31 | int l_Value = 0; 32 | 33 | if (p_Character >= 'A' && p_Character <= 'F') 34 | l_Value = (p_Character - 'A') + 10; 35 | else if (p_Character >= 'a' && p_Character <= 'f') 36 | l_Value = (p_Character - 'a') + 10; 37 | else if (p_Character >= '0' && p_Character <= '9') 38 | l_Value = p_Character - '0'; 39 | 40 | return l_Value; 41 | } 42 | 43 | BOOLEAN 44 | ParseMAC (MACADDR dest, const char *src) 45 | { 46 | int c; 47 | int mac_index = 0; 48 | BOOLEAN high_digit = FALSE; 49 | int delim_action = 1; 50 | 51 | ASSERT (src); 52 | ASSERT (dest); 53 | 54 | CLEAR_MAC (dest); 55 | 56 | while (c = *src++) 57 | { 58 | if (IsMacDelimiter (c)) 59 | { 60 | mac_index += delim_action; 61 | high_digit = FALSE; 62 | delim_action = 1; 63 | } 64 | else if (IsHexDigit (c)) 65 | { 66 | const int digit = HexStringToDecimalInt (c); 67 | if (mac_index < sizeof (MACADDR)) 68 | { 69 | if (!high_digit) 70 | { 71 | dest[mac_index] = (char)(digit); 72 | high_digit = TRUE; 73 | delim_action = 1; 74 | } 75 | else 76 | { 77 | dest[mac_index] = (char)(dest[mac_index] * 16 + digit); 78 | ++mac_index; 79 | high_digit = FALSE; 80 | delim_action = 0; 81 | } 82 | } 83 | else 84 | return FALSE; 85 | } 86 | else 87 | return FALSE; 88 | } 89 | 90 | return (mac_index + delim_action) >= sizeof (MACADDR); 91 | } 92 | 93 | /* 94 | * Generate a MAC using the GUID in the adapter name. 95 | * 96 | * The mac is constructed as 00:FF:xx:xx:xx:xx where 97 | * the Xs are taken from the first 32 bits of the GUID in the 98 | * adapter name. This is similar to the Linux 2.4 tap MAC 99 | * generator, except linux uses 32 random bits for the Xs. 100 | * 101 | * In general, this solution is reasonable for most 102 | * applications except for very large bridged TAP networks, 103 | * where the probability of address collisions becomes more 104 | * than infintesimal. 105 | * 106 | * Using the well-known "birthday paradox", on a 1000 node 107 | * network the probability of collision would be 108 | * 0.000116292153. On a 10,000 node network, the probability 109 | * of collision would be 0.01157288998621678766. 110 | */ 111 | 112 | VOID 113 | GenerateRandomMac( 114 | __in MACADDR mac, 115 | __in const unsigned char *adapter_name 116 | ) 117 | { 118 | unsigned const char *cp = adapter_name; 119 | unsigned char c; 120 | unsigned int i = 2; 121 | unsigned int byte = 0; 122 | int brace = 0; 123 | int state = 0; 124 | 125 | CLEAR_MAC (mac); 126 | 127 | mac[0] = 0x00; 128 | mac[1] = 0xFF; 129 | 130 | while (c = *cp++) 131 | { 132 | if (i >= sizeof (MACADDR)) 133 | break; 134 | if (c == '{') 135 | brace = 1; 136 | if (IsHexDigit (c) && brace) 137 | { 138 | const unsigned int digit = HexStringToDecimalInt (c); 139 | if (state) 140 | { 141 | byte <<= 4; 142 | byte |= digit; 143 | mac[i++] = (unsigned char) byte; 144 | state = 0; 145 | } 146 | else 147 | { 148 | byte = digit; 149 | state = 1; 150 | } 151 | } 152 | } 153 | } 154 | 155 | VOID 156 | GenerateRelatedMAC( 157 | __out MACADDR dest, 158 | __in const MACADDR src, 159 | __in const int delta 160 | ) 161 | { 162 | ETH_COPY_NETWORK_ADDRESS (dest, src); 163 | dest[2] += (UCHAR) delta; 164 | } 165 | -------------------------------------------------------------------------------- /src/macinfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #ifndef MacInfoDefined 26 | #define MacInfoDefined 27 | 28 | //=================================================================================== 29 | // Macros 30 | //=================================================================================== 31 | #define IsMacDelimiter(a) (a == ':' || a == '-' || a == '.') 32 | #define IsHexDigit(c) ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) 33 | 34 | #define CLEAR_MAC(dest) NdisZeroMemory ((dest), sizeof (MACADDR)) 35 | #define MAC_EQUAL(a,b) (memcmp ((a), (b), sizeof (MACADDR)) == 0) 36 | 37 | BOOLEAN 38 | ParseMAC (MACADDR dest, const char *src); 39 | 40 | VOID 41 | GenerateRandomMac( 42 | __in MACADDR mac, 43 | __in const unsigned char *adapter_name 44 | ); 45 | 46 | VOID 47 | GenerateRelatedMAC( 48 | __out MACADDR dest, 49 | __in const MACADDR src, 50 | __in const int delta 51 | ); 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/mem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | //------------------ 26 | // Memory Management 27 | //------------------ 28 | 29 | #include "tap.h" 30 | 31 | PVOID 32 | MemAlloc( 33 | __in ULONG p_Size, 34 | __in BOOLEAN zero 35 | ) 36 | { 37 | PVOID l_Return = NULL; 38 | 39 | if (p_Size) 40 | { 41 | __try 42 | { 43 | if (NdisAllocateMemoryWithTag (&l_Return, p_Size, 'APAT') 44 | == NDIS_STATUS_SUCCESS) 45 | { 46 | if (zero) 47 | { 48 | NdisZeroMemory (l_Return, p_Size); 49 | } 50 | } 51 | else 52 | { 53 | l_Return = NULL; 54 | } 55 | } 56 | __except (EXCEPTION_EXECUTE_HANDLER) 57 | { 58 | l_Return = NULL; 59 | } 60 | } 61 | 62 | return l_Return; 63 | } 64 | 65 | VOID 66 | MemFree( 67 | __in PVOID p_Addr, 68 | __in ULONG p_Size 69 | ) 70 | { 71 | if (p_Addr && p_Size) 72 | { 73 | __try 74 | { 75 | #if DBG 76 | NdisZeroMemory (p_Addr, p_Size); 77 | #endif 78 | NdisFreeMemory (p_Addr, p_Size, 0); 79 | } 80 | __except (EXCEPTION_EXECUTE_HANDLER) 81 | { 82 | } 83 | } 84 | } 85 | 86 | //====================================================================== 87 | // TAP Packet Queue Support 88 | //====================================================================== 89 | 90 | VOID 91 | tapPacketQueueInsertTail( 92 | __in PTAP_PACKET_QUEUE TapPacketQueue, 93 | __in PTAP_PACKET TapPacket 94 | ) 95 | { 96 | KIRQL irql; 97 | 98 | KeAcquireSpinLock(&TapPacketQueue->QueueLock,&irql); 99 | 100 | InsertTailList(&TapPacketQueue->Queue,&TapPacket->QueueLink); 101 | 102 | // BUGBUG!!! Enforce PACKET_QUEUE_SIZE queue count limit??? 103 | // For NDIS 6 there is no per-packet status, so this will need to 104 | // be handled on per-NBL basis in AdapterSendNetBufferLists... 105 | 106 | // Update counts 107 | ++TapPacketQueue->Count; 108 | TapPacketQueue->TotalBytes += (TapPacket->m_SizeFlags & TP_SIZE_MASK); 109 | 110 | 111 | if(TapPacketQueue->Count > TapPacketQueue->MaxCount) 112 | { 113 | TapPacketQueue->MaxCount = TapPacketQueue->Count; 114 | 115 | DEBUGP (("[TAP] tapPacketQueueInsertTail: New MAX queued packet count = %d\n", 116 | TapPacketQueue->MaxCount)); 117 | } 118 | 119 | KeReleaseSpinLock(&TapPacketQueue->QueueLock,irql); 120 | } 121 | 122 | // Call with QueueLock held 123 | PTAP_PACKET 124 | tapPacketRemoveHeadLocked( 125 | __in PTAP_PACKET_QUEUE TapPacketQueue 126 | ) 127 | { 128 | PTAP_PACKET tapPacket = NULL; 129 | PLIST_ENTRY listEntry; 130 | 131 | listEntry = RemoveHeadList(&TapPacketQueue->Queue); 132 | 133 | if(listEntry != &TapPacketQueue->Queue) 134 | { 135 | tapPacket = CONTAINING_RECORD(listEntry, TAP_PACKET, QueueLink); 136 | 137 | // Update counts 138 | --TapPacketQueue->Count; 139 | TapPacketQueue->TotalBytes -= (tapPacket->m_SizeFlags & TP_SIZE_MASK); 140 | } 141 | 142 | return tapPacket; 143 | } 144 | 145 | VOID 146 | tapPacketQueueInitialize( 147 | __in PTAP_PACKET_QUEUE TapPacketQueue 148 | ) 149 | { 150 | KeInitializeSpinLock(&TapPacketQueue->QueueLock); 151 | 152 | NdisInitializeListHead(&TapPacketQueue->Queue); 153 | } 154 | 155 | //====================================================================== 156 | // TAP Cancel-Safe Queue Support 157 | //====================================================================== 158 | 159 | VOID 160 | tapIrpCsqInsert ( 161 | __in struct _IO_CSQ *Csq, 162 | __in PIRP Irp 163 | ) 164 | { 165 | PTAP_IRP_CSQ tapIrpCsq; 166 | 167 | tapIrpCsq = (PTAP_IRP_CSQ )Csq; 168 | 169 | InsertTailList( 170 | &tapIrpCsq->Queue, 171 | &Irp->Tail.Overlay.ListEntry 172 | ); 173 | 174 | // Update counts 175 | ++tapIrpCsq->Count; 176 | 177 | if(tapIrpCsq->Count > tapIrpCsq->MaxCount) 178 | { 179 | tapIrpCsq->MaxCount = tapIrpCsq->Count; 180 | 181 | DEBUGP (("[TAP] tapIrpCsqInsert: New MAX queued IRP count = %d\n", 182 | tapIrpCsq->MaxCount)); 183 | } 184 | } 185 | 186 | VOID 187 | tapIrpCsqRemoveIrp( 188 | __in PIO_CSQ Csq, 189 | __in PIRP Irp 190 | ) 191 | { 192 | PTAP_IRP_CSQ tapIrpCsq; 193 | 194 | tapIrpCsq = (PTAP_IRP_CSQ )Csq; 195 | 196 | // Update counts 197 | --tapIrpCsq->Count; 198 | 199 | RemoveEntryList(&Irp->Tail.Overlay.ListEntry); 200 | } 201 | 202 | 203 | PIRP 204 | tapIrpCsqPeekNextIrp( 205 | __in PIO_CSQ Csq, 206 | __in PIRP Irp, 207 | __in PVOID PeekContext 208 | ) 209 | { 210 | PTAP_IRP_CSQ tapIrpCsq; 211 | PIRP nextIrp = NULL; 212 | PLIST_ENTRY nextEntry; 213 | PLIST_ENTRY listHead; 214 | PIO_STACK_LOCATION irpStack; 215 | 216 | tapIrpCsq = (PTAP_IRP_CSQ )Csq; 217 | 218 | listHead = &tapIrpCsq->Queue; 219 | 220 | // 221 | // If the IRP is NULL, we will start peeking from the listhead, else 222 | // we will start from that IRP onwards. This is done under the 223 | // assumption that new IRPs are always inserted at the tail. 224 | // 225 | 226 | if (Irp == NULL) 227 | { 228 | nextEntry = listHead->Flink; 229 | } 230 | else 231 | { 232 | nextEntry = Irp->Tail.Overlay.ListEntry.Flink; 233 | } 234 | 235 | while(nextEntry != listHead) 236 | { 237 | nextIrp = CONTAINING_RECORD(nextEntry, IRP, Tail.Overlay.ListEntry); 238 | 239 | irpStack = IoGetCurrentIrpStackLocation(nextIrp); 240 | 241 | // 242 | // If context is present, continue until you find a matching one. 243 | // Else you break out as you got next one. 244 | // 245 | if (PeekContext) 246 | { 247 | if (irpStack->FileObject == (PFILE_OBJECT) PeekContext) 248 | { 249 | break; 250 | } 251 | } 252 | else 253 | { 254 | break; 255 | } 256 | 257 | nextIrp = NULL; 258 | nextEntry = nextEntry->Flink; 259 | } 260 | 261 | return nextIrp; 262 | } 263 | 264 | // 265 | // tapIrpCsqAcquireQueueLock modifies the execution level of the current processor. 266 | // 267 | // KeAcquireSpinLock raises the execution level to Dispatch Level and stores 268 | // the current execution level in the Irql parameter to be restored at a later 269 | // time. KeAcqurieSpinLock also requires us to be running at no higher than 270 | // Dispatch level when it is called. 271 | // 272 | // The annotations reflect these changes and requirments. 273 | // 274 | 275 | _Requires_lock_not_held_(((PTAP_IRP_CSQ )Csq)->QueueLock) 276 | _Acquires_lock_(((PTAP_IRP_CSQ )Csq)->QueueLock) 277 | _IRQL_requires_max_(DISPATCH_LEVEL) 278 | _IRQL_saves_global_(SpinLock, Csq) 279 | _IRQL_raises_(DISPATCH_LEVEL) 280 | VOID 281 | tapIrpCsqAcquireQueueLock( 282 | __in PIO_CSQ Csq, 283 | __out PKIRQL Irql 284 | ) 285 | { 286 | PTAP_IRP_CSQ tapIrpCsq; 287 | 288 | tapIrpCsq = (PTAP_IRP_CSQ )Csq; 289 | 290 | // 291 | // Suppressing because the address below csq is valid since it's 292 | // part of TAP_ADAPTER_CONTEXT structure. 293 | // 294 | #pragma prefast(suppress: __WARNING_BUFFER_UNDERFLOW, "Underflow using expression 'adapter->PendingReadCsqQueueLock'") 295 | KeAcquireSpinLock(&tapIrpCsq->QueueLock, Irql); 296 | } 297 | 298 | // 299 | // tapIrpCsqReleaseQueueLock modifies the execution level of the current processor. 300 | // 301 | // KeReleaseSpinLock assumes we already hold the spin lock and are therefore 302 | // running at Dispatch level. It will use the Irql parameter saved in a 303 | // previous call to KeAcquireSpinLock to return the thread back to it's original 304 | // execution level. 305 | // 306 | // The annotations reflect these changes and requirments. 307 | // 308 | 309 | _Releases_lock_(((PTAP_IRP_CSQ )Csq)->QueueLock) 310 | _Requires_lock_held_(((PTAP_IRP_CSQ )Csq)->QueueLock) 311 | _IRQL_requires_(DISPATCH_LEVEL) 312 | _IRQL_restores_global_(SpinLock, Csq) 313 | VOID 314 | tapIrpCsqReleaseQueueLock( 315 | __in PIO_CSQ Csq, 316 | __in KIRQL Irql 317 | ) 318 | { 319 | PTAP_IRP_CSQ tapIrpCsq; 320 | 321 | tapIrpCsq = (PTAP_IRP_CSQ )Csq; 322 | 323 | // 324 | // Suppressing because the address below csq is valid since it's 325 | // part of TAP_ADAPTER_CONTEXT structure. 326 | // 327 | #pragma prefast(suppress: __WARNING_BUFFER_UNDERFLOW, "Underflow using expression 'adapter->PendingReadCsqQueueLock'") 328 | KeReleaseSpinLock(&tapIrpCsq->QueueLock, Irql); 329 | } 330 | 331 | VOID 332 | tapIrpCsqCompleteCanceledIrp( 333 | __in PIO_CSQ pCsq, 334 | __in PIRP Irp 335 | ) 336 | { 337 | UNREFERENCED_PARAMETER(pCsq); 338 | 339 | Irp->IoStatus.Status = STATUS_CANCELLED; 340 | Irp->IoStatus.Information = 0; 341 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 342 | } 343 | 344 | VOID 345 | tapIrpCsqInitialize( 346 | __in PTAP_IRP_CSQ TapIrpCsq 347 | ) 348 | { 349 | KeInitializeSpinLock(&TapIrpCsq->QueueLock); 350 | 351 | NdisInitializeListHead(&TapIrpCsq->Queue); 352 | 353 | IoCsqInitialize( 354 | &TapIrpCsq->CsqQueue, 355 | tapIrpCsqInsert, 356 | tapIrpCsqRemoveIrp, 357 | tapIrpCsqPeekNextIrp, 358 | tapIrpCsqAcquireQueueLock, 359 | tapIrpCsqReleaseQueueLock, 360 | tapIrpCsqCompleteCanceledIrp 361 | ); 362 | } 363 | 364 | VOID 365 | tapIrpCsqFlush( 366 | __in PTAP_IRP_CSQ TapIrpCsq 367 | ) 368 | { 369 | PIRP pendingIrp; 370 | 371 | // 372 | // Flush the pending read IRP queue. 373 | // 374 | pendingIrp = IoCsqRemoveNextIrp( 375 | &TapIrpCsq->CsqQueue, 376 | NULL 377 | ); 378 | 379 | while(pendingIrp) 380 | { 381 | // Cancel the IRP 382 | pendingIrp->IoStatus.Information = 0; 383 | pendingIrp->IoStatus.Status = STATUS_CANCELLED; 384 | IoCompleteRequest(pendingIrp, IO_NO_INCREMENT); 385 | 386 | pendingIrp = IoCsqRemoveNextIrp( 387 | &TapIrpCsq->CsqQueue, 388 | NULL 389 | ); 390 | } 391 | 392 | ASSERT(IsListEmpty(&TapIrpCsq->Queue)); 393 | } 394 | -------------------------------------------------------------------------------- /src/mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | //------------------ 26 | // Memory Management 27 | //------------------ 28 | 29 | PVOID 30 | MemAlloc( 31 | __in ULONG p_Size, 32 | __in BOOLEAN zero 33 | ); 34 | 35 | VOID 36 | MemFree( 37 | __in PVOID p_Addr, 38 | __in ULONG p_Size 39 | ); 40 | 41 | //====================================================================== 42 | // TAP Packet Queue 43 | //====================================================================== 44 | 45 | typedef 46 | struct _TAP_PACKET 47 | { 48 | LIST_ENTRY QueueLink; 49 | 50 | # define TAP_PACKET_SIZE(data_size) (sizeof (TAP_PACKET) + (data_size)) 51 | # define TP_TUN 0x80000000 52 | # define TP_SIZE_MASK (~TP_TUN) 53 | ULONG m_SizeFlags; 54 | 55 | // m_Data must be the last struct member 56 | UCHAR m_Data []; 57 | } TAP_PACKET, *PTAP_PACKET; 58 | 59 | #define TAP_PACKET_TAG '6PAT' // "TAP6" 60 | 61 | typedef struct _TAP_PACKET_QUEUE 62 | { 63 | KSPIN_LOCK QueueLock; 64 | LIST_ENTRY Queue; 65 | ULONG Count; // Count of currently queued items 66 | ULONG TotalBytes; // Total length of queued packets 67 | ULONG MaxCount; 68 | } TAP_PACKET_QUEUE, *PTAP_PACKET_QUEUE; 69 | 70 | VOID 71 | tapPacketQueueInsertTail( 72 | __in PTAP_PACKET_QUEUE TapPacketQueue, 73 | __in PTAP_PACKET TapPacket 74 | ); 75 | 76 | 77 | // Call with QueueLock held 78 | PTAP_PACKET 79 | tapPacketRemoveHeadLocked( 80 | __in PTAP_PACKET_QUEUE TapPacketQueue 81 | ); 82 | 83 | VOID 84 | tapPacketQueueInitialize( 85 | __in PTAP_PACKET_QUEUE TapPacketQueue 86 | ); 87 | 88 | //---------------------- 89 | // Cancel-Safe IRP Queue 90 | //---------------------- 91 | 92 | typedef struct _TAP_IRP_CSQ 93 | { 94 | IO_CSQ CsqQueue; 95 | KSPIN_LOCK QueueLock; 96 | LIST_ENTRY Queue; 97 | ULONG Count; // Count of currently queued items 98 | ULONG MaxCount; 99 | } TAP_IRP_CSQ, *PTAP_IRP_CSQ; 100 | 101 | VOID 102 | tapIrpCsqInitialize( 103 | __in PTAP_IRP_CSQ TapIrpCsq 104 | ); 105 | 106 | VOID 107 | tapIrpCsqFlush( 108 | __in PTAP_IRP_CSQ TapIrpCsq 109 | ); 110 | -------------------------------------------------------------------------------- /src/proto.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | //============================================================ 26 | // MAC address, Ethernet header, and ARP 27 | //============================================================ 28 | 29 | #pragma pack(1) 30 | 31 | #define IP_HEADER_SIZE 20 32 | #define IPV6_HEADER_SIZE 40 33 | 34 | #define MACADDR_SIZE 6 35 | typedef unsigned char MACADDR[MACADDR_SIZE]; 36 | 37 | typedef unsigned long IPADDR; 38 | typedef unsigned char IPV6ADDR[16]; 39 | 40 | //----------------- 41 | // Ethernet address 42 | //----------------- 43 | 44 | typedef struct { 45 | MACADDR addr; 46 | } ETH_ADDR; 47 | 48 | typedef struct { 49 | ETH_ADDR list[TAP_MAX_MCAST_LIST]; 50 | } MC_LIST; 51 | 52 | 53 | // BUGBUG!!! Consider using ststem defines in netiodef.h!!! 54 | 55 | //---------------- 56 | // Ethernet header 57 | //---------------- 58 | typedef struct 59 | { 60 | MACADDR dest; /* destination eth addr */ 61 | MACADDR src; /* source ether addr */ 62 | USHORT proto; /* packet type ID field */ 63 | } ETH_HEADER, *PETH_HEADER; 64 | 65 | //---------------- 66 | // ARP packet 67 | //---------------- 68 | 69 | typedef struct 70 | { 71 | MACADDR m_MAC_Destination; // Reverse these two 72 | MACADDR m_MAC_Source; // to answer ARP requests 73 | USHORT m_Proto; // 0x0806 74 | 75 | # define MAC_ADDR_TYPE 0x0001 76 | USHORT m_MAC_AddressType; // 0x0001 77 | 78 | USHORT m_PROTO_AddressType; // 0x0800 79 | UCHAR m_MAC_AddressSize; // 0x06 80 | UCHAR m_PROTO_AddressSize; // 0x04 81 | 82 | # define ARP_REQUEST 0x0001 83 | # define ARP_REPLY 0x0002 84 | USHORT m_ARP_Operation; // 0x0001 for ARP request, 0x0002 for ARP reply 85 | 86 | MACADDR m_ARP_MAC_Source; 87 | IPADDR m_ARP_IP_Source; 88 | MACADDR m_ARP_MAC_Destination; 89 | IPADDR m_ARP_IP_Destination; 90 | } 91 | ARP_PACKET, *PARP_PACKET; 92 | 93 | //---------- 94 | // IP Header 95 | //---------- 96 | 97 | typedef struct { 98 | # define IPH_GET_VER(v) (((v) >> 4) & 0x0F) 99 | # define IPH_GET_LEN(v) (((v) & 0x0F) << 2) 100 | UCHAR version_len; 101 | 102 | UCHAR tos; 103 | USHORT tot_len; 104 | USHORT id; 105 | 106 | # define IP_OFFMASK 0x1fff 107 | USHORT frag_off; 108 | 109 | UCHAR ttl; 110 | 111 | # define IPPROTO_UDP 17 /* UDP protocol */ 112 | # define IPPROTO_TCP 6 /* TCP protocol */ 113 | # define IPPROTO_ICMP 1 /* ICMP protocol */ 114 | # define IPPROTO_IGMP 2 /* IGMP protocol */ 115 | UCHAR protocol; 116 | 117 | USHORT check; 118 | ULONG saddr; 119 | ULONG daddr; 120 | /* The options start here. */ 121 | } IPHDR; 122 | 123 | //----------- 124 | // UDP header 125 | //----------- 126 | 127 | typedef struct { 128 | USHORT source; 129 | USHORT dest; 130 | USHORT len; 131 | USHORT check; 132 | } UDPHDR; 133 | 134 | //-------------------------- 135 | // TCP header, per RFC 793. 136 | //-------------------------- 137 | 138 | typedef struct { 139 | USHORT source; /* source port */ 140 | USHORT dest; /* destination port */ 141 | ULONG seq; /* sequence number */ 142 | ULONG ack_seq; /* acknowledgement number */ 143 | 144 | # define TCPH_GET_DOFF(d) (((d) & 0xF0) >> 2) 145 | UCHAR doff_res; 146 | 147 | # define TCPH_FIN_MASK (1<<0) 148 | # define TCPH_SYN_MASK (1<<1) 149 | # define TCPH_RST_MASK (1<<2) 150 | # define TCPH_PSH_MASK (1<<3) 151 | # define TCPH_ACK_MASK (1<<4) 152 | # define TCPH_URG_MASK (1<<5) 153 | # define TCPH_ECE_MASK (1<<6) 154 | # define TCPH_CWR_MASK (1<<7) 155 | UCHAR flags; 156 | 157 | USHORT window; 158 | USHORT check; 159 | USHORT urg_ptr; 160 | } TCPHDR; 161 | 162 | #define TCPOPT_EOL 0 163 | #define TCPOPT_NOP 1 164 | #define TCPOPT_MAXSEG 2 165 | #define TCPOLEN_MAXSEG 4 166 | 167 | //------------ 168 | // IPv6 Header 169 | //------------ 170 | 171 | typedef struct { 172 | UCHAR version_prio; 173 | UCHAR flow_lbl[3]; 174 | USHORT payload_len; 175 | # define IPPROTO_ICMPV6 0x3a /* ICMP protocol v6 */ 176 | UCHAR nexthdr; 177 | UCHAR hop_limit; 178 | IPV6ADDR saddr; 179 | IPV6ADDR daddr; 180 | } IPV6HDR; 181 | 182 | //-------------------------------------------- 183 | // IPCMPv6 NS/NA Packets (RFC4443 and RFC4861) 184 | //-------------------------------------------- 185 | 186 | // Neighbor Solictiation - RFC 4861, 4.3 187 | // (this is just the ICMPv6 part of the packet) 188 | typedef struct { 189 | UCHAR type; 190 | # define ICMPV6_TYPE_NS 135 // neighbour solicitation 191 | UCHAR code; 192 | # define ICMPV6_CODE_0 0 // no specific sub-code for NS/NA 193 | USHORT checksum; 194 | ULONG reserved; 195 | IPV6ADDR target_addr; 196 | } ICMPV6_NS; 197 | 198 | // Neighbor Advertisement - RFC 4861, 4.4 + 4.6/4.6.1 199 | // (this is just the ICMPv6 payload) 200 | typedef struct { 201 | UCHAR type; 202 | # define ICMPV6_TYPE_NA 136 // neighbour advertisement 203 | UCHAR code; 204 | # define ICMPV6_CODE_0 0 // no specific sub-code for NS/NA 205 | USHORT checksum; 206 | UCHAR rso_bits; // Router(0), Solicited(2), Ovrrd(4) 207 | UCHAR reserved[3]; 208 | IPV6ADDR target_addr; 209 | // always include "Target Link-layer Address" option (RFC 4861 4.6.1) 210 | UCHAR opt_type; 211 | #define ICMPV6_OPTION_TLLA 2 212 | UCHAR opt_length; 213 | #define ICMPV6_LENGTH_TLLA 1 // multiplied by 8 -> 1 = 8 bytes 214 | MACADDR target_macaddr; 215 | } ICMPV6_NA; 216 | 217 | // this is the complete packet with Ethernet and IPv6 headers 218 | typedef struct { 219 | ETH_HEADER eth; 220 | IPV6HDR ipv6; 221 | ICMPV6_NA icmpv6; 222 | } ICMPV6_NA_PKT; 223 | 224 | 225 | //-------------------------------------------- 226 | // 802.1Q Header 227 | //-------------------------------------------- 228 | 229 | typedef struct { 230 | USHORT Tag; 231 | USHORT EtherType; 232 | } ETH_8021Q_HEADER, *PETH_8021Q_HEADER; 233 | 234 | #define ETHERTYPE_8021Q 0x8100 235 | 236 | 237 | #pragma pack() 238 | -------------------------------------------------------------------------------- /src/prototypes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #ifndef TAP_PROTOTYPES_DEFINED 26 | #define TAP_PROTOTYPES_DEFINED 27 | 28 | DRIVER_INITIALIZE DriverEntry; 29 | 30 | //VOID AdapterFreeResources 31 | // ( 32 | // TapAdapterPointer p_Adapter 33 | // ); 34 | // 35 | 36 | // 37 | //NTSTATUS TapDeviceHook 38 | // ( 39 | // IN PDEVICE_OBJECT p_DeviceObject, 40 | // IN PIRP p_IRP 41 | // ); 42 | // 43 | 44 | NDIS_STATUS 45 | CreateTapDevice( 46 | __in PTAP_ADAPTER_CONTEXT Adapter 47 | ); 48 | 49 | VOID 50 | DestroyTapDevice( 51 | __in PTAP_ADAPTER_CONTEXT Adapter 52 | ); 53 | 54 | // Flush the pending send TAP packet queue. 55 | VOID 56 | tapFlushSendPacketQueue( 57 | __in PTAP_ADAPTER_CONTEXT Adapter 58 | ); 59 | 60 | VOID 61 | tapCompleteFlowControlPackets( 62 | __in PTAP_ADAPTER_CONTEXT Adapter 63 | ); 64 | 65 | VOID 66 | tapCheckFlowControl( 67 | __in PTAP_ADAPTER_CONTEXT Adapter 68 | ); 69 | 70 | VOID 71 | IndicateReceivePacket( 72 | __in PTAP_ADAPTER_CONTEXT Adapter, 73 | __in PUCHAR packetData, 74 | __in const unsigned int packetLength 75 | ); 76 | 77 | BOOLEAN 78 | ProcessDHCP( 79 | __in PTAP_ADAPTER_CONTEXT Adapter, 80 | __in const ETH_HEADER *eth, 81 | __in const IPHDR *ip, 82 | __in const UDPHDR *udp, 83 | __in const DHCP *dhcp, 84 | __in int optlen 85 | ); 86 | 87 | BOOLEAN 88 | ProcessARP( 89 | __in PTAP_ADAPTER_CONTEXT Adapter, 90 | __in const PARP_PACKET src, 91 | __in const IPADDR adapter_ip, 92 | __in const IPADDR ip_network, 93 | __in const IPADDR ip_netmask, 94 | __in const MACADDR mac 95 | ); 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /src/resource.rc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "config.h" 5 | 6 | #undef VER_PRODUCTVERSION 7 | #undef VER_PRODUCTVERSION_STR 8 | #undef VER_COMPANYNAME_STR 9 | #undef VER_PRODUCTNAME_STR 10 | 11 | /* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR 12 | * and VER_INTERNALNAME_STR must be defined before including COMMON.VER 13 | * The strings don't need a '\0', since common.ver has them. 14 | */ 15 | 16 | #define VER_FILETYPE VFT_DRV 17 | /* possible values: VFT_UNKNOWN 18 | VFT_APP 19 | VFT_DLL 20 | VFT_DRV 21 | VFT_FONT 22 | VFT_VXD 23 | VFT_STATIC_LIB 24 | */ 25 | #define VER_FILESUBTYPE VFT2_DRV_NETWORK 26 | /* possible values VFT2_UNKNOWN 27 | VFT2_DRV_PRINTER 28 | VFT2_DRV_KEYBOARD 29 | VFT2_DRV_LANGUAGE 30 | VFT2_DRV_DISPLAY 31 | VFT2_DRV_MOUSE 32 | VFT2_DRV_NETWORK 33 | VFT2_DRV_SYSTEM 34 | VFT2_DRV_INSTALLABLE 35 | VFT2_DRV_SOUND 36 | VFT2_DRV_COMM 37 | */ 38 | 39 | #define VER_COMPANYNAME_STR "The OpenVPN Project" 40 | #define VER_FILEDESCRIPTION_STR "TAP-Windows Virtual Network Driver (NDIS 6.0)" 41 | #define VER_ORIGINALFILENAME_STR PRODUCT_TAP_WIN_COMPONENT_ID ".sys" 42 | #define VER_LEGALCOPYRIGHT_YEARS "2003-2018" 43 | #define VER_LEGALCOPYRIGHT_STR "OpenVPN Technologies, Inc." 44 | 45 | 46 | #define VER_PRODUCTNAME_STR VER_FILEDESCRIPTION_STR 47 | #define VER_PRODUCTVERSION PRODUCT_TAP_WIN_MAJOR,PRODUCT_TAP_WIN_MINOR,PRODUCT_TAP_WIN_REVISION,PRODUCT_TAP_WIN_BUILD 48 | 49 | #define XSTR(s) STR(s) 50 | #define STR(s) #s 51 | 52 | #define VSTRING PRODUCT_VERSION " " XSTR(PRODUCT_TAP_WIN_MAJOR) "/" XSTR(PRODUCT_TAP_WIN_MINOR) 53 | 54 | #ifdef DBG 55 | #define VER_PRODUCTVERSION_STR VSTRING " (DEBUG)" 56 | #else 57 | #define VER_PRODUCTVERSION_STR VSTRING 58 | #endif 59 | 60 | #define VER_INTERNALNAME_STR VER_ORIGINALFILENAME_STR 61 | 62 | #include "common.ver" 63 | -------------------------------------------------------------------------------- /src/tap-windows.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). This particular file 9 | * (tap-windows.h) is also licensed using the MIT license (see COPYRIGHT.MIT). 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License version 2 13 | * as published by the Free Software Foundation. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program (see the file COPYING included with this 22 | * distribution); if not, write to the Free Software Foundation, Inc., 23 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 | */ 25 | #ifndef __TAP_WIN_H 26 | #define __TAP_WIN_H 27 | 28 | /* 29 | * ============= 30 | * TAP IOCTLs 31 | * ============= 32 | */ 33 | 34 | #define TAP_WIN_CONTROL_CODE(request,method) \ 35 | CTL_CODE (FILE_DEVICE_UNKNOWN, request, method, FILE_ANY_ACCESS) 36 | 37 | /* Present in 8.1 */ 38 | 39 | #define TAP_WIN_IOCTL_GET_MAC TAP_WIN_CONTROL_CODE (1, METHOD_BUFFERED) 40 | #define TAP_WIN_IOCTL_GET_VERSION TAP_WIN_CONTROL_CODE (2, METHOD_BUFFERED) 41 | #define TAP_WIN_IOCTL_GET_MTU TAP_WIN_CONTROL_CODE (3, METHOD_BUFFERED) 42 | #define TAP_WIN_IOCTL_GET_INFO TAP_WIN_CONTROL_CODE (4, METHOD_BUFFERED) 43 | #define TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT TAP_WIN_CONTROL_CODE (5, METHOD_BUFFERED) 44 | #define TAP_WIN_IOCTL_SET_MEDIA_STATUS TAP_WIN_CONTROL_CODE (6, METHOD_BUFFERED) 45 | #define TAP_WIN_IOCTL_CONFIG_DHCP_MASQ TAP_WIN_CONTROL_CODE (7, METHOD_BUFFERED) 46 | #define TAP_WIN_IOCTL_GET_LOG_LINE TAP_WIN_CONTROL_CODE (8, METHOD_BUFFERED) 47 | #define TAP_WIN_IOCTL_CONFIG_DHCP_SET_OPT TAP_WIN_CONTROL_CODE (9, METHOD_BUFFERED) 48 | 49 | /* Added in 8.2 */ 50 | 51 | /* obsoletes TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT */ 52 | #define TAP_WIN_IOCTL_CONFIG_TUN TAP_WIN_CONTROL_CODE (10, METHOD_BUFFERED) 53 | 54 | /* Control whether 802.1Q headers are added for priority */ 55 | #define TAP_WIN_IOCTL_PRIORITY_BEHAVIOR TAP_WIN_CONTROL_CODE (11, METHOD_BUFFERED) 56 | #define TAP_PRIORITY_BEHAVIOR_NOPRIORITY 0 57 | #define TAP_PRIORITY_BEHAVIOR_ENABLED 1 58 | #define TAP_PRIORITY_BEHAVIOR_ADDALWAYS 2 59 | #define TAP_PRIORITY_BEHAVIOR_MAX 2 60 | 61 | /* 62 | * ================= 63 | * Registry keys 64 | * ================= 65 | */ 66 | 67 | #define ADAPTER_KEY "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}" 68 | 69 | #define NETWORK_CONNECTIONS_KEY "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}" 70 | 71 | /* 72 | * ====================== 73 | * Filesystem prefixes 74 | * ====================== 75 | */ 76 | 77 | #define USERMODEDEVICEDIR "\\\\.\\Global\\" 78 | #define SYSDEVICEDIR "\\Device\\" 79 | #define USERDEVICEDIR "\\DosDevices\\Global\\" 80 | #define TAP_WIN_SUFFIX ".tap" 81 | 82 | #endif // __TAP_WIN_H 83 | -------------------------------------------------------------------------------- /src/tap-windows6.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Source Files 6 | 7 | 8 | Source Files 9 | 10 | 11 | Source Files 12 | 13 | 14 | Source Files 15 | 16 | 17 | Source Files 18 | 19 | 20 | Source Files 21 | 22 | 23 | Source Files 24 | 25 | 26 | Source Files 27 | 28 | 29 | Source Files 30 | 31 | 32 | Source Files 33 | 34 | 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 | Header Files 65 | 66 | 67 | Header Files 68 | 69 | 70 | Header Files 71 | 72 | 73 | Header Files 74 | 75 | 76 | Header Files 77 | 78 | 79 | Header Files 80 | 81 | 82 | Header Files 83 | 84 | 85 | 86 | 87 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 88 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 89 | 90 | 91 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 92 | h;hpp;hxx;hm;inl;inc;xsd 93 | 94 | 95 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 96 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 97 | 98 | 99 | {8E41214B-6785-4CFE-B992-037D68949A14} 100 | inf;inv;inx;mof;mc; 101 | 102 | 103 | 104 | 105 | Driver Files 106 | 107 | 108 | 109 | 110 | Resource Files 111 | 112 | 113 | -------------------------------------------------------------------------------- /src/tap-windows6.vcxproj.in: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Hlk 10 | Win32 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Debug 18 | x64 19 | 20 | 21 | Hlk 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | Debug 30 | ARM64 31 | 32 | 33 | Hlk 34 | ARM64 35 | 36 | 37 | Release 38 | ARM64 39 | 40 | 41 | 42 | {A52442E2-8B33-4C4C-AC96-E8868DBADC6C} 43 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 44 | v4.5 45 | 12.0 46 | Debug 47 | Win32 48 | @PRODUCT_TAP_WIN_COMPONENT_ID@ 49 | $(LatestTargetPlatformVersion) 50 | 51 | 52 | 53 | Windows7 54 | true 55 | WindowsKernelModeDriver10.0 56 | Driver 57 | WDM 58 | TestSign 59 | 60 | 61 | Windows7 62 | false 63 | WindowsKernelModeDriver10.0 64 | Driver 65 | WDM 66 | TestSign 67 | 68 | 69 | Windows7 70 | false 71 | WindowsKernelModeDriver10.0 72 | Driver 73 | WDM 74 | Off 75 | 76 | 77 | Windows7 78 | true 79 | WindowsKernelModeDriver10.0 80 | Driver 81 | WDM 82 | TestSign 83 | 84 | 85 | Windows7 86 | false 87 | WindowsKernelModeDriver10.0 88 | Driver 89 | WDM 90 | TestSign 91 | 92 | 93 | Windows7 94 | false 95 | WindowsKernelModeDriver10.0 96 | Driver 97 | WDM 98 | Off 99 | 100 | 101 | Windows10 102 | true 103 | WindowsKernelModeDriver10.0 104 | Driver 105 | WDM 106 | TestSign 107 | 108 | 109 | Windows10 110 | false 111 | WindowsKernelModeDriver10.0 112 | Driver 113 | WDM 114 | TestSign 115 | 116 | 117 | Windows10 118 | false 119 | WindowsKernelModeDriver10.0 120 | Driver 121 | WDM 122 | Off 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | DbgengKernelDebugger 134 | @PRODUCT_TAP_WIN_COMPONENT_ID@ 135 | Vista_X86,Server2008_X86,7_X86,8_X86,6_3_X86,10_X86 136 | 137 | 138 | DbgengKernelDebugger 139 | @PRODUCT_TAP_WIN_COMPONENT_ID@ 140 | 141 | 142 | DbgengKernelDebugger 143 | @PRODUCT_TAP_WIN_COMPONENT_ID@ 144 | Vista_X86,Server2008_X86,7_X86,8_X86,6_3_X86,10_X86 145 | 146 | 147 | DbgengKernelDebugger 148 | @PRODUCT_TAP_WIN_COMPONENT_ID@ 149 | Vista_X64,Server2008_X64,7_X64,8_X64,6_3_X64,10_X64,Server2008R2_X64,Server8_X64,Server10_X64 150 | 151 | 152 | DbgengKernelDebugger 153 | @PRODUCT_TAP_WIN_COMPONENT_ID@ 154 | 155 | 156 | DbgengKernelDebugger 157 | @PRODUCT_TAP_WIN_COMPONENT_ID@ 158 | true 159 | $(WDKContentRoot)CodeAnalysis\DriverMinimumRules.ruleset 160 | Vista_X64,Server2008_X64,7_X64,8_X64,6_3_X64,10_X64,Server2008R2_X64,Server8_X64,Server10_X64 161 | 162 | 163 | DbgengKernelDebugger 164 | @PRODUCT_TAP_WIN_COMPONENT_ID@ 165 | 166 | 167 | DbgengKernelDebugger 168 | @PRODUCT_TAP_WIN_COMPONENT_ID@ 169 | 170 | 171 | DbgengKernelDebugger 172 | @PRODUCT_TAP_WIN_COMPONENT_ID@ 173 | 174 | 175 | 176 | Level4 177 | %(DisableSpecificWarnings);4201;4214;4100;4101;4200;4057;4127 178 | false 179 | %(PreprocessorDefinitions);TAP_DRIVER_MAJOR_VERSION=@PRODUCT_TAP_WIN_MAJOR@;TAP_DRIVER_MINOR_VERSION=@PRODUCT_TAP_WIN_MINOR@;NDIS_WDM=1;NDIS_MINIPORT_DRIVER=1;NDIS620_MINIPORT=1;NDIS630_MINIPORT=1 180 | true 181 | 182 | 183 | %(AdditionalDependencies);$(KernelBufferOverflowLib);$(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib;ndis.lib;ntstrsafe.lib;wdmsec.lib 184 | 185 | 186 | @PRODUCT_TAP_WIN_MAJOR@.@PRODUCT_TAP_WIN_MINOR@.@PRODUCT_TAP_WIN_REVISION@.@PRODUCT_TAP_WIN_BUILD@ 187 | @PRODUCT_TAP_WIN_RELDATE@ 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | -------------------------------------------------------------------------------- /src/tap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | #ifndef __TAP_H 25 | #define __TAP_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "config.h" 33 | #include "lock.h" 34 | #include "constants.h" 35 | #include "proto.h" 36 | #include "mem.h" 37 | #include "macinfo.h" 38 | #include "dhcp.h" 39 | #include "error.h" 40 | #include "endian.h" 41 | #include "dhcp.h" 42 | #include "types.h" 43 | #include "adapter.h" 44 | #include "device.h" 45 | #include "prototypes.h" 46 | #include "tap-windows.h" 47 | 48 | //======================================================== 49 | // Check for truncated IPv4 packets, log errors if found. 50 | //======================================================== 51 | #define PACKET_TRUNCATION_CHECK 0 52 | 53 | //======================================================== 54 | // EXPERIMENTAL -- Configure TAP device object to be 55 | // accessible from non-administrative accounts, based 56 | // on an advanced properties setting. 57 | // 58 | // Duplicates the functionality of OpenVPN's 59 | // --allow-nonadmin directive. 60 | //======================================================== 61 | #define ENABLE_NONADMIN 1 62 | 63 | // 64 | // The driver has exactly one instance of the TAP_GLOBAL structure. NDIS keeps 65 | // an opaque handle to this data, (it doesn't attempt to read or interpret this 66 | // data), and it passes the handle back to the miniport in MiniportSetOptions 67 | // and MiniportInitializeEx. 68 | // 69 | typedef struct _TAP_GLOBAL 70 | { 71 | LIST_ENTRY AdapterList; 72 | 73 | PNDIS_RW_LOCK_EX Lock; 74 | 75 | NDIS_HANDLE NdisDriverHandle; // From NdisMRegisterMiniportDriver 76 | 77 | UINT NdisVersion; 78 | 79 | BOOLEAN RunningWindows8OrGreater; 80 | 81 | BOOLEAN EnableTapDiag; 82 | 83 | } TAP_GLOBAL, *PTAP_GLOBAL; 84 | 85 | 86 | // Global data 87 | extern TAP_GLOBAL GlobalData; 88 | 89 | #define TAP_NDIS_MAJOR_VERSION ((UCHAR)(GlobalData.NdisVersion >> 16)) 90 | #define TAP_NDIS_MINOR_VERSION ((UCHAR)(GlobalData.NdisVersion & 0xFF)) 91 | 92 | #endif // __TAP_H 93 | -------------------------------------------------------------------------------- /src/tapdrvr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | //====================================================== 26 | // This driver is designed to work on Windows Vista or higher 27 | // versions of Windows. 28 | // 29 | // It is SMP-safe and handles power management. 30 | // 31 | // By default we operate as a "tap" virtual ethernet 32 | // 802.3 interface, but we can emulate a "tun" 33 | // interface (point-to-point IPv4) through the 34 | // TAP_WIN_IOCTL_CONFIG_POINT_TO_POINT or 35 | // TAP_WIN_IOCTL_CONFIG_TUN ioctl. 36 | //====================================================== 37 | 38 | // 39 | // Include files. 40 | // 41 | 42 | #include 43 | 44 | #include "tap.h" 45 | 46 | 47 | // Global data 48 | TAP_GLOBAL GlobalData; 49 | 50 | 51 | #ifdef ALLOC_PRAGMA 52 | #pragma alloc_text( INIT, DriverEntry ) 53 | #pragma alloc_text( PAGE, TapDriverUnload) 54 | #endif // ALLOC_PRAGMA 55 | 56 | NTSTATUS 57 | DriverEntry( 58 | __in PDRIVER_OBJECT DriverObject, 59 | __in PUNICODE_STRING RegistryPath 60 | ) 61 | /*++ 62 | Routine Description: 63 | 64 | In the context of its DriverEntry function, a miniport driver associates 65 | itself with NDIS, specifies the NDIS version that it is using, and 66 | registers its entry points. 67 | 68 | 69 | Arguments: 70 | PVOID DriverObject - pointer to the driver object. 71 | PVOID RegistryPath - pointer to the driver registry path. 72 | 73 | Return Value: 74 | 75 | NTSTATUS code 76 | 77 | --*/ 78 | { 79 | ULONGLONG conditionMask; 80 | RTL_OSVERSIONINFOEXW osInfo = { 0 }; 81 | NTSTATUS status; 82 | 83 | UNREFERENCED_PARAMETER(RegistryPath); 84 | 85 | DEBUGP (("[TAP] --> DriverEntry; version [%d.%d] %s %s\n", 86 | TAP_DRIVER_MAJOR_VERSION, 87 | TAP_DRIVER_MINOR_VERSION, 88 | __DATE__, 89 | __TIME__)); 90 | 91 | DEBUGP (("[TAP] Registry Path: '%wZ'\n", RegistryPath)); 92 | 93 | // 94 | // Initialize any driver-global variables here. 95 | // 96 | NdisZeroMemory(&GlobalData, sizeof(GlobalData)); 97 | 98 | // 99 | // Check what NDIS version is supported by the OS 100 | // 101 | GlobalData.NdisVersion = NdisGetVersion(); 102 | if (GlobalData.NdisVersion < NDIS_RUNTIME_VERSION_620) 103 | { 104 | return NDIS_STATUS_UNSUPPORTED_REVISION; 105 | } 106 | if (GlobalData.NdisVersion == NDIS_RUNTIME_VERSION_620) 107 | { 108 | GlobalData.NdisVersion = NDIS_RUNTIME_VERSION_620; 109 | } 110 | if (GlobalData.NdisVersion > NDIS_RUNTIME_VERSION_620) 111 | { 112 | GlobalData.NdisVersion = NDIS_RUNTIME_VERSION_630; 113 | } 114 | 115 | // 116 | // The AdapterList in the GlobalData structure is used to track multiple 117 | // adapters controlled by this miniport. 118 | // 119 | NdisInitializeListHead(&GlobalData.AdapterList); 120 | 121 | // 122 | // Determine whether to enable TapDiag devices 123 | // 124 | { 125 | HANDLE regKey = NULL; 126 | NTSTATUS result; 127 | OBJECT_ATTRIBUTES keyAttributes; 128 | UNICODE_STRING regValueName; 129 | 130 | RtlInitUnicodeString(®ValueName, L"TapDiag"); 131 | 132 | InitializeObjectAttributes(&keyAttributes, RegistryPath, OBJ_KERNEL_HANDLE, NULL, NULL); 133 | 134 | result = ZwOpenKey(®Key, KEY_QUERY_VALUE, &keyAttributes); 135 | if(NT_SUCCESS(result)) 136 | { 137 | UCHAR partialInfoBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)]; 138 | PKEY_VALUE_PARTIAL_INFORMATION partialInfo = (PKEY_VALUE_PARTIAL_INFORMATION)partialInfoBuffer; 139 | ULONG resultLength = 0; 140 | 141 | result = ZwQueryValueKey( 142 | regKey, 143 | ®ValueName, 144 | KeyValuePartialInformation, 145 | partialInfo, 146 | sizeof(partialInfoBuffer), 147 | &resultLength); 148 | 149 | if(NT_SUCCESS(result)) 150 | { 151 | if(partialInfo->Type == REG_DWORD) 152 | { 153 | DWORD value = *((DWORD*)partialInfo->Data); 154 | 155 | GlobalData.EnableTapDiag = value != 0; 156 | } 157 | } 158 | 159 | ZwClose(regKey); 160 | } 161 | } 162 | 163 | 164 | do 165 | { 166 | NDIS_MINIPORT_DRIVER_CHARACTERISTICS miniportCharacteristics; 167 | 168 | NdisZeroMemory(&miniportCharacteristics, sizeof(miniportCharacteristics)); 169 | 170 | {C_ASSERT(sizeof(miniportCharacteristics) >= NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2);} 171 | miniportCharacteristics.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS; 172 | miniportCharacteristics.Header.Size = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2; 173 | miniportCharacteristics.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2; 174 | 175 | miniportCharacteristics.MajorNdisVersion = TAP_NDIS_MAJOR_VERSION; 176 | miniportCharacteristics.MinorNdisVersion = TAP_NDIS_MINOR_VERSION; 177 | 178 | miniportCharacteristics.MajorDriverVersion = TAP_DRIVER_MAJOR_VERSION; 179 | miniportCharacteristics.MinorDriverVersion = TAP_DRIVER_MINOR_VERSION; 180 | 181 | miniportCharacteristics.Flags = 0; 182 | 183 | //miniportCharacteristics.SetOptionsHandler = MPSetOptions; // Optional 184 | miniportCharacteristics.InitializeHandlerEx = AdapterCreate; 185 | miniportCharacteristics.HaltHandlerEx = AdapterHalt; 186 | miniportCharacteristics.UnloadHandler = TapDriverUnload; 187 | miniportCharacteristics.PauseHandler = AdapterPause; 188 | miniportCharacteristics.RestartHandler = AdapterRestart; 189 | miniportCharacteristics.OidRequestHandler = AdapterOidRequest; 190 | miniportCharacteristics.SendNetBufferListsHandler = AdapterSendNetBufferLists; 191 | miniportCharacteristics.ReturnNetBufferListsHandler = AdapterReturnNetBufferLists; 192 | miniportCharacteristics.CancelSendHandler = AdapterCancelSend; 193 | miniportCharacteristics.CheckForHangHandlerEx = AdapterCheckForHangEx; 194 | miniportCharacteristics.ResetHandlerEx = AdapterReset; 195 | miniportCharacteristics.DevicePnPEventNotifyHandler = AdapterDevicePnpEventNotify; 196 | miniportCharacteristics.ShutdownHandlerEx = AdapterShutdownEx; 197 | miniportCharacteristics.CancelOidRequestHandler = AdapterCancelOidRequest; 198 | miniportCharacteristics.DirectOidRequestHandler = AdapterDirectOidRequest; 199 | miniportCharacteristics.CancelDirectOidRequestHandler = AdapterCancelDirectOidRequest; 200 | 201 | // 202 | // Associate the miniport driver with NDIS by calling the 203 | // NdisMRegisterMiniportDriver. This function returns an NdisDriverHandle. 204 | // The miniport driver must retain this handle but it should never attempt 205 | // to access or interpret this handle. 206 | // 207 | // By calling NdisMRegisterMiniportDriver, the driver indicates that it 208 | // is ready for NDIS to call the driver's MiniportSetOptions and 209 | // MiniportInitializeEx handlers. 210 | // 211 | DEBUGP (("[TAP] Calling NdisMRegisterMiniportDriver...\n")); 212 | //NDIS_DECLARE_MINIPORT_DRIVER_CONTEXT(TAP_GLOBAL); 213 | status = NdisMRegisterMiniportDriver( 214 | DriverObject, 215 | RegistryPath, 216 | &GlobalData, 217 | &miniportCharacteristics, 218 | &GlobalData.NdisDriverHandle 219 | ); 220 | 221 | if (NDIS_STATUS_SUCCESS == status) 222 | { 223 | DEBUGP (("[TAP] Registered miniport successfully\n")); 224 | 225 | // 226 | // This driver calls MmGetSystemAddressForMdlSafe which has a flag that is 227 | // required for HVCI on Windows 8/Windows Server 2012 and newer. Capture 228 | // the version information on driver load. 229 | // 230 | // Per the docs, major and minor versions are compared hierarchically, not 231 | // simultaneously, so the expected behavior is intuitive: 10.0 > 6.2. 232 | // 233 | 234 | osInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); 235 | osInfo.dwMajorVersion = 6; 236 | osInfo.dwMajorVersion = 2; 237 | conditionMask = 0; 238 | VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); 239 | VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); 240 | 241 | status = RtlVerifyVersionInfo(&osInfo, 242 | (ULONG)(VER_MAJORVERSION | VER_MINORVERSION), 243 | (ULONGLONG)conditionMask); 244 | 245 | switch (status) { 246 | case STATUS_SUCCESS: 247 | 248 | GlobalData.RunningWindows8OrGreater = TRUE; 249 | status = NDIS_STATUS_SUCCESS; 250 | break; 251 | 252 | case STATUS_REVISION_MISMATCH: 253 | 254 | GlobalData.RunningWindows8OrGreater = FALSE; 255 | status = NDIS_STATUS_SUCCESS; 256 | break; 257 | 258 | case STATUS_INVALID_PARAMETER: 259 | default: 260 | NOTHING; 261 | } 262 | 263 | if (status != NDIS_STATUS_SUCCESS) { 264 | DEBUGP(("[TAP] Failed to detemine OS version using RtlVerifyVersionInfo: %x\n", status)); 265 | TapDriverUnload(DriverObject); 266 | break; 267 | } 268 | 269 | // 270 | // This lock protects the AdapterList. 271 | // 272 | GlobalData.Lock = NdisAllocateRWLock(GlobalData.NdisDriverHandle); 273 | if (GlobalData.Lock == NULL) 274 | { 275 | DEBUGP(("[TAP] NdisAllocateRWLock failed to allocate a lock.\n")); 276 | TapDriverUnload(DriverObject); 277 | status = NDIS_STATUS_FAILURE; 278 | break; 279 | } 280 | } 281 | else 282 | { 283 | DEBUGP(("[TAP] NdisMRegisterMiniportDriver failed: %8.8X\n", status)); 284 | TapDriverUnload(DriverObject); 285 | status = NDIS_STATUS_FAILURE; 286 | break; 287 | } 288 | } while(FALSE); 289 | 290 | DEBUGP (("[TAP] <-- DriverEntry; status = %8.8X\n",status)); 291 | 292 | return status; 293 | } 294 | 295 | VOID 296 | TapDriverUnload( 297 | __in PDRIVER_OBJECT DriverObject 298 | ) 299 | /*++ 300 | 301 | Routine Description: 302 | 303 | The unload handler is called during driver unload to free up resources 304 | acquired in DriverEntry. This handler is registered in DriverEntry through 305 | NdisMRegisterMiniportDriver. Note that an unload handler differs from 306 | a MiniportHalt function in that this unload handler releases resources that 307 | are global to the driver, while the halt handler releases resource for a 308 | particular adapter. 309 | 310 | Runs at IRQL = PASSIVE_LEVEL. 311 | 312 | Arguments: 313 | 314 | DriverObject Not used 315 | 316 | Return Value: 317 | 318 | None. 319 | 320 | --*/ 321 | { 322 | DEBUGP (("[TAP] --> TapDriverUnload; version [%d.%d] %s %s unloaded\n", 323 | TAP_DRIVER_MAJOR_VERSION, 324 | TAP_DRIVER_MINOR_VERSION, 325 | __DATE__, 326 | __TIME__ 327 | )); 328 | 329 | PAGED_CODE(); 330 | 331 | // 332 | // Clean up all globals that were allocated in DriverEntry 333 | // 334 | 335 | ASSERT(IsListEmpty(&GlobalData.AdapterList)); 336 | 337 | if (GlobalData.Lock != NULL) 338 | { 339 | NdisFreeRWLock(GlobalData.Lock); 340 | GlobalData.Lock = NULL; 341 | } 342 | 343 | if(GlobalData.NdisDriverHandle != NULL ) 344 | { 345 | NdisMDeregisterMiniportDriver(GlobalData.NdisDriverHandle); 346 | } 347 | 348 | DEBUGP (("[TAP] <-- TapDriverUnload\n")); 349 | } 350 | 351 | -------------------------------------------------------------------------------- /src/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TAP-Windows -- A kernel driver to provide virtual tap 3 | * device functionality on Windows. 4 | * 5 | * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. 6 | * 7 | * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., 8 | * and is released under the GPL version 2 (see below). 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 12 | * as published by the Free Software Foundation. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program (see the file COPYING included with this 21 | * distribution); if not, write to the Free Software Foundation, Inc., 22 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 | */ 24 | 25 | #ifndef TAP_TYPES_DEFINED 26 | #define TAP_TYPES_DEFINED 27 | 28 | //typedef 29 | //struct _Queue 30 | //{ 31 | // ULONG base; 32 | // ULONG size; 33 | // ULONG capacity; 34 | // ULONG max_size; 35 | // PVOID data[]; 36 | //} Queue; 37 | 38 | //typedef struct _TAP_PACKET; 39 | 40 | //typedef struct _TapExtension 41 | //{ 42 | // // TAP device object and packet queues 43 | // Queue *m_PacketQueue, *m_IrpQueue; 44 | // PDEVICE_OBJECT m_TapDevice; 45 | // NDIS_HANDLE m_TapDeviceHandle; 46 | // ULONG TapFileIsOpen; 47 | // 48 | // // Used to lock packet queues 49 | // NDIS_SPIN_LOCK m_QueueLock; 50 | // BOOLEAN m_AllocatedSpinlocks; 51 | // 52 | // // Used to bracket open/close 53 | // // state changes. 54 | // MUTEX m_OpenCloseMutex; 55 | // 56 | // // True if device has been permanently halted 57 | // BOOLEAN m_Halt; 58 | // 59 | // // TAP device name 60 | // unsigned char *m_TapName; 61 | // UNICODE_STRING m_UnicodeLinkName; 62 | // BOOLEAN m_CreatedUnicodeLinkName; 63 | // 64 | // // Used for device status ioctl only 65 | // const char *m_LastErrorFilename; 66 | // int m_LastErrorLineNumber; 67 | // LONG TapFileOpenCount; 68 | // 69 | // // Flags 70 | // BOOLEAN TapDeviceCreated; 71 | // BOOLEAN m_CalledTapDeviceFreeResources; 72 | // 73 | // // DPC queue for deferred packet injection 74 | // BOOLEAN m_InjectDpcInitialized; 75 | // KDPC m_InjectDpc; 76 | // NDIS_SPIN_LOCK m_InjectLock; 77 | // Queue *m_InjectQueue; 78 | //} 79 | //TapExtension, *TapExtensionPointer; 80 | 81 | typedef struct _InjectPacket 82 | { 83 | # define INJECT_PACKET_SIZE(data_size) (sizeof (InjectPacket) + (data_size)) 84 | # define INJECT_PACKET_FREE(ib) NdisFreeMemory ((ib), INJECT_PACKET_SIZE ((ib)->m_Size), 0) 85 | ULONG m_Size; 86 | UCHAR m_Data []; // m_Data must be the last struct member 87 | } 88 | InjectPacket, *InjectPacketPointer; 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /version.m4: -------------------------------------------------------------------------------- 1 | dnl define the TAP version 2 | define([PRODUCT_NAME], [TAP-Windows]) 3 | define([PRODUCT_PUBLISHER], [London Trust Media, Inc.]) 4 | define([PRODUCT_VERSION], [9.24.2]) 5 | define([PRODUCT_VERSION_RESOURCE], [9,24,2,601]) 6 | define([PRODUCT_TAP_WIN_COMPONENT_ID], [tap-pia-0901]) 7 | define([PRODUCT_TAP_WIN_MAJOR], [9]) 8 | define([PRODUCT_TAP_WIN_MINOR], [24]) 9 | define([PRODUCT_TAP_WIN_REVISION], [2]) 10 | define([PRODUCT_TAP_WIN_BUILD], [601]) 11 | define([PRODUCT_TAP_WIN_PROVIDER], [Private Internet Access]) 12 | define([PRODUCT_TAP_WIN_CHARACTERISTICS], [0x1]) 13 | define([PRODUCT_TAP_WIN_DEVICE_DESCRIPTION], [Private Internet Access Network Adapter]) 14 | define([PRODUCT_TAP_WIN_RELDATE], [09/27/2019]) 15 | --------------------------------------------------------------------------------