├── .github └── workflows │ └── main.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md ├── bindgen.sh ├── examples ├── demo_server.rs └── wireguard_nt │ ├── LICENSE.txt │ ├── README.md │ ├── bin │ ├── amd64 │ │ └── wireguard.dll │ ├── arm │ │ └── wireguard.dll │ ├── arm64 │ │ └── wireguard.dll │ └── x86 │ │ └── wireguard.dll │ └── include │ └── wireguard.h ├── src ├── adapter.rs ├── lib.rs ├── log.rs ├── util.rs └── wireguard_nt_raw.rs └── wireguard_nt ├── LICENSE.txt ├── README.md ├── wireguard.h └── wireguard_functions.h /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | 2 | name: CI 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | test: 7 | name: Test 8 | runs-on: windows-latest 9 | strategy: 10 | matrix: 11 | rust: [stable, beta, nightly] 12 | steps: 13 | - uses: actions/checkout@master 14 | - name: Build & Test 15 | run: | 16 | rustup update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} 17 | cargo test 18 | 19 | rustfmt: 20 | name: Rustfmt 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@master 24 | - name: Rustfmt Check 25 | run: | 26 | rustup update stable && rustup default stable && rustup component add rustfmt 27 | cargo fmt -- --check 28 | 29 | clippy_check: 30 | name: Clippy Check 31 | runs-on: windows-latest 32 | steps: 33 | - uses: actions/checkout@v1 34 | - id: component 35 | uses: actions-rs/components-nightly@v1 36 | with: 37 | component: clippy 38 | - uses: actions-rs/toolchain@v1 39 | with: 40 | toolchain: ${{ steps.component.outputs.toolchain }} 41 | override: true 42 | - run: rustup component add clippy 43 | - uses: actions-rs/clippy-check@v1 44 | with: 45 | token: ${{ secrets.GITHUB_TOKEN }} 46 | args: --all-features 47 | 48 | # TODO(Troy): re-enable after we bump to fix breaking change in winapi breaking our old compilation 49 | # semver: 50 | # name: Check semver 51 | # runs-on: windows-latest 52 | # steps: 53 | # - uses: actions/checkout@v2 54 | # - uses: actions-rs/toolchain@v1 55 | # with: 56 | # profile: minimal 57 | # toolchain: stable 58 | # override: true 59 | # - uses: obi1kenobi/cargo-semver-checks-action@v2 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | /.idea/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # ChangeLog 2 | 3 | This format is based on [Keep a Changelog](https://keepachangelog.com/) 4 | and this project adheres to [Semantic Versioning](https://semver.org). 5 | 6 | 7 | ## [0.5.0] - 2024-08-10 8 | 9 | ### Changes 10 | 11 | - Fixes compilation failure due to breaking change in winapi. Use windows-sys now that it is the agreed-on crate: https://github.com/nulldotblack/wireguard-nt/pull/15 12 | - Adds a proper error type for this crate: https://github.com/nulldotblack/wireguard-nt/pull/17 13 | - Use `getrandom` over `rand` to reduce dependency tree: https://github.com/nulldotblack/wireguard-nt/pull/16 14 | - Allow creating routes with custom metric: https://github.com/nulldotblack/wireguard-nt/pull/18 15 | 16 | 17 | ### Breaking Changes 18 | 19 | - Any function taking in a `wireguard_nt_raw::wireguard`, a newtype wrapper `wireguard_nt::Wireguard` is used instead 20 | - Any function previously returning an `Result<_, Box>`, a proper error type is now used across this crate 21 | 22 | ## [0.4.0] - 2024-04-11 23 | 24 | ### Fixed 25 | 26 | - Correct printing of handshake time when an adapter has not yet completed the handshake in `demo_server` example. 27 | 28 | ### Breaking Changes 29 | 30 | - `last_handshake` in `WireguardPeer` changed from a `std::time::Instant` to a `std::option::Option` to reflect non handshake state. 31 | 32 | ## [0.3.0] - 2021-11-23 33 | 34 | ### Added 35 | 36 | - `get_config` in `Adapter` to obtain the config from an active WireguardNT interface #6 37 | - `set_default_route` in `Adapter` now takes a slice of IpNet addresses to 38 | support multiple addresses as well as hybrid Ipv6/Ipv4 configuration #7 39 | - Added loop that uses `get_config` to print network traffic stats in `demo_server`. 40 | 41 | ### Breaking Changes 42 | 43 | - `set_default_route` Takes a immutable slice of IpNet's instead of a single Ipv4Net #7 44 | - Names of fields inside adapter::WireguardInterface and adapter::WireguardPeer are changed to be snake case 45 | - `adapter::WireguardPeer::last_handshake` is now an instant to simplify use case 46 | 47 | ## [0.2.2] - 2021-11-14 48 | 49 | ### Fixed 50 | 51 | - Added missing winapi features to fix compilation issue when used as from crates.io 52 | 53 | ## [0.2.1] - 2021-11-5 54 | 55 | ### Documented new API for WireguardNT 0.10 56 | 57 | ## [0.2.0] - 2021-11-4 58 | 59 | ### Added 60 | 61 | - Support for WireguardNT 0.10 #4 62 | - Remove support for versions < WireguardNT 0.10 #3 63 | 64 | ### Fixed 65 | 66 | - `Adapter::set_default_route` doesnt respect allowed ips #2 67 | 68 | ### Documented 69 | 70 | - Updated `demo_server` example accordingly 71 | 72 | ## [0.1.0] - 2021-09-30 73 | 74 | Initial Release 75 | 76 | ### Added 77 | 78 | - Basic API for loading WireguardNT driver dlls, and creating adapters 79 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wireguard-nt" 3 | version = "0.5.0" 4 | edition = "2021" 5 | authors = ["null.black Inc. ", "Troy Neubauer "] 6 | repository = "https://github.com/nulldotblack/wireguard-nt" 7 | readme = "README.md" 8 | documentation = "https://docs.rs/wireguard-nt/" 9 | description = "Safe idiomatic bindings to the Wireguard NT C library" 10 | license = "MIT" 11 | keywords = ["wireguard", "vpn", "windows"] 12 | categories = ["api-bindings"] 13 | 14 | [package.metadata.docs.rs] 15 | default-target = "x86_64-pc-windows-msvc" 16 | targets = ["aarch64-pc-windows-msvc", "i686-pc-windows-msvc", "x86_64-pc-windows-msvc"] 17 | 18 | [dependencies] 19 | bitflags = "2" 20 | getrandom = "0.2" 21 | ipnet = "2.3" 22 | libloading = "0.8" 23 | log = "0.4" 24 | thiserror = "1.0" 25 | widestring = "0.4" 26 | windows-sys = { version = "0.59", features = [ 27 | "Win32_Foundation", 28 | "Win32_Networking", 29 | "Win32_Networking_WinSock", 30 | "Win32_NetworkManagement_IpHelper", 31 | "Win32_NetworkManagement_Ndis" 32 | ]} 33 | 34 | [dev-dependencies] 35 | base64 = "0.13" 36 | env_logger = "0.11" 37 | ipnet = "2.3" 38 | x25519-dalek = { version = "2", default-features = false, features = ["static_secrets", "getrandom"] } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 nulldotblack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wireguard-nt 2 | 3 | Safe rust idiomatic bindings for the WireGuard NT C library: 4 | 5 | Features of the WireGuard NT library are wrapped using pure rust types and functions to make 6 | usage ergonomic. 7 | 8 | ## Usage 9 | 10 | Add a dependency on this library to your `Cargo.toml` 11 | 12 | ```toml 13 | [dependencies] 14 | wireguard-nt = "0.4" 15 | ``` 16 | 17 | Inside your code load the wireguard.dll signed driver file, downloaded from 18 | 19 | Then either call [`Adapter::create`] or [`Adapter::open`] to obtain a wireguard 20 | adapter. Start by setting its config with [`Adapter::set_config`]. 21 | 22 | ## Example 23 | ```rust 24 | //Must be run as Administrator because we create network adapters 25 | //Load the wireguard dll file so that we can call the underlying C functions 26 | //Unsafe because we are loading an arbitrary dll file 27 | let wireguard = unsafe { wireguard_nt::load_from_path("path/to/wireguard.dll") }.expect("Failed to load wireguard dll"); 28 | //Try to open an adapter with the name "Demo" 29 | let adapter = match wireguard_nt::Adapter::open(wireguard, "Demo") { 30 | Ok(a) => a, 31 | Err((_, wireguard)) => { 32 | //If loading failed (most likely it didn't exist), create a new one 33 | match wireguard_nt::Adapter::create(wireguard, "WireGuard", "Demo", None) { 34 | Ok(a) => a, 35 | Err((e, _)) => panic!("Failed to create adapter: {:?}", e), 36 | } 37 | } 38 | }; 39 | 40 | let interface = wireguard_nt::SetInterface { 41 | //Let the OS pick a port for us 42 | listen_port: None, 43 | //Generated from the private key if not specified 44 | public_key: None, 45 | //Fill in private keys in real code 46 | private_key: None, 47 | //Add a peer 48 | peers: vec![wireguard_nt::SetPeer { 49 | //Provide a public key so that we can communicate with them 50 | public_key: None, 51 | //Disable additional AES encryption 52 | preshared_key: None, 53 | //Send a keepalive packet every 21 seconds 54 | keep_alive: Some(21), 55 | //Route all traffic through the WireGuard interface 56 | allowed_ips: vec!["0.0.0.0/0".parse().unwrap()], 57 | //The peer's ip address 58 | endpoint: "1.2.3.4".parse().unwrap(), 59 | }], 60 | }; 61 | 62 | //Set the config our adapter will use 63 | //This lets it know about the peers and keys 64 | adapter.set_config(&interface).unwrap(); 65 | 66 | let internal_ip = "10.4.0.2".parse().unwrap(); 67 | let internal_prefix_length = 24; 68 | let internal_ipnet = ipnet::Ipv4Net::new(internal_ip, internal_prefix_length).unwrap(); 69 | //Set up the routing table with the allowed ips for our peers, 70 | //and assign an ip to the interface 71 | adapter.set_default_route(&[internal_ipnet.into()], &interface).unwrap(); 72 | 73 | //drop(adapter) 74 | //The adapter closes its resources when dropped 75 | ``` 76 | 77 | See `examples/demo_server.rs` that connects to the wireguard demo server 78 | 79 | ## Version compatibility 80 | Wireguard NT versions 0.10 and above are supported. Versions < 0.10 have breaking changes that 81 | make interoperability hard. Please file an issue if this effects your use case. 82 | 83 | 84 | License: MIT -------------------------------------------------------------------------------- /bindgen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | bindgen \ 3 | --allowlist-function "WireGuard.*" \ 4 | --allowlist-type "WIREGUARD_.*" \ 5 | --dynamic-loading wireguard \ 6 | --dynamic-link-require-all \ 7 | wireguard_nt/wireguard_functions.h > src/wireguard_nt_raw.rs 8 | -------------------------------------------------------------------------------- /examples/demo_server.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Read, Write}; 2 | use std::net::{IpAddr, Ipv4Addr, SocketAddr}; 3 | use std::sync::atomic::{AtomicBool, Ordering}; 4 | use std::sync::Arc; 5 | use std::time::{Duration, SystemTime}; 6 | 7 | use ipnet::{Ipv4Net, Ipv6Net}; 8 | use log::*; 9 | 10 | fn main() { 11 | env_logger::init(); 12 | 13 | let private = x25519_dalek::StaticSecret::random(); 14 | let public = x25519_dalek::PublicKey::from(&private); 15 | 16 | let (demo_pub, internal_ip, endpoint) = 17 | get_demo_server_config(public.as_bytes()).expect("Failed to get demo server credentials"); 18 | println!("Connecting to {} - internal ip: {}", endpoint, internal_ip); 19 | 20 | // Must be run as Administrator because we create network adapters 21 | 22 | // Load the wireguard dll file so that we can call the underlying C functions 23 | // Unsafe because we are loading an arbitrary dll file 24 | let wireguard = 25 | unsafe { wireguard_nt::load_from_path("examples/wireguard_nt/bin/amd64/wireguard.dll") } 26 | .expect("Failed to load wireguard dll"); 27 | 28 | // Try to open an adapter from the given pool with the name "Demo" 29 | let adapter = wireguard_nt::Adapter::open(&wireguard, "Demo").unwrap_or_else(|_| { 30 | wireguard_nt::Adapter::create(&wireguard, "WireGuard", "Demo", None) 31 | .expect("Failed to create wireguard adapter!") 32 | }); 33 | let mut interface_private = [0; 32]; 34 | let mut peer_pub = [0; 32]; 35 | 36 | interface_private.copy_from_slice(private.as_bytes()); 37 | peer_pub.copy_from_slice(demo_pub.as_slice()); 38 | 39 | //Only allow traffic going to the demo server to pass through the wireguard interface 40 | let allowed_ip = match endpoint.ip() { 41 | IpAddr::V4(v4) => Ipv4Net::new(v4, 32).unwrap().into(), 42 | IpAddr::V6(v6) => Ipv6Net::new(v6, 128).unwrap().into(), 43 | }; 44 | 45 | let interface = wireguard_nt::SetInterface { 46 | listen_port: None, 47 | public_key: None, 48 | private_key: Some(interface_private), 49 | peers: vec![wireguard_nt::SetPeer { 50 | public_key: Some(peer_pub), 51 | preshared_key: None, 52 | keep_alive: Some(21), 53 | //Uncomment to tunnel all traffic 54 | //allowed_ips: vec!["0.0.0.0/0".parse().unwrap()], 55 | allowed_ips: vec![allowed_ip], //Only tunnel traffic bound for the demo server the wireguard interface 56 | endpoint, 57 | }], 58 | }; 59 | assert!(adapter.set_logging(wireguard_nt::AdapterLoggingLevel::OnWithPrefix)); 60 | 61 | adapter.set_config(&interface).unwrap(); 62 | match adapter.set_default_route(&[Ipv4Net::new(internal_ip, 24).unwrap().into()], &interface) { 63 | Ok(()) => {} 64 | Err(err) => panic!("Failed to set default route: {}", err), 65 | } 66 | assert!(adapter.up().is_ok()); 67 | 68 | // Go to http://demo.wireguard.com/ and see the bandwidth numbers change! 69 | println!("Printing peer bandwidth statistics"); 70 | println!("Press enter to exit"); 71 | let done = Arc::new(AtomicBool::new(false)); 72 | let done2 = Arc::clone(&done); 73 | let thread = std::thread::spawn(move || 'outer: loop { 74 | let stats = adapter.get_config(); 75 | for peer in stats.peers { 76 | let handshake_age = peer 77 | .last_handshake 78 | .map(|h| SystemTime::now().duration_since(h).unwrap_or_default()); 79 | let handshake_msg = match handshake_age { 80 | Some(age) => format!("handshake performed {:.2}s ago", age.as_secs_f32()), 81 | None => "no active handshake".to_string(), 82 | }; 83 | 84 | println!( 85 | " {:?}, {} bytes up, {} bytes down, {handshake_msg}", 86 | peer.allowed_ips, peer.tx_bytes, peer.rx_bytes 87 | ); 88 | } 89 | for _ in 0..10 { 90 | if done2.load(Ordering::Relaxed) { 91 | break 'outer; 92 | } 93 | std::thread::sleep(Duration::from_millis(100)); 94 | } 95 | }); 96 | 97 | let mut _buf = [0u8; 32]; 98 | let _ = std::io::stdin().read(&mut _buf); 99 | 100 | done.store(true, Ordering::Relaxed); 101 | thread.join().unwrap(); 102 | println!("Exiting!"); 103 | } 104 | 105 | /// Gets info from the demo server that can be used to connect. 106 | /// pub_key is a 32 byte public key that corresponds to the private key that the caller has 107 | fn get_demo_server_config(pub_key: &[u8]) -> Result<(Vec, Ipv4Addr, SocketAddr), String> { 108 | use std::net::{TcpStream, ToSocketAddrs}; 109 | let addrs: Vec = "demo.wireguard.com:42912" 110 | .to_socket_addrs() 111 | .unwrap() 112 | .collect(); 113 | 114 | let mut s: TcpStream = TcpStream::connect_timeout( 115 | addrs.first().expect("Failed to resolve demo server DNS"), 116 | Duration::from_secs(5), 117 | ) 118 | .expect("Failed to open connection to demo server"); 119 | 120 | let mut encoded = base64::encode(pub_key); 121 | encoded.push('\n'); 122 | s.write_all(encoded.as_bytes()) 123 | .expect("Failed to write public key to server"); 124 | 125 | let mut bytes = [0u8; 512]; 126 | let len = s.read(&mut bytes).expect("Failed to read from demo server"); 127 | let reply = &std::str::from_utf8(&bytes).unwrap()[..len].trim(); 128 | info!("Demo server gave: {}", reply); 129 | 130 | if !reply.starts_with("OK") { 131 | return Err(format!("Demo Server returned error {}", reply)); 132 | } 133 | let parts: Vec<&str> = reply.split(':').collect(); 134 | if parts.len() != 4 { 135 | return Err(format!( 136 | "Demo Server returned wrong number of parts. Expected 4 got: {:?}", 137 | parts 138 | )); 139 | } 140 | let peer_pub = base64::decode(parts[1]) 141 | .map_err(|e| format!("Demo server gave invalid public key: {}", e))?; 142 | 143 | let endpoint_port: u16 = parts[2] 144 | .parse() 145 | .map_err(|e| format!("Demo server gave invalid port number: {}", e))?; 146 | 147 | let internal_ip = parts[3]; 148 | let internal_ip: Ipv4Addr = internal_ip.parse().unwrap(); 149 | 150 | Ok(( 151 | peer_pub, 152 | internal_ip, 153 | SocketAddr::new(addrs[0].ip(), endpoint_port), 154 | )) 155 | } 156 | -------------------------------------------------------------------------------- /examples/wireguard_nt/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Prebuilt Binaries License 2 | ------------------------- 3 | 4 | 1. DEFINITIONS. "Software" means the precise contents of the "wireguard.dll" 5 | files that are included in the .zip file that contains this document as 6 | downloaded from download.wireguard.com. 7 | 8 | 2. LICENSE GRANT. WireGuard LLC grants to you a non-exclusive and 9 | non-transferable right to use Software for lawful purposes under certain 10 | obligations and limited rights as set forth in this agreement. 11 | 12 | 3. RESTRICTIONS. Software is owned and copyrighted by WireGuard LLC. It is 13 | licensed, not sold. Title to Software and all associated intellectual 14 | property rights are retained by WireGuard. You must not: 15 | a. reverse engineer, decompile, disassemble, extract from, or otherwise 16 | modify the Software; 17 | b. modify or create derivative work based upon Software in whole or in 18 | parts, except insofar as only the API interfaces of the "wireguard.h" file 19 | distributed alongside the Software (the "Permitted API") are used; 20 | c. remove any proprietary notices, labels, or copyrights from the Software; 21 | d. resell, redistribute, lease, rent, transfer, sublicense, or otherwise 22 | transfer rights of the Software without the prior written consent of 23 | WireGuard LLC, except insofar as the Software is distributed alongside 24 | other software that uses the Software only via the Permitted API; 25 | e. use the name of WireGuard LLC, the WireGuard project, the WireGuard 26 | project, or the names of its contributors to endorse or promote products 27 | derived from the Software without specific prior written consent. 28 | 29 | 4. LIMITED WARRANTY. THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF 30 | ANY KIND. WIREGUARD LLC HEREBY EXCLUDES AND DISCLAIMS ALL IMPLIED OR 31 | STATUTORY WARRANTIES, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS 32 | FOR A PARTICULAR PURPOSE, QUALITY, NON-INFRINGEMENT, TITLE, RESULTS, 33 | EFFORTS, OR QUIET ENJOYMENT. THERE IS NO WARRANTY THAT THE PRODUCT WILL BE 34 | ERROR-FREE OR WILL FUNCTION WITHOUT INTERRUPTION. YOU ASSUME THE ENTIRE 35 | RISK FOR THE RESULTS OBTAINED USING THE PRODUCT. TO THE EXTENT THAT 36 | WIREGUARD LLC MAY NOT DISCLAIM ANY WARRANTY AS A MATTER OF APPLICABLE LAW, 37 | THE SCOPE AND DURATION OF SUCH WARRANTY WILL BE THE MINIMUM PERMITTED UNDER 38 | SUCH LAW. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 39 | WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR 40 | A PARTICULAR PURPOSE OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE 41 | EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. 42 | 43 | 5. LIMITATION OF LIABILITY. To the extent not prohibited by law, in no event 44 | WireGuard LLC or any third-party-developer will be liable for any lost 45 | revenue, profit or data or for special, indirect, consequential, incidental 46 | or punitive damages, however caused regardless of the theory of liability, 47 | arising out of or related to the use of or inability to use Software, even 48 | if WireGuard LLC has been advised of the possibility of such damages. 49 | Solely you are responsible for determining the appropriateness of using 50 | Software and accept full responsibility for all risks associated with its 51 | exercise of rights under this agreement, including but not limited to the 52 | risks and costs of program errors, compliance with applicable laws, damage 53 | to or loss of data, programs or equipment, and unavailability or 54 | interruption of operations. The foregoing limitations will apply even if 55 | the above stated warranty fails of its essential purpose. You acknowledge, 56 | that it is in the nature of software that software is complex and not 57 | completely free of errors. In no event shall WireGuard LLC or any 58 | third-party-developer be liable to you under any theory for any damages 59 | suffered by you or any user of Software or for any special, incidental, 60 | indirect, consequential or similar damages (including without limitation 61 | damages for loss of business profits, business interruption, loss of 62 | business information or any other pecuniary loss) arising out of the use or 63 | inability to use Software, even if WireGuard LLC has been advised of the 64 | possibility of such damages and regardless of the legal or quitable theory 65 | (contract, tort, or otherwise) upon which the claim is based. 66 | 67 | 6. TERMINATION. This agreement is affected until terminated. You may 68 | terminate this agreement at any time. This agreement will terminate 69 | immediately without notice from WireGuard LLC if you fail to comply with 70 | the terms and conditions of this agreement. Upon termination, you must 71 | delete Software and all copies of Software and cease all forms of 72 | distribution of Software. 73 | 74 | 7. SEVERABILITY. If any provision of this agreement is held to be 75 | unenforceable, this agreement will remain in effect with the provision 76 | omitted, unless omission would frustrate the intent of the parties, in 77 | which case this agreement will immediately terminate. 78 | 79 | 8. RESERVATION OF RIGHTS. All rights not expressly granted in this agreement 80 | are reserved by WireGuard LLC. For example, WireGuard LLC reserves the 81 | right at any time to cease development of Software, to alter distribution 82 | details, features, specifications, capabilities, functions, licensing 83 | terms, release dates, APIs, ABIs, general availability, or other 84 | characteristics of the Software. 85 | -------------------------------------------------------------------------------- /examples/wireguard_nt/README.md: -------------------------------------------------------------------------------- 1 | # [WireGuard](https://www.wireguard.com/) for the NT Kernel 2 | ### High performance in-kernel WireGuard implementation for Windows 3 | 4 | WireGuardNT is an implementation of WireGuard, for the NT Kernel as used in Windows 7, 8, 8.1, 10, and 11, supporting AMD64, x86, ARM64, and ARM processors. 5 | 6 | #### Not the droids you're looking for 7 | 8 | **If you've come here looking to run [WireGuard on Windows](https://git.zx2c4.com/wireguard-windows/about/), you're in the wrong place. Instead, head on over to the [WireGuard Download Page](https://www.wireguard.com/install/) to download the WireGuard application.** Alternatively, if you've come here looking to embed WireGuard into your Windows program, **you are still in the wrong place**. Instead, head on over to the [embeddable DLL service project](https://git.zx2c4.com/wireguard-windows/about/embeddable-dll-service/README.md), to get everything you need to bake WireGuard into your Windows programs. These projects use WireGuardNT inside. 9 | 10 | ## Usage 11 | 12 | #### Download 13 | 14 | WireGuardNT is deployed as a platform-specific `wireguard.dll` file. Install the `wireguard.dll` file side-by-side with your application. Download the dll from [the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/), alongside the header file for your application described below. 15 | 16 | #### API 17 | 18 | Include the [`wireguard.h` file](https://git.zx2c4.com/wireguard-nt/tree/api/wireguard.h) in your project simply by copying it there and dynamically load the `wireguard.dll` using [`LoadLibraryEx()`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa) and [`GetProcAddress()`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress) to resolve each function, using the typedefs provided in the header file. The [`InitializeWireGuardNT` function in the example.c code](https://git.zx2c4.com/wireguard-nt/tree/example/example.c) provides this in a function that you can simply copy and paste. 19 | 20 | With the library setup, WireGuardNT can then be used by first creating an adapter, configuring it, and then setting its status to "up". Adapters have names (e.g. "OfficeNet") and types (e.g. "WireGuard"). 21 | 22 | ```C 23 | WIREGUARD_ADAPTER_HANDLE Adapter1 = WireGuardCreateAdapter(L"OfficeNet", L"WireGuard", &SomeFixedGUID1); 24 | WIREGUARD_ADAPTER_HANDLE Adapter2 = WireGuardCreateAdapter(L"HomeNet", L"WireGuard", &SomeFixedGUID2); 25 | WIREGUARD_ADAPTER_HANDLE Adapter3 = WireGuardCreateAdapter(L"Data Center", L"WireGuard", &SomeFixedGUID3); 26 | ``` 27 | 28 | After creating an adapter, we can use it by setting a configuration and setting its status to "up": 29 | 30 | ```C 31 | struct 32 | { 33 | WIREGUARD_INTERFACE Interface; 34 | WIREGUARD_PEER FirstPeer; 35 | WIREGUARD_ALLOWED_IP FirstPeerAllowedIP1; 36 | WIREGUARD_ALLOWED_IP FirstPeerAllowedIP2; 37 | WIREGUARD_PEER SecondPeer; 38 | WIREGUARD_ALLOWED_IP SecondtPeerAllowedIP1; 39 | } Config = { 40 | .Interface = { 41 | .Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY, 42 | .PrivateKey = ..., 43 | .PeersCount = 2 44 | }, 45 | .FirstPeer = { 46 | .Flags = WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_ENDPOINT, 47 | .PublicKey = ..., 48 | .Endpoint = ..., 49 | .AllowedIPsCount = 2 50 | }, 51 | .FirstPeerAllowedIP1 = { ... }, 52 | ... 53 | }; 54 | WireGuardSetConfiguration(Adapter1, &Config.Interface, sizeof(Config)); 55 | WireGuardSetAdapterState(Adapter1, WIREGUARD_ADAPTER_STATE_UP); 56 | ``` 57 | 58 | You are *highly encouraged* to read the [**example.c short example**](https://git.zx2c4.com/wireguard-nt/tree/example/example.c) to see how to put together a simple network tunnel. The example one connects to the [demo server](https://demo.wireguard.com/). 59 | 60 | The various functions and definitions are [documented in `wireguard.h`](https://git.zx2c4.com/wireguard-nt/tree/api/wireguard.h) as well as in the reference below. 61 | 62 | ## API Reference 63 | 64 | ### Type: `WIREGUARD_ADAPTER_HANDLE` - opaque type to an instance of a WireGuard adapter. 65 | 66 | ### Function: `WireGuardCreateAdapter` - creates a new adapter. 67 | 68 | ```c 69 | WIREGUARD_ADAPTER_HANDLE WireGuardCreateAdapter(LPCWSTR Name, LPCWSTR TunnelType, const GUID *RequestedGUID); 70 | ``` 71 | 72 | Typedef'd as `WIREGUARD_CREATE_ADAPTER_FUNC`. Returns a `WIREGUARD_ADAPTER_HANDLE` if successful, which must be released with `WireGuardCloseAdapter`; otherwise returns `NULL` and sets LastError. 73 | 74 | #### Parameters 75 | |Type|Name|Description| 76 | |--|--|--| 77 | |`LPCWSTR`|Name|The requested name of the adapter. Zero-terminated string of up to `MAX_ADAPTER_NAME-1` characters.| 78 | |`LPCWSTR`|TunnelType|Name of the adapter tunnel type. Zero-terminated string of up to `MAX_ADAPTER_NAME-1` characters.| 79 | |`GUID *`|RequestedGUID|The GUID of the created network adapter, which then influences NLA generation deterministically. If it is set to `NULL`, the GUID is chosen by the system at random, and hence a new NLA entry is created for each new adapter.| 80 | 81 | ### Function: `WireGuardOpenAdapter` - opens an existing adapter. 82 | 83 | ```c 84 | WIREGUARD_ADAPTER_HANDLE WireGuardOpenAdapter(LPCWSTR Name); 85 | ``` 86 | 87 | Typedef'd as `WIREGUARD_OPEN_ADAPTER_FUNC`. Returns a `WIREGUARD_ADAPTER_HANDLE` if successful, which must be released with `WireGuardCloseAdapter`; otherwise returns `NULL` and sets LastError. 88 | 89 | #### Parameters 90 | |Type|Name|Description| 91 | |--|--|--| 92 | |`LPCWSTR`|Name|The requested name of the adapter. Zero-terminated string of up to `MAX_ADAPTER_NAME-1` characters.| 93 | 94 | ### Function: `WireGuardCloseAdapter` - closes an open adapter and releases its resources. 95 | 96 | ```c 97 | VOID WireGuardCloseAdapter(WIREGUARD_ADAPTER_HANDLE Adapter); 98 | ``` 99 | 100 | Typedef'd as `WIREGUARD_CLOSE_ADAPTER_FUNC`. Releases WireGuard adapter resources and, if adapter was created with `WireGuardCreateAdapter`, removes adapter. 101 | 102 | #### Parameters 103 | |Type|Name|Description| 104 | |--|--|--| 105 | |`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.| 106 | 107 | ### Function: `WireGuardGetAdapterLUID` - gets the LUID of an adapter. 108 | 109 | ```c 110 | VOID WireGuardGetAdapterLUID(WIREGUARD_ADAPTER_HANDLE Adapter, NET_LUID *Luid); 111 | ``` 112 | 113 | Typedef'd as `WIREGUARD_GET_ADAPTER_LUID_FUNC`. Returns the LUID of the adapter into the variable passed as the `Luid` argument. 114 | 115 | #### Parameters 116 | |Type|Name|Description| 117 | |--|--|--| 118 | |`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.| 119 | |`NET_LUID *` (out)|Luid|Pointer to receive adapter LUID.| 120 | 121 | ### Function: `WireGuardGetRunningDriverVersion` - gets the version of the loaded driver. 122 | 123 | ```c 124 | DWORD WireGuardGetRunningDriverVersion(VOID); 125 | ``` 126 | 127 | Typedef'd as `WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC`. Returns the version of the WireGuardNT driver currently loaded, or zero on error and sets LastError, which is `ERROR_FILE_NOT_FOUND` if WireGuardNT is not currently loaded. 128 | 129 | ### Function: `WireGuardDeleteDriver` - deletes driver if not in use. 130 | 131 | ```c 132 | BOOL WireGuardDeleteDriver(VOID); 133 | ``` 134 | 135 | Typedef'd as `WIREGUARD_DELETE_DRIVER_FUNC`. Deletes the WireGuardNT driver if there are no more adapters in use, and returns `TRUE` if successful, or returns `FALSE` if not and sets LastError. 136 | 137 | ### Enumeration: `WIREGUARD_LOGGER_LEVEL` - determines level of logging. 138 | 139 | |Name|Description| 140 | |--|--| 141 | |`WIREGUARD_LOG_INFO`|Informational| 142 | |`WIREGUARD_LOG_WARN`|Warning| 143 | |`WIREGUARD_LOG_ERR`|Error| 144 | 145 | ### Callback type: `WIREGUARD_LOGGER_CALLBACK` - called for each log message. 146 | 147 | ```c 148 | VOID WireGuardLoggerCallback(WIREGUARD_LOGGER_LEVEL Level, DWORD64 Timestamp, LPCWSTR Message); 149 | ``` 150 | 151 | Typedef'd as `WIREGUARD_LOGGER_CALLBACK`. Called by the library on each log message. 152 | 153 | #### Parameters 154 | |Type|Name|Description| 155 | |--|--|--| 156 | |`WIREGUARD_LOGGER_LEVEL`|Level|Message level.| 157 | |`DWORD64`|Timestamp|Message timestamp in in 100ns intervals since 1601-01-01 UTC.| 158 | |`LPCWSTR`|Message|Message text.| 159 | 160 | ### Function: `WireGuardSetLogger` - registers logger callback function. 161 | 162 | ```c 163 | VOID WireGuardSetLogger(WIREGUARD_LOGGER_CALLBACK NewLogger); 164 | ``` 165 | 166 | Typedef'd as `WIREGUAR_SET_LOGGER_FUNC`. After registration, the callback may be called concurrently by multiple threads. It is up to the supplied callback function, `NewLogger`, to handle synchronization. If `NewLogger` is `NULL`, logging is disabled. 167 | 168 | #### Parameters 169 | |Type|Name|Description| 170 | |--|--|--| 171 | |`WIREGUARD_LOGGER_CALLBACK`|NewLogger|Pointer to callback function to use as a new global logger.| 172 | 173 | ### Enumeration: `WIREGUARD_ADAPTER_LOG_STATE` - determines adapter log generation. 174 | 175 | |Name|Description| 176 | |--|--| 177 | |`WIREGUARD_ADAPTER_LOG_OFF`|No logs are generated from the driver.| 178 | |`WIREGUARD_ADAPTER_LOG_ON`|Logs are generated from the driver.| 179 | |`WIREGUARD_ADAPTER_LOG_ON_WITH_PREFIX`|Logs are generated from the driver, adapter index-prefixed.| 180 | 181 | ### Function: `WireGuardSetAdapterLogging` - sets whether adapter logs are generated. 182 | 183 | ```c 184 | BOOL WireGuardSetAdapterLogging(WIREGUARD_ADAPTER_HANDLE Adapter, WIREGUARD_ADAPTER_LOG_STATE LogState); 185 | ``` 186 | 187 | Typedef'd as `WIREGUARD_SET_ADAPTER_LOGGING`. Sets whether and how the specified adapter logs to the logger previously set by `WireGuardSetLogger`. Returns `TRUE` if successful, or returns `FALSE` if not and sets LastError. 188 | 189 | #### Parameters 190 | |Type|Name|Description| 191 | |--|--|--| 192 | |`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.| 193 | |`WIREGUARD_ADAPTER_LOG_STATE`|LogState|Adapter logging state.| 194 | 195 | ### Enumeration: `WIREGUARD_ADAPTER_STATE` - determines adapter state. 196 | 197 | |Name|Description| 198 | |--|--| 199 | |`WIREGUARD_ADAPTER_STATE_DOWN`|Down| 200 | |`WIREGUARD_ADAPTER_STATE_UP`|Up| 201 | 202 | ### Function: `WireGuardSetAdapterState` - sets state of adapter. 203 | 204 | ```c 205 | BOOL WireGuardSetAdapterState(WIREGUARD_ADAPTER_HANDLE Adapter, WIREGUARD_ADAPTER_STATE State); 206 | ``` 207 | 208 | Typedef'd as `WIREGUARD_SET_ADAPTER_STATE`. Sets the specified adapter up or down. Note that sockets used by the specified adapter are owned by the process that sets the adapter up. Returns `TRUE` if successful, or returns `FALSE` if not and sets LastError. 209 | 210 | #### Parameters 211 | |Type|Name|Description| 212 | |--|--|--| 213 | |`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.| 214 | |`WIREGUARD_ADAPTER_STATE`|State|Adapter state.| 215 | 216 | ### Function: `WireGuardGetAdapterState` - gets state of adapter. 217 | 218 | ```c 219 | BOOL WireGuardGetAdapterState(WIREGUARD_ADAPTER_HANDLE Adapter, WIREGUARD_ADAPTER_STATE *State); 220 | ``` 221 | 222 | Typedef'd as `WIREGUARD_GET_ADAPTER_STATE`. Gets whether the specified adapter is up or down. Returns `TRUE` if successful, or returns `FALSE` if not and sets LastError. 223 | 224 | #### Parameters 225 | |Type|Name|Description| 226 | |--|--|--| 227 | |`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.| 228 | |`WIREGUARD_ADAPTER_STATE` (out)|State|Pointer to adapter state.| 229 | 230 | ### Structure: `WIREGUARD_INTERFACE` - an interface. 231 | 232 | |Type|Name|Description| 233 | |--|--|--| 234 | |`WIREGUARD_INTERFACE_FLAG`|Flags|Bitwise combination of flags.| 235 | |`WORD`|ListenPort|Port for UDP listen socket, or 0 to choose randomly.| 236 | |`BYTE[WIREGUARD_KEY_LENGTH]`|PrivateKey|Private key of interface.| 237 | |`BYTE[WIREGUARD_KEY_LENGTH]`|PublicKey|Corresponding public key of private key (unused on set).| 238 | |`DWORD`|PeersCount|Number of peer structures following this structure.| 239 | 240 | ### Structure: `WIREGUARD_PEER` - a peer. 241 | 242 | |Type|Name|Description| 243 | |--|--|--| 244 | |`WIREGUARD_PEER_FLAG`|Flags|Bitwise combination of flags.| 245 | |`DWORD`|Reserved|Reserved; must be zero.| 246 | |`BYTE[WIREGUARD_KEY_LENGTH]`|PublicKey|Public key, the peer's primary identifier.| 247 | |`BYTE[WIREGUARD_KEY_LENGTH]`|PresharedKey|Preshared key for additional layer of post-quantum resistance.| 248 | |`WORD`|PersistentKeepalive|Persistent keep-alive seconds interval, or 0 to disable.| 249 | |`SOCKADDR_INET`|Endpoint|Endpoint, with IP address and UDP port number.| 250 | |`DWORD64`|TxBytes|Number of bytes transmitted (unused on set).| 251 | |`DWORD64`|RxBytes|Number of bytes received (unused on set).| 252 | |`DWORD64`|LastHandshake|Time of the last handshake, in 100ns intervals since 1601-01-01 UTC (unused on set).| 253 | |`DWORD`|AllowedIPsCount|Number of allowed IP structures following this structure.| 254 | 255 | ### Structure: `WIREGUARD_ALLOWED_IP` - an IP network range. 256 | 257 | |Type|Name|Description| 258 | |--|--|--| 259 | |Union|Address|IP address; the `V4` member is a `IN_ADDR` and the `V6` member is a `IN6_ADDR`.| 260 | |`ADDRESS_FAMILY`|AddressFamily|Address family, either `AF_INET` or `AF_INET6`.| 261 | |`BYTE`|Cidr|The CIDR of the address range.| 262 | 263 | ### Constant: `WIREGUARD_KEY_LENGTH` - the length of a key. 264 | 265 | All WireGuard keys -- public, private, or pre-shared -- are 32 bytes in length. 266 | 267 | ### Enumeration: `WIREGUARD_INTERFACE_FLAG` - bitwise flags for interfaces. 268 | 269 | These values may be or'd together. 270 | 271 | |Name|Description| 272 | |--|--| 273 | |`WIREGUARD_INTERFACE_HAS_PUBLIC_KEY`|The PublicKey field is set (unused on set).| 274 | |`WIREGUARD_INTERFACE_HAS_PRIVATE_KEY`|The PrivateKey field is set.| 275 | |`WIREGUARD_INTERFACE_HAS_LISTEN_PORT`|The ListenPort field is set.| 276 | |`WIREGUARD_INTERFACE_REPLACE_PEERS`|Remove all peers before adding new ones (unused on get).| 277 | 278 | ### Enumeration: `WIREGUARD_PEER_FLAG` - bitwise flags for peers. 279 | 280 | These values may be or'd together. 281 | 282 | |Name|Description| 283 | |--|--| 284 | |`WIREGUARD_PEER_HAS_PUBLIC_KEY`|The PublicKey field is set.| 285 | |`WIREGUARD_PEER_HAS_PRESHARED_KEY`|The PresharedKey field is set.| 286 | |`WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE`|The PersistentKeepAlive field is set.| 287 | |`WIREGUARD_PEER_HAS_ENDPOINT`|The Endpoint field is set.| 288 | |`WIREGUARD_PEER_REPLACE_ALLOWED_IPS`|Remove all allowed IPs before adding new ones (unused on get).| 289 | |`WIREGUARD_PEER_REMOVE`|Remove specified peer (unused on get).| 290 | |`WIREGUARD_PEER_UPDATE`|Do not add a new peer (unused on get).| 291 | 292 | ### Function: `WireGuardSetConfiguration` - sets configuration of adapter. 293 | 294 | ```c 295 | BOOL WireGuardSetConfiguration(WIREGUARD_ADAPTER_HANDLE Adapter, const WIREGUARD_INTERFACE *Config, DWORD Bytes); 296 | ``` 297 | 298 | Typedef'd as `WIREGUARD_SET_CONFIGURATION`. Sets the configuration of the specified adapter. The `Config` argument represents a `WIREGUARD_INTERFACE` structure, immediately followed in memory by zero or more `WIREGUARD_PEER` or `WIREGUARD_ALLOWED_IP` structures. Returns `TRUE` if successful, or returns `FALSE` if not and sets LastError. 299 | 300 | #### Parameters 301 | |Type|Name|Description| 302 | |--|--|--| 303 | |`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.| 304 | |`WIREGUARD_INTERFACE *`|Config|Adapter configuration.| 305 | |`DWORD`|Bytes|Number of bytes of `Config` allocation.| 306 | 307 | 308 | ### Function: `WireGuardGetConfiguration` - gets configuration of adapter. 309 | 310 | ```c 311 | BOOL WireGuardGetConfiguration(WIREGUARD_ADAPTER_HANDLE Adapter, WIREGUARD_INTERFACE *Config, DWORD *Bytes); 312 | ``` 313 | 314 | Typedef'd as `WIREGUARD_GET_CONFIGURATION`. Gets the configuration of the specified adapter. The `Config` argument represents a `WIREGUARD_INTERFACE` structure, immediately followed in memory by zero or more `WIREGUARD_PEER` or `WIREGUARD_ALLOWED_IP` structures. Returns `TRUE` if successful, or returns `FALSE` if not and sets LastError. If LastError is `ERROR_MORE_DATA`, `Bytes` is updated with the number of bytes needed for successful operation. Since that byte value can change, this function should be called in a tight loop until success or until the error is not `ERROR_MORE_DATA`. 315 | 316 | #### Parameters 317 | |Type|Name|Description| 318 | |--|--|--| 319 | |`WIREGUARD_ADAPTER_HANDLE`|Adapter|Adapter handle obtained with `WireGuardCreateAdapter` or `WireGuardOpenAdapter`.| 320 | |`WIREGUARD_INTERFACE *` (out)|Config|Adapter configuration.| 321 | |`DWORD *` (in/out)|Bytes|Pointer to number of bytes of `Config` allocation, on input, and is updated when the function returns to the amount of bytes required.| 322 | 323 | ## Building 324 | 325 | **Do not distribute drivers or files named "WireGuard" or "wireguard" or similar, as they will most certainly clash with official deployments. Instead distribute [`wireguard.dll` as downloaded from the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/).** 326 | 327 | General requirements: 328 | 329 | - [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) with Windows SDK 330 | - [Windows Driver Kit](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk) 331 | 332 | `wireguard-nt.sln` may be opened in Visual Studio for development and building. Be sure to run `bcdedit /set testsigning on` and then reboot before to enable unsigned driver loading. The default run sequence (F5) in Visual Studio will build the example project and its dependencies. 333 | 334 | ## License 335 | 336 | The entire contents of [this repository](https://git.zx2c4.com/wireguard-nt/), including all documentation and example code, is "Copyright © 2018-2021 WireGuard LLC. All Rights Reserved." Source code is licensed under the [GPLv2](COPYING). Prebuilt binaries from [the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/) are released under a more permissive license suitable for more forms of software contained inside of the .zip files distributed there. 337 | -------------------------------------------------------------------------------- /examples/wireguard_nt/bin/amd64/wireguard.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nulldotblack/wireguard-nt/3e24a3a7d6f8040117c113d76e185447b931f176/examples/wireguard_nt/bin/amd64/wireguard.dll -------------------------------------------------------------------------------- /examples/wireguard_nt/bin/arm/wireguard.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nulldotblack/wireguard-nt/3e24a3a7d6f8040117c113d76e185447b931f176/examples/wireguard_nt/bin/arm/wireguard.dll -------------------------------------------------------------------------------- /examples/wireguard_nt/bin/arm64/wireguard.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nulldotblack/wireguard-nt/3e24a3a7d6f8040117c113d76e185447b931f176/examples/wireguard_nt/bin/arm64/wireguard.dll -------------------------------------------------------------------------------- /examples/wireguard_nt/bin/x86/wireguard.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nulldotblack/wireguard-nt/3e24a3a7d6f8040117c113d76e185447b931f176/examples/wireguard_nt/bin/x86/wireguard.dll -------------------------------------------------------------------------------- /examples/wireguard_nt/include/wireguard.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT 2 | * 3 | * Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved. 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #ifndef ALIGNED 19 | # if defined(_MSC_VER) 20 | # define ALIGNED(n) __declspec(align(n)) 21 | # elif defined(__GNUC__) 22 | # define ALIGNED(n) __attribute__((aligned(n))) 23 | # else 24 | # error "Unable to define ALIGNED" 25 | # endif 26 | #endif 27 | 28 | /* MinGW is missing this one, unfortunately. */ 29 | #ifndef _Post_maybenull_ 30 | # define _Post_maybenull_ 31 | #endif 32 | 33 | #pragma warning(push) 34 | #pragma warning(disable : 4324) /* structure was padded due to alignment specifier */ 35 | 36 | /** 37 | * A handle representing WireGuard adapter 38 | */ 39 | typedef struct _WIREGUARD_ADAPTER *WIREGUARD_ADAPTER_HANDLE; 40 | 41 | /** 42 | * Creates a new WireGuard adapter. 43 | * 44 | * @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1 45 | * characters. 46 | * 47 | * @param TunnelType Name of the adapter tunnel type. Zero-terminated string of up to MAX_ADAPTER_NAME-1 48 | * characters. 49 | * 50 | * @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation deterministically. 51 | * If it is set to NULL, the GUID is chosen by the system at random, and hence a new NLA entry is 52 | * created for each new adapter. It is called "requested" GUID because the API it uses is 53 | * completely undocumented, and so there could be minor interesting complications with its usage. 54 | * 55 | * @return If the function succeeds, the return value is the adapter handle. Must be released with 56 | * WireGuardCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call 57 | * GetLastError. 58 | */ 59 | typedef _Must_inspect_result_ 60 | _Return_type_success_(return != NULL) 61 | _Post_maybenull_ 62 | WIREGUARD_ADAPTER_HANDLE(WINAPI WIREGUARD_CREATE_ADAPTER_FUNC) 63 | (_In_z_ LPCWSTR Name, _In_z_ LPCWSTR TunnelType, _In_opt_ const GUID *RequestedGUID); 64 | 65 | /** 66 | * Opens an existing WireGuard adapter. 67 | * 68 | * @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1 69 | * characters. 70 | * 71 | * @return If the function succeeds, the return value is the adapter handle. Must be released with 72 | * WireGuardCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call 73 | * GetLastError. 74 | */ 75 | typedef _Must_inspect_result_ 76 | _Return_type_success_(return != NULL) 77 | _Post_maybenull_ 78 | WIREGUARD_ADAPTER_HANDLE(WINAPI WIREGUARD_OPEN_ADAPTER_FUNC)(_In_z_ LPCWSTR Name); 79 | 80 | /** 81 | * Releases WireGuard adapter resources and, if adapter was created with WireGuardCreateAdapter, removes adapter. 82 | * 83 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter. 84 | */ 85 | typedef VOID(WINAPI WIREGUARD_CLOSE_ADAPTER_FUNC)(_In_opt_ WIREGUARD_ADAPTER_HANDLE Adapter); 86 | 87 | /** 88 | * Deletes the WireGuard driver if there are no more adapters in use. 89 | * 90 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 91 | * get extended error information, call GetLastError. 92 | */ 93 | typedef _Return_type_success_(return != FALSE) 94 | BOOL(WINAPI WIREGUARD_DELETE_DRIVER_FUNC)(VOID); 95 | 96 | /** 97 | * Returns the LUID of the adapter. 98 | * 99 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 100 | * 101 | * @param Luid Pointer to LUID to receive adapter LUID. 102 | */ 103 | typedef VOID(WINAPI WIREGUARD_GET_ADAPTER_LUID_FUNC)(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid); 104 | 105 | /** 106 | * Determines the version of the WireGuard driver currently loaded. 107 | * 108 | * @return If the function succeeds, the return value is the version number. If the function fails, the return value is 109 | * zero. To get extended error information, call GetLastError. Possible errors include the following: 110 | * ERROR_FILE_NOT_FOUND WireGuard not loaded 111 | */ 112 | typedef _Return_type_success_(return != 0) 113 | DWORD(WINAPI WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC)(VOID); 114 | 115 | /** 116 | * Determines the level of logging, passed to WIREGUARD_LOGGER_CALLBACK. 117 | */ 118 | typedef enum 119 | { 120 | WIREGUARD_LOG_INFO, /**< Informational */ 121 | WIREGUARD_LOG_WARN, /**< Warning */ 122 | WIREGUARD_LOG_ERR /**< Error */ 123 | } WIREGUARD_LOGGER_LEVEL; 124 | 125 | /** 126 | * Called by internal logger to report diagnostic messages 127 | * 128 | * @param Level Message level. 129 | * 130 | * @param Timestamp Message timestamp in in 100ns intervals since 1601-01-01 UTC. 131 | * 132 | * @param Message Message text. 133 | */ 134 | typedef VOID(CALLBACK *WIREGUARD_LOGGER_CALLBACK)( 135 | _In_ WIREGUARD_LOGGER_LEVEL Level, 136 | _In_ DWORD64 Timestamp, 137 | _In_z_ LPCWSTR Message); 138 | 139 | /** 140 | * Sets logger callback function. 141 | * 142 | * @param NewLogger Pointer to callback function to use as a new global logger. NewLogger may be called from various 143 | * threads concurrently. Should the logging require serialization, you must handle serialization in 144 | * NewLogger. Set to NULL to disable. 145 | */ 146 | typedef VOID(WINAPI WIREGUARD_SET_LOGGER_FUNC)(_In_ WIREGUARD_LOGGER_CALLBACK NewLogger); 147 | 148 | /** 149 | * Whether and how logs from the driver are collected for the callback function. 150 | */ 151 | typedef enum 152 | { 153 | WIREGUARD_ADAPTER_LOG_OFF, /**< No logs are generated from the driver. */ 154 | WIREGUARD_ADAPTER_LOG_ON, /**< Logs are generated from the driver. */ 155 | WIREGUARD_ADAPTER_LOG_ON_WITH_PREFIX /**< Logs are generated from the driver, index-prefixed. */ 156 | } WIREGUARD_ADAPTER_LOG_STATE; 157 | 158 | /** 159 | * Sets whether and how the adapter logs to the logger previously set up with WireGuardSetLogger. 160 | * 161 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 162 | * 163 | * @param LogState Adapter logging state. 164 | * 165 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 166 | * get extended error information, call GetLastError. 167 | */ 168 | typedef _Return_type_success_(return != FALSE) 169 | BOOL(WINAPI WIREGUARD_SET_ADAPTER_LOGGING_FUNC) 170 | (_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_ WIREGUARD_ADAPTER_LOG_STATE LogState); 171 | 172 | /** 173 | * Determines the state of the adapter. 174 | */ 175 | typedef enum 176 | { 177 | WIREGUARD_ADAPTER_STATE_DOWN, /**< Down */ 178 | WIREGUARD_ADAPTER_STATE_UP, /**< Up */ 179 | } WIREGUARD_ADAPTER_STATE; 180 | 181 | /** 182 | * Sets the adapter state of the WireGuard adapter. Note: sockets are owned by the process that sets the state to up. 183 | * 184 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 185 | * 186 | * @param State Adapter state. 187 | * 188 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 189 | * get extended error information, call GetLastError. 190 | */ 191 | typedef _Return_type_success_(return != FALSE) 192 | BOOL(WINAPI WIREGUARD_SET_ADAPTER_STATE_FUNC) 193 | (_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_ WIREGUARD_ADAPTER_STATE State); 194 | 195 | /** 196 | * Gets the adapter state of the WireGuard adapter. 197 | * 198 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 199 | * 200 | * @param State Pointer to adapter state. 201 | * 202 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 203 | * get extended error information, call GetLastError. 204 | */ 205 | typedef _Must_inspect_result_ 206 | _Return_type_success_(return != FALSE) 207 | BOOL(WINAPI WIREGUARD_GET_ADAPTER_STATE_FUNC) 208 | (_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _Out_ WIREGUARD_ADAPTER_STATE *State); 209 | 210 | #define WIREGUARD_KEY_LENGTH 32 211 | 212 | typedef struct _WIREGUARD_ALLOWED_IP WIREGUARD_ALLOWED_IP; 213 | struct ALIGNED(8) _WIREGUARD_ALLOWED_IP 214 | { 215 | union 216 | { 217 | IN_ADDR V4; 218 | IN6_ADDR V6; 219 | } Address; /**< IP address */ 220 | ADDRESS_FAMILY AddressFamily; /**< Address family, either AF_INET or AF_INET6 */ 221 | BYTE Cidr; /**< CIDR of allowed IPs */ 222 | }; 223 | 224 | typedef enum 225 | { 226 | WIREGUARD_PEER_HAS_PUBLIC_KEY = 1 << 0, /**< The PublicKey field is set */ 227 | WIREGUARD_PEER_HAS_PRESHARED_KEY = 1 << 1, /**< The PresharedKey field is set */ 228 | WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2, /**< The PersistentKeepAlive field is set */ 229 | WIREGUARD_PEER_HAS_ENDPOINT = 1 << 3, /**< The Endpoint field is set */ 230 | WIREGUARD_PEER_REPLACE_ALLOWED_IPS = 1 << 5, /**< Remove all allowed IPs before adding new ones */ 231 | WIREGUARD_PEER_REMOVE = 1 << 6, /**< Remove specified peer */ 232 | WIREGUARD_PEER_UPDATE = 1 << 7 /**< Do not add a new peer */ 233 | } WIREGUARD_PEER_FLAG; 234 | 235 | typedef struct _WIREGUARD_PEER WIREGUARD_PEER; 236 | struct ALIGNED(8) _WIREGUARD_PEER 237 | { 238 | WIREGUARD_PEER_FLAG Flags; /**< Bitwise combination of flags */ 239 | DWORD Reserved; /**< Reserved; must be zero */ 240 | BYTE PublicKey[WIREGUARD_KEY_LENGTH]; /**< Public key, the peer's primary identifier */ 241 | BYTE PresharedKey[WIREGUARD_KEY_LENGTH]; /**< Preshared key for additional layer of post-quantum resistance */ 242 | WORD PersistentKeepalive; /**< Seconds interval, or 0 to disable */ 243 | SOCKADDR_INET Endpoint; /**< Endpoint, with IP address and UDP port number*/ 244 | DWORD64 TxBytes; /**< Number of bytes transmitted */ 245 | DWORD64 RxBytes; /**< Number of bytes received */ 246 | DWORD64 LastHandshake; /**< Time of the last handshake, in 100ns intervals since 1601-01-01 UTC */ 247 | DWORD AllowedIPsCount; /**< Number of allowed IP structs following this struct */ 248 | }; 249 | 250 | typedef enum 251 | { 252 | WIREGUARD_INTERFACE_HAS_PUBLIC_KEY = (1 << 0), /**< The PublicKey field is set */ 253 | WIREGUARD_INTERFACE_HAS_PRIVATE_KEY = (1 << 1), /**< The PrivateKey field is set */ 254 | WIREGUARD_INTERFACE_HAS_LISTEN_PORT = (1 << 2), /**< The ListenPort field is set */ 255 | WIREGUARD_INTERFACE_REPLACE_PEERS = (1 << 3) /**< Remove all peers before adding new ones */ 256 | } WIREGUARD_INTERFACE_FLAG; 257 | 258 | typedef struct _WIREGUARD_INTERFACE WIREGUARD_INTERFACE; 259 | struct ALIGNED(8) _WIREGUARD_INTERFACE 260 | { 261 | WIREGUARD_INTERFACE_FLAG Flags; /**< Bitwise combination of flags */ 262 | WORD ListenPort; /**< Port for UDP listen socket, or 0 to choose randomly */ 263 | BYTE PrivateKey[WIREGUARD_KEY_LENGTH]; /**< Private key of interface */ 264 | BYTE PublicKey[WIREGUARD_KEY_LENGTH]; /**< Corresponding public key of private key */ 265 | DWORD PeersCount; /**< Number of peer structs following this struct */ 266 | }; 267 | 268 | /** 269 | * Sets the configuration of the WireGuard adapter. 270 | * 271 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 272 | * 273 | * @param Config Configuration for the adapter. 274 | * 275 | * @param Bytes Number of bytes in Config allocation. 276 | * 277 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 278 | * get extended error information, call GetLastError. 279 | */ 280 | typedef _Return_type_success_(return != FALSE) 281 | BOOL(WINAPI WIREGUARD_SET_CONFIGURATION_FUNC) 282 | (_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_reads_bytes_(Bytes) const WIREGUARD_INTERFACE *Config, _In_ DWORD Bytes); 283 | 284 | /** 285 | * Gets the configuration of the WireGuard adapter. 286 | * 287 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 288 | * 289 | * @param Config Configuration for the adapter. 290 | * 291 | * @param Bytes Pointer to number of bytes in Config allocation. 292 | * 293 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 294 | * get extended error information, call GetLastError, which if ERROR_MORE_DATA, Bytes is updated with the 295 | * required size. 296 | */ 297 | typedef _Must_inspect_result_ 298 | _Return_type_success_(return != FALSE) 299 | BOOL(WINAPI WIREGUARD_GET_CONFIGURATION_FUNC) 300 | (_In_ WIREGUARD_ADAPTER_HANDLE Adapter, 301 | _Out_writes_bytes_all_(*Bytes) WIREGUARD_INTERFACE *Config, 302 | _Inout_ DWORD *Bytes); 303 | 304 | #pragma warning(pop) 305 | 306 | #ifdef __cplusplus 307 | } 308 | #endif 309 | -------------------------------------------------------------------------------- /src/adapter.rs: -------------------------------------------------------------------------------- 1 | use std::mem::{align_of, size_of}; 2 | use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; 3 | use std::ptr; 4 | use std::sync::Arc; 5 | use std::time::{Duration, SystemTime}; 6 | 7 | use ipnet::{IpNet, Ipv4Net, Ipv6Net}; 8 | use widestring::U16CString; 9 | use windows_sys::Win32::{ 10 | Foundation::{GetLastError, ERROR_MORE_DATA, ERROR_OBJECT_ALREADY_EXISTS, ERROR_SUCCESS}, 11 | NetworkManagement::{ 12 | IpHelper::{ 13 | CreateIpForwardEntry2, CreateUnicastIpAddressEntry, GetIpInterfaceEntry, 14 | InitializeIpForwardEntry, InitializeIpInterfaceEntry, InitializeUnicastIpAddressEntry, 15 | SetIpInterfaceEntry, MIB_IPFORWARD_ROW2, MIB_IPINTERFACE_ROW, MIB_UNICASTIPADDRESS_ROW, 16 | }, 17 | Ndis, 18 | }, 19 | Networking::{ 20 | WinSock::{IpDadStatePreferred, AF_INET, AF_INET6}, 21 | WinSock::{IN6_ADDR, IN_ADDR}, 22 | }, 23 | }; 24 | 25 | use crate::log::AdapterLoggingLevel; 26 | use crate::util::{self, StructReader, UnsafeHandle}; 27 | use crate::wireguard_nt_raw::{ 28 | in6_addr, in_addr, wireguard, GUID, WIREGUARD_ADAPTER_HANDLE, WIREGUARD_ALLOWED_IP, 29 | WIREGUARD_INTERFACE, WIREGUARD_INTERFACE_FLAG, WIREGUARD_PEER, WIREGUARD_PEER_FLAG, 30 | _NET_LUID_LH, 31 | }; 32 | use crate::{Error, Result, Wireguard}; 33 | 34 | /// Representation of a wireGuard adapter with safe idiomatic bindings to the functionality provided by 35 | /// the WireGuard* C functions. 36 | /// 37 | /// The [`Adapter::create`] and [`Adapter::open`] functions serve as the entry point to using 38 | /// wireguard functionality 39 | /// 40 | /// Wrapper around a `WIREGUARD_ADAPTER_HANDLE` 41 | /// 42 | /// Related functions from WireGuardXXX are functions with an adapter self parameter 43 | pub struct Adapter { 44 | adapter: UnsafeHandle, 45 | wireguard: Arc, 46 | } 47 | 48 | /// Representation of a WireGuard peer when setting the config 49 | #[derive(Clone)] 50 | pub struct SetPeer { 51 | /// The peer's public key 52 | pub public_key: Option<[u8; 32]>, 53 | 54 | /// A preshared key used to symmetrically encrypt data with this peer 55 | pub preshared_key: Option<[u8; 32]>, 56 | 57 | /// How often to send a keep alive packet to prevent NATs from blocking UDP packets 58 | /// 59 | /// Set to None if no keep alive behavior is wanted 60 | pub keep_alive: Option, 61 | 62 | /// The address this peer is reachable from using UDP across the internet 63 | pub endpoint: SocketAddr, 64 | 65 | /// The set of [`IpNet`]'s that dictate what packets are allowed to be sent of received from 66 | /// this peer 67 | pub allowed_ips: Vec, 68 | } 69 | 70 | pub type RebootRequired = bool; 71 | 72 | /// The data required when setting the config for an interface 73 | pub struct SetInterface { 74 | /// The port this interface should listen on. 75 | /// The default 51820 is used if this is set to `None` 76 | pub listen_port: Option, 77 | 78 | /// The public key of this interface. 79 | /// If this is `None`, the public key is generated from the private key 80 | pub public_key: Option<[u8; 32]>, 81 | 82 | /// The private key of this interface 83 | pub private_key: Option<[u8; 32]>, 84 | 85 | /// The peers that this interface is allowed to communicate with 86 | pub peers: Vec, 87 | } 88 | 89 | fn encode_name(name: &str) -> Result { 90 | let utf16 = U16CString::from_str(name)?; 91 | let max = crate::MAX_NAME; 92 | if utf16.len() >= max { 93 | //max_characters is the maximum number of characters including the null terminator. And .len() measures the 94 | //number of characters (excluding the null terminator). Therefore, we can hold a string with 95 | //max_characters - 1 because the null terminator sits in the last element. A string 96 | //of length max_characters needs max_characters + 1 to store the null terminator so the >= 97 | //check holds 98 | Err(Error::NameTooLarge) 99 | } else { 100 | Ok(utf16) 101 | } 102 | } 103 | 104 | /// Contains information about a single existing adapter 105 | pub struct EnumeratedAdapter { 106 | /// The name of the adapter 107 | pub name: String, 108 | } 109 | 110 | fn win_error(context: &str, error_code: u32) -> Result<()> { 111 | let e = std::io::Error::from_raw_os_error(error_code as i32); 112 | Err(Error::Windows(context.to_string(), e)) 113 | } 114 | 115 | const WIREGUARD_STATE_DOWN: i32 = 0; 116 | const WIREGUARD_STATE_UP: i32 = 1; 117 | 118 | impl Adapter { 119 | //TODO: Call get last error for error information on failure and improve error types 120 | 121 | /// Creates a new wireguard adapter inside the pool `pool` with name `name` 122 | /// 123 | /// Optionally a GUID can be specified that will become the GUID of this adapter once created. 124 | pub fn create( 125 | wireguard: &Wireguard, 126 | pool: &str, 127 | name: &str, 128 | guid: Option, 129 | ) -> Result { 130 | let pool_utf16 = encode_name(pool)?; 131 | let name_utf16 = encode_name(name)?; 132 | 133 | let guid = guid.unwrap_or_else(|| { 134 | let mut guid_bytes = [0u8; 16]; 135 | getrandom::getrandom(&mut guid_bytes) 136 | .expect("Failed to generate random bytes for guid"); 137 | u128::from_ne_bytes(guid_bytes) 138 | }); 139 | //SAFETY: guid is a unique integer so transmuting either all zeroes or the user's preferred 140 | //guid to the WinAPI guid type is safe and will allow the Windows kernel to see our GUID 141 | let guid_struct = unsafe { std::mem::transmute::(guid) }; 142 | //TODO: The guid of the adapter once created might differ from the one provided because of 143 | //the byte order of the segments of the GUID struct that are larger than a byte. Verify 144 | //that this works as expected 145 | 146 | crate::log::set_default_logger_if_unset(wireguard); 147 | 148 | //SAFETY: the function is loaded from the wireguard dll properly, we are providing valid 149 | //pointers, and all the strings are correct null terminated UTF-16. This safety rationale 150 | //applies for all WireGuard* functions below 151 | let result = unsafe { 152 | wireguard.WireGuardCreateAdapter( 153 | pool_utf16.as_ptr(), 154 | name_utf16.as_ptr(), 155 | &guid_struct as *const GUID, 156 | ) 157 | }; 158 | 159 | if result.is_null() { 160 | Err(Error::Driver(std::io::Error::last_os_error())) 161 | } else { 162 | Ok(Self { 163 | adapter: UnsafeHandle(result), 164 | wireguard: Arc::clone(&wireguard.0), 165 | }) 166 | } 167 | } 168 | 169 | /// Attempts to open an existing wireguard with name `name`. 170 | pub fn open(wireguard: &Wireguard, name: &str) -> Result { 171 | let name_utf16 = encode_name(name)?; 172 | 173 | crate::log::set_default_logger_if_unset(wireguard); 174 | 175 | let result = unsafe { wireguard.WireGuardOpenAdapter(name_utf16.as_ptr()) }; 176 | 177 | if result.is_null() { 178 | Err(Error::Driver(std::io::Error::last_os_error())) 179 | } else { 180 | Ok(Adapter { 181 | adapter: UnsafeHandle(result), 182 | wireguard: Arc::clone(&wireguard.0), 183 | }) 184 | } 185 | } 186 | 187 | /// Sets the wireguard configuration of this adapter 188 | pub fn set_config(&self, config: &SetInterface) -> Result<()> { 189 | bitflags::bitflags! { 190 | struct InterfaceFlags: i32 { 191 | const HAS_PUBLIC_KEY = 1 << 0; 192 | const HAS_PRIVATE_KEY = 1 << 1; 193 | const HAS_LISTEN_PORT = 1 << 2; 194 | const REPLACE_PEERS = 1 << 3; 195 | } 196 | } 197 | 198 | bitflags::bitflags! { 199 | struct PeerFlags: i32 { 200 | const HAS_PUBLIC_KEY = 1 << 0; 201 | const HAS_PRESHARED_KEY = 1 << 1; 202 | const HAS_PERSISTENT_KEEPALIVE = 1 << 2; 203 | const HAS_ENDPOINT = 1 << 3; 204 | const REPLACE_ALLOWED_IPS = 1 << 5; 205 | const REMOVE = 1 << 6; 206 | const UPDATE = 1 << 7; 207 | } 208 | } 209 | 210 | let peer_size = config 211 | .peers 212 | .iter() 213 | .map(|p| { 214 | size_of::() 215 | + p.allowed_ips.len() * size_of::() 216 | }) 217 | .sum::(); 218 | 219 | let size = size_of::() + peer_size; 220 | let align = align_of::(); 221 | 222 | let mut writer = util::StructWriter::new(size, align); 223 | //Most of this function is writing data into `writer`, in a format that wireguard expects 224 | //so that it can decode the data when we call WireGuardSetConfiguration 225 | 226 | // Safety: 227 | // 1. `writer` has the correct alignment for a `WIREGUARD_INTERFACE` 228 | // 2. Nothing has been written to writer so the internal pointer must be aligned 229 | let interface = unsafe { writer.write::() }; 230 | interface.Flags = { 231 | let mut flags = InterfaceFlags::REPLACE_PEERS; 232 | if let Some(private_key) = &config.private_key { 233 | flags |= InterfaceFlags::HAS_PRIVATE_KEY; 234 | interface.PrivateKey.copy_from_slice(private_key); 235 | } 236 | if let Some(pub_key) = &config.public_key { 237 | flags |= InterfaceFlags::HAS_PUBLIC_KEY; 238 | interface.PublicKey.copy_from_slice(pub_key); 239 | } 240 | 241 | if let Some(listen_port) = config.listen_port { 242 | flags |= InterfaceFlags::HAS_LISTEN_PORT; 243 | interface.ListenPort = listen_port; 244 | } 245 | 246 | flags.bits() 247 | }; 248 | interface.PeersCount = config.peers.len() as u32; 249 | 250 | for peer in &config.peers { 251 | // Safety: 252 | // `align_of::() }; 256 | 257 | wg_peer.Flags = { 258 | let mut flags = PeerFlags::HAS_ENDPOINT; 259 | if let Some(pub_key) = &peer.public_key { 260 | flags |= PeerFlags::HAS_PUBLIC_KEY; 261 | wg_peer.PublicKey.copy_from_slice(pub_key); 262 | } 263 | if let Some(preshared_key) = &peer.preshared_key { 264 | flags |= PeerFlags::HAS_PRESHARED_KEY; 265 | wg_peer.PresharedKey.copy_from_slice(preshared_key); 266 | } 267 | if let Some(keep_alive) = peer.keep_alive { 268 | flags |= PeerFlags::HAS_PERSISTENT_KEEPALIVE; 269 | wg_peer.PersistentKeepalive = keep_alive; 270 | } 271 | flags.bits() 272 | }; 273 | 274 | log::info!("endpoint: {}", &peer.endpoint); 275 | match peer.endpoint { 276 | SocketAddr::V4(v4) => unsafe { 277 | let addr = std::mem::transmute::<[u8; 4], in_addr>(v4.ip().octets()); 278 | wg_peer.Endpoint.Ipv4.sin_family = AF_INET; 279 | //Make sure to put the port in network byte order 280 | wg_peer.Endpoint.Ipv4.sin_port = u16::from_ne_bytes(v4.port().to_be_bytes()); 281 | wg_peer.Endpoint.Ipv4.sin_addr = addr; 282 | }, 283 | SocketAddr::V6(v6) => unsafe { 284 | let addr = std::mem::transmute::<[u8; 16], in6_addr>(v6.ip().octets()); 285 | wg_peer.Endpoint.Ipv6.sin6_family = AF_INET6; 286 | wg_peer.Endpoint.Ipv4.sin_port = u16::from_ne_bytes(v6.port().to_be_bytes()); 287 | wg_peer.Endpoint.Ipv6.sin6_addr = addr; 288 | }, 289 | } 290 | 291 | wg_peer.AllowedIPsCount = peer.allowed_ips.len() as u32; 292 | 293 | for allowed_ip in &peer.allowed_ips { 294 | // Safety: 295 | // Same as above, `writer` is aligned because it was aligned before 296 | let wg_allowed_ip = unsafe { writer.write::() }; 297 | match allowed_ip { 298 | IpNet::V4(v4) => { 299 | let addr = 300 | unsafe { std::mem::transmute::<[u8; 4], in_addr>(v4.addr().octets()) }; 301 | wg_allowed_ip.Address.V4 = addr; 302 | wg_allowed_ip.AddressFamily = AF_INET; 303 | wg_allowed_ip.Cidr = v4.prefix_len(); 304 | } 305 | IpNet::V6(v6) => { 306 | let addr = unsafe { 307 | std::mem::transmute::<[u8; 16], in6_addr>(v6.addr().octets()) 308 | }; 309 | wg_allowed_ip.Address.V6 = addr; 310 | wg_allowed_ip.AddressFamily = AF_INET6; 311 | wg_allowed_ip.Cidr = v6.prefix_len(); 312 | } 313 | } 314 | } 315 | } 316 | 317 | //Make sure that our allocation math was correct and that we filled all of writer 318 | debug_assert!(writer.is_full()); 319 | 320 | let result = unsafe { 321 | self.wireguard.WireGuardSetConfiguration( 322 | self.adapter.0, 323 | writer.ptr().cast(), 324 | size as u32, 325 | ) 326 | }; 327 | 328 | match result { 329 | 0 => Err(Error::Driver(std::io::Error::last_os_error())), 330 | _ => Ok(()), 331 | } 332 | } 333 | 334 | /// Assigns this adapter an ip address and adds route(s) so that packets sent 335 | /// within the `interface_addr` ipnet will be sent across the WireGuard VPN 336 | pub fn set_default_route( 337 | &self, 338 | interface_addrs: &[IpNet], 339 | config: &SetInterface, 340 | ) -> Result<()> { 341 | // Set the route with metric = 0 (highest priority / default) 342 | self.set_route_with_metric(interface_addrs, config, 0) 343 | } 344 | 345 | /// Assigns this adapter an ip address and adds route(s) so that packets sent 346 | /// within the `interface_addr` ipnet will be sent across the WireGuard VPN 347 | /// if no route with lower metric (higher priority) is found 348 | pub fn set_route_with_metric( 349 | &self, 350 | interface_addrs: &[IpNet], 351 | config: &SetInterface, 352 | metric: u32, 353 | ) -> Result<()> { 354 | let luid = self.get_luid(); 355 | unsafe { 356 | for allowed_ip in config.peers.iter().flat_map(|p| p.allowed_ips.iter()) { 357 | let mut default_route = std::mem::zeroed::(); 358 | InitializeIpForwardEntry(&mut default_route); 359 | default_route.InterfaceLuid = std::mem::transmute::(luid); 360 | default_route.Metric = 5; 361 | 362 | match allowed_ip { 363 | IpNet::V4(v4) => { 364 | default_route.DestinationPrefix.Prefix.si_family = AF_INET; 365 | default_route.DestinationPrefix.Prefix.Ipv4.sin_addr = 366 | std::mem::transmute::<[u8; 4], IN_ADDR>(v4.addr().octets()); 367 | 368 | default_route.DestinationPrefix.PrefixLength = v4.prefix_len(); 369 | 370 | //Next hop is 0.0.0.0/0, because it is the address of a local interface 371 | //(the wireguard interface). So because the struct is zeroed we don't need 372 | //to set anything except the address family 373 | default_route.NextHop.si_family = AF_INET; 374 | } 375 | IpNet::V6(v6) => { 376 | default_route.DestinationPrefix.Prefix.si_family = AF_INET6; 377 | default_route.DestinationPrefix.Prefix.Ipv6.sin6_addr = 378 | std::mem::transmute::<[u8; 16], IN6_ADDR>(v6.addr().octets()); 379 | 380 | default_route.DestinationPrefix.PrefixLength = v6.prefix_len(); 381 | default_route.NextHop.si_family = AF_INET6; 382 | } 383 | } 384 | 385 | let err = CreateIpForwardEntry2(&default_route); 386 | if err != ERROR_SUCCESS && err != ERROR_OBJECT_ALREADY_EXISTS { 387 | return win_error("CreateIpForwardEntry2", err); 388 | } 389 | } 390 | 391 | let mut ip_interface = std::mem::zeroed::(); 392 | InitializeIpInterfaceEntry(&mut ip_interface); 393 | ip_interface.InterfaceLuid = std::mem::transmute::(luid); 394 | 395 | for interface_addr in interface_addrs { 396 | let mut address_row = std::mem::zeroed::(); 397 | InitializeUnicastIpAddressEntry(&mut address_row); 398 | address_row.InterfaceLuid = std::mem::transmute::(luid); 399 | address_row.OnLinkPrefixLength = interface_addr.prefix_len(); 400 | address_row.DadState = IpDadStatePreferred; 401 | 402 | match interface_addr { 403 | IpNet::V4(interface_addr_v4) => { 404 | ip_interface.Family = AF_INET; 405 | 406 | address_row.Address.Ipv4.sin_family = AF_INET; 407 | address_row.Address.Ipv4.sin_addr = std::mem::transmute::<[u8; 4], IN_ADDR>( 408 | interface_addr_v4.addr().octets(), 409 | ); 410 | } 411 | IpNet::V6(interface_addr_v6) => { 412 | ip_interface.Family = AF_INET6; 413 | 414 | address_row.Address.Ipv6.sin6_family = AF_INET6; 415 | address_row.Address.Ipv6.sin6_addr = 416 | std::mem::transmute::<[u8; 16], IN6_ADDR>( 417 | interface_addr_v6.addr().octets(), 418 | ); 419 | } 420 | } 421 | 422 | let err = CreateUnicastIpAddressEntry(&address_row); 423 | if err != ERROR_SUCCESS && err != ERROR_OBJECT_ALREADY_EXISTS { 424 | return win_error("CreateUnicastIpAddressEntry", err); 425 | } 426 | } 427 | 428 | let err = GetIpInterfaceEntry(&mut ip_interface); 429 | if err != ERROR_SUCCESS { 430 | return win_error("GetIpInterfaceEntry", err); 431 | } 432 | ip_interface.UseAutomaticMetric = 0; 433 | ip_interface.Metric = metric; 434 | ip_interface.NlMtu = 1420; 435 | ip_interface.SitePrefixLength = 0; 436 | let err = SetIpInterfaceEntry(&mut ip_interface); 437 | if err != ERROR_SUCCESS { 438 | return win_error("SetIpInterfaceEntry", err); 439 | } 440 | 441 | Ok(()) 442 | } 443 | } 444 | 445 | /// Get the state of this adapter 446 | pub fn is_up(&self) -> Result { 447 | let mut state = 0; 448 | let success = unsafe { 449 | self.wireguard 450 | .WireGuardGetAdapterState(self.adapter.0, &mut state) 451 | != 0 452 | }; 453 | if success { 454 | Ok(state == WIREGUARD_STATE_UP) 455 | } else { 456 | Err(Error::Driver(std::io::Error::last_os_error())) 457 | } 458 | } 459 | 460 | /// Puts this adapter into the up state 461 | pub fn up(&self) -> Result<()> { 462 | let success = unsafe { 463 | self.wireguard 464 | .WireGuardSetAdapterState(self.adapter.0, WIREGUARD_STATE_UP) 465 | != 0 466 | }; 467 | if success { 468 | Ok(()) 469 | } else { 470 | Err(Error::Driver(std::io::Error::last_os_error())) 471 | } 472 | } 473 | 474 | /// Puts this adapter into the down state 475 | pub fn down(&self) -> Result<()> { 476 | let success = unsafe { 477 | self.wireguard 478 | .WireGuardSetAdapterState(self.adapter.0, WIREGUARD_STATE_DOWN) 479 | != 0 480 | }; 481 | if success { 482 | Ok(()) 483 | } else { 484 | Err(Error::Driver(std::io::Error::last_os_error())) 485 | } 486 | } 487 | 488 | /// Returns the adapter's LUID. 489 | /// This is a 64bit unique identifier that windows uses when referencing this adapter 490 | pub fn get_luid(&self) -> u64 { 491 | let mut luid = 0u64; 492 | let ptr = &mut luid as *mut u64 as *mut _NET_LUID_LH; 493 | unsafe { self.wireguard.WireGuardGetAdapterLUID(self.adapter.0, ptr) }; 494 | luid 495 | } 496 | 497 | /// Sets the logging level of this adapter 498 | /// 499 | /// Log messages will be sent to the current logger (set using [`crate::set_logger`] 500 | pub fn set_logging(&self, level: AdapterLoggingLevel) -> bool { 501 | let level = match level { 502 | AdapterLoggingLevel::Off => 0, 503 | AdapterLoggingLevel::On => 1, 504 | AdapterLoggingLevel::OnWithPrefix => 2, 505 | }; 506 | unsafe { 507 | self.wireguard 508 | .WireGuardSetAdapterLogging(self.adapter.0, level) 509 | != 0 510 | } 511 | } 512 | 513 | /// Gets the current configuration of this adapter 514 | pub fn get_config(&self) -> WireguardInterface { 515 | // calling wireguard.WireGuardGetConfiguration with Bytes = 0 returns ERROR_MORE_DATA 516 | // and updates Bytes to the correct value 517 | let mut size = 0u32; 518 | let res = unsafe { 519 | self.wireguard 520 | .WireGuardGetConfiguration(self.adapter.0, ptr::null_mut(), &mut size) 521 | }; 522 | // Should never fail since we 523 | assert_eq!(res, 0, "Failed to query size of wireguard configuration"); 524 | assert_eq!( 525 | unsafe { GetLastError() }, 526 | ERROR_MORE_DATA, 527 | "WireGuardGetConfiguration returned invalid error for size request" 528 | ); 529 | assert_ne!(size, 0, "Wireguard config is zero bytes"); // size has been updated 530 | let align = align_of::(); 531 | let mut reader = StructReader::new(size as usize, align); 532 | let res = unsafe { 533 | self.wireguard.WireGuardGetConfiguration( 534 | self.adapter.0, 535 | reader.ptr_mut().cast(), 536 | &mut size, 537 | ) 538 | }; 539 | assert_ne!(res, 0); 540 | 541 | // # Safety: 542 | // 1. `WireGuardGetConfiguration` writes a `WIREGUARD_INTERFACE` at offset 0 to the buffer we give it. 543 | // 2. The buffer's alignment is set to be the proper alignment for a `WIREGUARD_INTERFACE` by the line above 544 | // 3. We calculate the size of `reader` with the first call to `WireGuardGetConfiguration`. Wireguard writes at 545 | // least one `WIREGUARD_INTERFACE`, and size is updated accordingly, therefore `reader`'s allocation is at least 546 | // the size of a `WIREGUARD_INTERFACE` 547 | let wireguard_interface = unsafe { reader.read::() }; 548 | let mut wg_interface = WireguardInterface { 549 | flags: wireguard_interface.Flags, 550 | listen_port: wireguard_interface.ListenPort, 551 | private_key: wireguard_interface.PrivateKey, 552 | public_key: wireguard_interface.PublicKey, 553 | peers: Vec::with_capacity(wireguard_interface.PeersCount as usize), 554 | }; 555 | 556 | for _ in 0..wireguard_interface.PeersCount { 557 | // # Safety: 558 | // 1. `WireGuardGetConfiguration` writes a `WIREGUARD_PEER` immediately after the WIREGUARD_INTERFACE we read above. 559 | // 2. We rely on Wireguard-NT to specify the number of peers written, and therefore we never read too many times unless Wireguard-NT (wrongly) tells us to 560 | let peer = unsafe { reader.read::() }; 561 | let endpoint = peer.Endpoint; 562 | let address_family = unsafe { endpoint.si_family }; 563 | let endpoint = match address_family { 564 | AF_INET => { 565 | // #Safety 566 | // This enum is valid to access because the address is a [u8; 4] which is set properly by the call above, 567 | // and it can have any value. 568 | let octets = unsafe { endpoint.Ipv4.sin_addr.S_un.S_un_b }; 569 | let address = Ipv4Addr::new(octets.s_b1, octets.s_b2, octets.s_b3, octets.s_b4); 570 | let port = u16::from_be(unsafe { endpoint.Ipv4.sin_port }); 571 | SocketAddr::V4(SocketAddrV4::new(address, port)) 572 | } 573 | AF_INET6 => { 574 | let octets = unsafe { endpoint.Ipv6.sin6_addr.u.Byte }; 575 | let address = Ipv6Addr::from(octets); 576 | let port = u16::from_be(unsafe { endpoint.Ipv6.sin6_port }); 577 | let flow_info = unsafe { endpoint.Ipv6.sin6_flowinfo }; 578 | let scope_id = unsafe { endpoint.Ipv6.__bindgen_anon_1.sin6_scope_id }; 579 | SocketAddr::V6(SocketAddrV6::new(address, port, flow_info, scope_id)) 580 | } 581 | _ => { 582 | panic!("Illegal address family {}", address_family); 583 | } 584 | }; 585 | let last_handshake = if peer.LastHandshake == 0 { 586 | None 587 | } else { 588 | // The number of 100ns intervals between 1-1-1600 and 1-1-1970 589 | const UNIX_EPOCH_FROM_1_1_1600: u64 = 116444736000000000; 590 | let ns_from_unix_epoch = 591 | peer.LastHandshake.saturating_sub(UNIX_EPOCH_FROM_1_1_1600) * 100; 592 | Some(SystemTime::UNIX_EPOCH + Duration::from_nanos(ns_from_unix_epoch)) 593 | }; 594 | 595 | let mut wg_peer = WireguardPeer { 596 | flags: peer.Flags, 597 | public_key: peer.PublicKey, 598 | preshared_key: peer.PresharedKey, 599 | persistent_keepalive: peer.PersistentKeepalive, 600 | endpoint, 601 | tx_bytes: peer.TxBytes, 602 | rx_bytes: peer.RxBytes, 603 | last_handshake, 604 | allowed_ips: Vec::with_capacity(peer.AllowedIPsCount as usize), 605 | }; 606 | for _ in 0..peer.AllowedIPsCount { 607 | // # Safety: 608 | // 1. `WireGuardGetConfiguration` writes zero or more `WIREGUARD_ALLOWED_IP`s immediately after the WIREGUARD_PEER we read above. 609 | // 2. We rely on Wireguard-NT to specify the number of allowed ips written, and therefore we never read too many times unless Wireguard-NT (wrongly) tells us to 610 | let allowed_ip = unsafe { reader.read::() }; 611 | let prefix_length = allowed_ip.Cidr; 612 | let allowed_ip = match allowed_ip.AddressFamily { 613 | AF_INET => { 614 | let octets = unsafe { allowed_ip.Address.V4.S_un.S_un_b }; 615 | let address = 616 | Ipv4Addr::new(octets.s_b1, octets.s_b2, octets.s_b3, octets.s_b4); 617 | IpNet::V4(Ipv4Net::new(address, prefix_length).expect("prefix is valid")) 618 | } 619 | AF_INET6 => { 620 | let octets = unsafe { allowed_ip.Address.V6.u.Byte }; 621 | let address = Ipv6Addr::from(octets); 622 | IpNet::V6(Ipv6Net::new(address, prefix_length).expect("prefix is valid")) 623 | } 624 | _ => { 625 | panic!("Illegal address family {}", allowed_ip.AddressFamily); 626 | } 627 | }; 628 | wg_peer.allowed_ips.push(allowed_ip); 629 | } 630 | wg_interface.peers.push(wg_peer); 631 | } 632 | wg_interface 633 | } 634 | } 635 | 636 | #[derive(Debug)] 637 | pub struct WireguardPeer { 638 | /// Bitwise combination of flags 639 | pub flags: WIREGUARD_PEER_FLAG, 640 | /// Public key, the peer's primary identifier 641 | pub public_key: [u8; 32usize], 642 | /// Preshared key for additional layer of post-quantum resistance 643 | pub preshared_key: [u8; 32usize], 644 | /// Seconds interval, or 0 to disable 645 | pub persistent_keepalive: u16, 646 | /// Endpoint, with IP address and UDP port number 647 | pub endpoint: SocketAddr, 648 | /// Number of bytes transmitted 649 | pub tx_bytes: u64, 650 | /// Number of bytes received 651 | pub rx_bytes: u64, 652 | /// Time of the last handshake, `None` if no handshake has occurred 653 | pub last_handshake: Option, 654 | /// Number of allowed IP structs following this struct 655 | pub allowed_ips: Vec, 656 | } 657 | 658 | #[derive(Debug)] 659 | pub struct WireguardInterface { 660 | /// Bitwise combination of flags 661 | pub flags: WIREGUARD_INTERFACE_FLAG, 662 | /// Port for UDP listen socket, or 0 to choose randomly 663 | pub listen_port: u16, 664 | /// Private key of interface 665 | pub private_key: [u8; 32usize], 666 | /// Corresponding public key of private key 667 | pub public_key: [u8; 32usize], 668 | /// Number of peer structs following this struct 669 | pub peers: Vec, 670 | } 671 | 672 | impl Drop for Adapter { 673 | fn drop(&mut self) { 674 | //Free adapter on drop 675 | //This is why we need an Arc of wireguard, so we have access to it here 676 | unsafe { self.wireguard.WireGuardCloseAdapter(self.adapter.0) }; 677 | self.adapter = UnsafeHandle(ptr::null_mut()); 678 | } 679 | } 680 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Safe rust idiomatic bindings for the WireGuard NT C library: 2 | //! 3 | //! Features of the WireGuard NT library are wrapped using pure rust types and functions to make 4 | //! usage ergonomic. 5 | //! 6 | //! # Usage 7 | //! 8 | //! Add a dependency on this library to your `Cargo.toml` 9 | //! 10 | //! ```toml 11 | //! [dependencies] 12 | //! wireguard-nt = "0.4" 13 | //! ``` 14 | //! 15 | //! Inside your code load the wireguard.dll signed driver file, downloaded from 16 | //! 17 | //! Then either call [`Adapter::create`] or [`Adapter::open`] to obtain a wireguard 18 | //! adapter. Start by setting its config with [`Adapter::set_config`]. 19 | //! 20 | //! # Example 21 | //! ```no_run 22 | //! // Must be run as Administrator because we create network adapters 23 | //! 24 | //! // Load the wireguard dll file so that we can call the underlying C functions 25 | //! // Unsafe because we are loading an arbitrary dll file 26 | //! let wireguard = 27 | //! unsafe { wireguard_nt::load_from_path("examples/wireguard_nt/bin/amd64/wireguard.dll") } 28 | //! .expect("Failed to load wireguard dll"); 29 | //! 30 | //! // Try to open an adapter from the given pool with the name "Demo" 31 | //! let adapter = 32 | //! wireguard_nt::Adapter::open(&wireguard, "Demo").unwrap_or_else(|_| { 33 | //! wireguard_nt::Adapter::create(&wireguard, "WireGuard", "Demo", None) 34 | //! .expect("Failed to create wireguard adapter!") 35 | //! }); 36 | //! 37 | //! let interface = wireguard_nt::SetInterface { 38 | //! //Let the OS pick a port for us 39 | //! listen_port: None, 40 | //! //Generated from the private key if not specified 41 | //! public_key: None, 42 | //! //Fill in private keys in real code 43 | //! private_key: None, 44 | //! //Add a peer 45 | //! peers: vec![wireguard_nt::SetPeer { 46 | //! //Provide a public key so that we can communicate with them 47 | //! public_key: None, 48 | //! //Disable additional AES encryption 49 | //! preshared_key: None, 50 | //! //Send a keepalive packet every 21 seconds 51 | //! keep_alive: Some(21), 52 | //! //Route all traffic through the WireGuard interface 53 | //! allowed_ips: vec!["0.0.0.0/0".parse().unwrap()], 54 | //! //The peer's ip address 55 | //! endpoint: "1.2.3.4".parse().unwrap(), 56 | //! }], 57 | //! }; 58 | //! 59 | //! //Set the config our adapter will use 60 | //! //This lets it know about the peers and keys 61 | //! adapter.set_config(&interface).unwrap(); 62 | //! 63 | //! let internal_ip = "10.4.0.2".parse().unwrap(); 64 | //! let internal_prefix_length = 24; 65 | //! let internal_ipnet = ipnet::Ipv4Net::new(internal_ip, internal_prefix_length).unwrap(); 66 | //! //Set up the routing table with the allowed ips for our peers, 67 | //! //and assign an ip to the interface 68 | //! adapter.set_default_route(&[internal_ipnet.into()], &interface).unwrap(); 69 | //! 70 | //! //drop(adapter) 71 | //! //The adapter closes its resources when dropped 72 | //! ``` 73 | //! 74 | //! See `examples/demo_server.rs` that connects to the wireguard demo server 75 | //! 76 | //! # Version compatibility 77 | //! Wireguard NT versions 0.10 and above are supported. Versions < 0.10 have breaking changes that 78 | //! make interoperability hard. Please file an issue if this effects your use case. 79 | //! 80 | 81 | mod adapter; 82 | mod log; 83 | mod util; 84 | 85 | //Generated by bingen, so ignore lints 86 | #[allow( 87 | non_snake_case, 88 | dead_code, 89 | unused_variables, 90 | non_camel_case_types, 91 | deref_nullptr, 92 | clippy::all 93 | )] 94 | mod wireguard_nt_raw; 95 | 96 | pub(crate) const MAX_NAME: usize = 256; 97 | 98 | pub use crate::adapter::*; 99 | pub use crate::log::*; 100 | pub use crate::util::get_running_driver_version; 101 | 102 | use std::sync::Arc; 103 | pub use wireguard_nt_raw::wireguard as Sys; 104 | 105 | use thiserror::Error; 106 | 107 | #[derive(Error, Debug)] 108 | pub enum Error { 109 | /// An error caused by calling into the wireguard-nt driver 110 | #[error("{0}")] 111 | Driver(#[from] std::io::Error), 112 | /// Unable to encode UTF-16 string due to early null 113 | #[error("invalid string: {0}")] 114 | Null(#[from] widestring::NulError), 115 | #[error("name too large (max {})", crate::MAX_NAME)] 116 | NameTooLarge, 117 | /// The windows function (self.0), failed with the given error (self.1) 118 | #[error("{0}: {1}")] 119 | Windows(String, std::io::Error), 120 | } 121 | 122 | pub type Result = std::result::Result; 123 | 124 | #[derive(Clone)] 125 | pub struct Wireguard(Arc); 126 | 127 | impl Wireguard { 128 | pub fn into_inner(self) -> Arc { 129 | self.0 130 | } 131 | } 132 | 133 | impl std::ops::Deref for Wireguard { 134 | type Target = Sys; 135 | fn deref(&self) -> &Self::Target { 136 | &self.0 137 | } 138 | } 139 | 140 | /// Attempts to load the Wireguand NT library from the current directory using the default name "wireguard.dll". 141 | /// 142 | /// Use [`load_from_path`] with an absolute path when more control is needed as to where wireguard.dll is 143 | /// 144 | /// 145 | /// # Safety 146 | /// This function loads a dll file with the name wireguard.dll using the default system search paths. 147 | /// This is inherently unsafe as a user could simply rename undefined_behavior.dll to wireguard.dll 148 | /// and do nefarious things inside of its DllMain function. In most cases, a regular wireguard.dll 149 | /// file which exports all of the required functions for these bindings to work is loaded. Because 150 | /// WireGuard NT is a well-written and well-tested library, loading a _normal_ wireguard.dll file should be safe. 151 | /// Hoverer one can never be too cautious when loading a dll file. 152 | /// 153 | /// For more information see [`libloading`]'s dynamic library safety guarantees: [`libloading`][`libloading::Library::new`] 154 | pub unsafe fn load() -> std::result::Result { 155 | load_from_path("wireguard") 156 | } 157 | 158 | /// Attempts to load the wireguard library as a dynamic library from the given path. 159 | /// 160 | /// 161 | /// # Safety 162 | /// This function loads a dll file with the path provided. 163 | /// This is inherently unsafe as a user could simply rename undefined_behavior.dll to wireguard.dll 164 | /// and do nefarious things inside of its DllMain function. In most cases, a regular wireguard.dll 165 | /// file which exports all of the required functions for these bindings to work is loaded. Because 166 | /// WireGuard NT is a well-written and well-tested library, loading a _normal_ wireguard.dll file should be safe. 167 | /// Hoverer one can never be too cautious when loading a dll file. 168 | /// 169 | /// For more information see [`libloading`]'s dynamic library safety guarantees: [`libloading`][`libloading::Library::new`] 170 | pub unsafe fn load_from_path

(path: P) -> std::result::Result 171 | where 172 | P: AsRef<::std::ffi::OsStr>, 173 | { 174 | Ok(Wireguard(Arc::new(wireguard_nt_raw::wireguard::new(path)?))) 175 | } 176 | 177 | /// Attempts to load the WireGuard NT library from an existing [`libloading::Library`]. 178 | /// 179 | /// 180 | /// # Safety 181 | /// This function loads the required WireGuard NT functions using the provided library. Reading a symbol table 182 | /// of a dynamic library and transmuting the function pointers inside to have the parameters and return 183 | /// values expected by the functions documented at: 184 | /// is inherently unsafe. 185 | /// 186 | /// For more information see [`libloading`]'s dynamic library safety guarantees: [`libloading::Library::new`] 187 | pub unsafe fn load_from_library(library: L) -> std::result::Result 188 | where 189 | L: Into, 190 | { 191 | Ok(Wireguard(Arc::new( 192 | wireguard_nt_raw::wireguard::from_library(library)?, 193 | ))) 194 | } 195 | 196 | // The error type 197 | // pub type WireGuardError = Box; 198 | -------------------------------------------------------------------------------- /src/log.rs: -------------------------------------------------------------------------------- 1 | use crate::wireguard_nt_raw; 2 | use log::*; 3 | use widestring::U16CStr; 4 | 5 | use std::sync::atomic::{AtomicBool, Ordering}; 6 | 7 | /// Sets the logger wireguard will use when logging. Maps to the wireguardSetLogger C function 8 | pub fn set_logger(wireguard: &crate::Wireguard, f: wireguard_nt_raw::WIREGUARD_LOGGER_CALLBACK) { 9 | unsafe { wireguard.WireGuardSetLogger(f) }; 10 | } 11 | 12 | /// What level of logging this adapter is using 13 | pub enum AdapterLoggingLevel { 14 | /// No messages are logged 15 | Off, 16 | 17 | /// All messages are logged 18 | On, 19 | 20 | /// All messaged are logged and the adapter id prefixes the log message 21 | OnWithPrefix, 22 | } 23 | 24 | static SET_LOGGER: AtomicBool = AtomicBool::new(false); 25 | 26 | /// The logger that is active by default. Logs messages to the log crate 27 | #[allow(clippy::not_unsafe_ptr_arg_deref)] 28 | pub extern "C" fn default_logger( 29 | level: wireguard_nt_raw::WIREGUARD_LOGGER_LEVEL, 30 | _timestamp: wireguard_nt_raw::DWORD64, 31 | message: *const wireguard_nt_raw::WCHAR, 32 | ) { 33 | if message.is_null() { 34 | return; 35 | } 36 | //WireGuard will always give us a valid UTF16 null terminated string 37 | let msg = unsafe { U16CStr::from_ptr_str(message) }; 38 | let utf8_msg = msg.to_string_lossy(); 39 | match level { 40 | wireguard_nt_raw::WIREGUARD_LOGGER_LEVEL_WIREGUARD_LOG_INFO => { 41 | info!("wireguard: {}", utf8_msg) 42 | } 43 | wireguard_nt_raw::WIREGUARD_LOGGER_LEVEL_WIREGUARD_LOG_WARN => { 44 | warn!("wireguard: {}", utf8_msg) 45 | } 46 | wireguard_nt_raw::WIREGUARD_LOGGER_LEVEL_WIREGUARD_LOG_ERR => { 47 | error!("wireguard: {}", utf8_msg) 48 | } 49 | _ => error!("wireguard: {} (with invalid log level {})", utf8_msg, level), 50 | } 51 | } 52 | 53 | pub(crate) fn set_default_logger_if_unset(wireguard: &crate::Wireguard) { 54 | if !SET_LOGGER.load(Ordering::Relaxed) { 55 | set_logger(wireguard, Some(default_logger)); 56 | SET_LOGGER.store(true, Ordering::Relaxed); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/util.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused_unsafe)] 2 | //In this file we are explicit about unsafe, even in unsafe functions 3 | //Hopefully one day we won't need this 4 | 5 | use crate::wireguard_nt_raw; 6 | use std::{alloc::Layout, sync::Arc}; 7 | 8 | /// A wrapper struct that allows a type to be Send and Sync 9 | pub(crate) struct UnsafeHandle(pub T); 10 | 11 | /// We never read from the pointer. It only serves as a handle we pass to the kernel or C code 12 | /// (where locks are used internally) 13 | unsafe impl Send for UnsafeHandle {} 14 | unsafe impl Sync for UnsafeHandle {} 15 | 16 | /// Returns the major and minor version of the wireguard driver 17 | pub fn get_running_driver_version(wireguard: &Arc) -> u32 { 18 | unsafe { wireguard.WireGuardGetRunningDriverVersion() } 19 | } 20 | 21 | pub(crate) struct StructWriter { 22 | start: *mut u8, 23 | offset: usize, 24 | layout: Layout, 25 | } 26 | 27 | impl StructWriter { 28 | /// Creates a struct writer that has the given initial capacity `capacity`, 29 | /// and whose allocation is aligned to `align` 30 | pub fn new(capacity: usize, align: usize) -> Self { 31 | let layout = Layout::from_size_align(capacity, align).unwrap(); 32 | let start = unsafe { std::alloc::alloc(layout) }; 33 | // Safety: 34 | // start is writeable for `capacity` bytes because that is the size of the allocation 35 | unsafe { start.write_bytes(0, capacity) }; 36 | Self { 37 | start, 38 | offset: 0, 39 | layout, 40 | } 41 | } 42 | 43 | /// Returns a reference of the desired type, which can be used to write a T into the 44 | /// buffer at the internal pointer. The internal pointer will be advanced by `size_of::()` so that 45 | /// the next call to [`write`] will return a reference to an adjacent memory location. 46 | /// The returned refrence will be the zero bit pattern initially. 47 | /// 48 | /// # Safety: 49 | /// 1. The caller must ensure the internal pointer is aligned suitably for writing to a T. 50 | /// In most C APIs (like Wireguard NT) the structs are setup in such a way that calling write 51 | /// repeatedly to pack data into the buffer always yields a struct that is aligned because the 52 | /// previous struct was aligned. 53 | /// 2. The caller must ensure that the zero bit pattern is valid for type T 54 | /// 55 | /// # Panics 56 | /// 1. If writing a struct of size T would overflow the buffer. 57 | /// 2. If the internal pointer does not meet the alignment requirements of T. 58 | pub unsafe fn write(&mut self) -> &mut T { 59 | let size = std::mem::size_of::(); 60 | if size + self.offset > self.layout.size() { 61 | panic!( 62 | "Overflow attempting to write struct of size {}. To allocation size: {}, offset: {}", 63 | size, 64 | self.layout.size(), 65 | self.offset 66 | ); 67 | } 68 | // Safety: 69 | // ptr is within this allocation by the bounds check above 70 | let ptr = unsafe { self.start.add(self.offset) }; 71 | self.offset += size; 72 | assert_eq!(ptr as usize % std::mem::align_of::(), 0); 73 | 74 | // Safety: 75 | // 1. This pointer is valid and within the bounds of this memory allocation 76 | // 2. The caller ensures that they the struct is aligned 77 | unsafe { &mut *ptr.cast::() } 78 | } 79 | 80 | pub fn ptr(&self) -> *const u8 { 81 | self.start 82 | } 83 | 84 | /// Returns true if this writer's capacity is full, false otherwise 85 | pub fn is_full(&self) -> bool { 86 | self.layout.size() == self.offset 87 | } 88 | } 89 | 90 | impl Drop for StructWriter { 91 | fn drop(&mut self) { 92 | unsafe { std::alloc::dealloc(self.start, self.layout) }; 93 | } 94 | } 95 | 96 | pub(crate) struct StructReader { 97 | start: *mut u8, 98 | offset: usize, 99 | layout: Layout, 100 | } 101 | 102 | impl StructReader { 103 | /// Creates a struct reader that has the given initial capacity `capacity`, 104 | /// and whose allocation is aligned to `align` 105 | pub fn new(capacity: usize, align: usize) -> Self { 106 | let layout = Layout::from_size_align(capacity, align).unwrap(); 107 | let start = unsafe { std::alloc::alloc(layout) }; 108 | Self { 109 | start, 110 | offset: 0, 111 | layout, 112 | } 113 | } 114 | 115 | /// Reads a given type from the internal buffer. 116 | /// This advances the internal pointer by the size of the read type, such that a given instance of 117 | /// the given type can only be read once. 118 | /// 119 | /// # Safety 120 | /// The caller must ensure the internal pointer is aligned suitably for reading a T. 121 | /// In most C APIs (like Wireguard NT) the structs are setup in such a way that calling read 122 | /// repeatedly to read packed data always yields a struct that is aligned because the 123 | /// previous struct was aligned. 124 | /// 125 | /// # Panics 126 | /// 1. If reading a struct of size T would overflow the buffer. 127 | /// 2. If the internal pointer does not meet the alignment requirements of T. 128 | pub unsafe fn read(&mut self) -> &T { 129 | let size = std::mem::size_of::(); 130 | if size + self.offset > self.layout.size() { 131 | panic!( 132 | "Overflow attempting to read struct of size {}. To allocation size: {}, offset: {}", 133 | size, 134 | self.layout.size(), 135 | self.offset 136 | ); 137 | } 138 | // Safety: 139 | // ptr is within this allocation by the bounds check above 140 | let ptr = unsafe { self.start.add(self.offset) }; 141 | self.offset += size; 142 | assert_eq!(ptr as usize % std::mem::align_of::(), 0); 143 | 144 | unsafe { &*ptr.cast::() } 145 | } 146 | 147 | pub fn ptr_mut(&self) -> *mut u8 { 148 | self.start 149 | } 150 | 151 | /// Returns true if this reader's capacity is full, false otherwise 152 | #[allow(dead_code)] 153 | pub fn is_full(&self) -> bool { 154 | self.layout.size() == self.offset 155 | } 156 | } 157 | 158 | impl Drop for StructReader { 159 | fn drop(&mut self) { 160 | unsafe { std::alloc::dealloc(self.start, self.layout) }; 161 | } 162 | } 163 | 164 | #[cfg(test)] 165 | mod tests { 166 | use super::*; 167 | use std::mem::{align_of_val, size_of_val}; 168 | 169 | #[test] 170 | fn reader_basic() { 171 | #[derive(Debug)] 172 | #[repr(C)] 173 | struct Data { 174 | field_a: u8, 175 | field_b: u32, 176 | } 177 | let expected_data = Data { 178 | field_a: 0b10000001, 179 | field_b: 0x00FFFF00, 180 | }; 181 | let mut reader = 182 | StructReader::new(size_of_val(&expected_data), align_of_val(&expected_data)); 183 | let byte_buffer: &mut [u8; 8] = unsafe { &mut *(reader.ptr_mut() as *mut [u8; 8]) }; 184 | byte_buffer[0] = 0b10000001; 185 | byte_buffer[4] = 0x0; 186 | byte_buffer[5] = 0xFF; 187 | byte_buffer[6] = 0xFF; 188 | byte_buffer[7] = 0x0; 189 | let actual_data: &Data = unsafe { reader.read() }; 190 | assert_eq!(actual_data.field_a, expected_data.field_a); 191 | assert_eq!(actual_data.field_b, expected_data.field_b); 192 | } 193 | 194 | #[test] 195 | #[should_panic] 196 | fn reader_overflow() { 197 | unsafe { StructReader::new(1, align_of_val(&1)).read::() }; 198 | } 199 | 200 | #[test] 201 | fn writer_basic() { 202 | let mut buf = StructWriter::new(20, 4); 203 | *unsafe { buf.write::() } = 0; 204 | //Keep bit patterns symmetrical so that this doesn't fail on big-endian systems 205 | *unsafe { buf.write::() } = 0xCCCC; 206 | *unsafe { buf.write::() } = 0x00FFFF00; 207 | *unsafe { buf.write::() } = 0x80808080; 208 | *unsafe { buf.write::() } = 0xFFFFFFFF; 209 | 210 | let slice: &[u8] = unsafe { std::slice::from_raw_parts(buf.ptr(), 16) }; 211 | assert_eq!( 212 | slice, 213 | &[0, 0, 204, 204, 0, 255, 255, 0, 128, 128, 128, 128, 255, 255, 255, 255] 214 | ); 215 | } 216 | 217 | #[test] 218 | #[should_panic] 219 | fn writer_unaligned() { 220 | let mut buf = StructWriter::new(8, 4); 221 | *unsafe { buf.write::() } = 0; 222 | *unsafe { buf.write::() } = 0xFFFFFFFF; 223 | } 224 | 225 | #[test] 226 | #[should_panic] 227 | fn writer_overflow() { 228 | let mut buf = StructWriter::new(16, 4); 229 | *unsafe { buf.write::() } = 0xFFFFFFFF; 230 | *unsafe { buf.write::() } = 0xFFFFFF00; 231 | *unsafe { buf.write::() } = 0xFFFF00FF; 232 | *unsafe { buf.write::() } = 0xFF00FFFF; 233 | 234 | //Panic here 235 | *unsafe { buf.write::() } = 5; 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /src/wireguard_nt_raw.rs: -------------------------------------------------------------------------------- 1 | /* automatically generated by rust-bindgen 0.59.1 */ 2 | 3 | #[repr(C)] 4 | #[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] 5 | pub struct __BindgenBitfieldUnit { 6 | storage: Storage, 7 | } 8 | impl __BindgenBitfieldUnit { 9 | #[inline] 10 | pub const fn new(storage: Storage) -> Self { 11 | Self { storage } 12 | } 13 | } 14 | impl __BindgenBitfieldUnit 15 | where 16 | Storage: AsRef<[u8]> + AsMut<[u8]>, 17 | { 18 | #[inline] 19 | pub fn get_bit(&self, index: usize) -> bool { 20 | debug_assert!(index / 8 < self.storage.as_ref().len()); 21 | let byte_index = index / 8; 22 | let byte = self.storage.as_ref()[byte_index]; 23 | let bit_index = if cfg!(target_endian = "big") { 24 | 7 - (index % 8) 25 | } else { 26 | index % 8 27 | }; 28 | let mask = 1 << bit_index; 29 | byte & mask == mask 30 | } 31 | #[inline] 32 | pub fn set_bit(&mut self, index: usize, val: bool) { 33 | debug_assert!(index / 8 < self.storage.as_ref().len()); 34 | let byte_index = index / 8; 35 | let byte = &mut self.storage.as_mut()[byte_index]; 36 | let bit_index = if cfg!(target_endian = "big") { 37 | 7 - (index % 8) 38 | } else { 39 | index % 8 40 | }; 41 | let mask = 1 << bit_index; 42 | if val { 43 | *byte |= mask; 44 | } else { 45 | *byte &= !mask; 46 | } 47 | } 48 | #[inline] 49 | pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { 50 | debug_assert!(bit_width <= 64); 51 | debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); 52 | debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); 53 | let mut val = 0; 54 | for i in 0..(bit_width as usize) { 55 | if self.get_bit(i + bit_offset) { 56 | let index = if cfg!(target_endian = "big") { 57 | bit_width as usize - 1 - i 58 | } else { 59 | i 60 | }; 61 | val |= 1 << index; 62 | } 63 | } 64 | val 65 | } 66 | #[inline] 67 | pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { 68 | debug_assert!(bit_width <= 64); 69 | debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); 70 | debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); 71 | for i in 0..(bit_width as usize) { 72 | let mask = 1 << i; 73 | let val_bit_is_set = val & mask == mask; 74 | let index = if cfg!(target_endian = "big") { 75 | bit_width as usize - 1 - i 76 | } else { 77 | i 78 | }; 79 | self.set_bit(index + bit_offset, val_bit_is_set); 80 | } 81 | } 82 | } 83 | pub type wchar_t = ::std::os::raw::c_ushort; 84 | pub type ULONG = ::std::os::raw::c_ulong; 85 | pub type USHORT = ::std::os::raw::c_ushort; 86 | pub type UCHAR = ::std::os::raw::c_uchar; 87 | pub type DWORD = ::std::os::raw::c_ulong; 88 | pub type BOOL = ::std::os::raw::c_int; 89 | pub type BYTE = ::std::os::raw::c_uchar; 90 | pub type WORD = ::std::os::raw::c_ushort; 91 | pub type ULONG64 = ::std::os::raw::c_ulonglong; 92 | pub type DWORD64 = ::std::os::raw::c_ulonglong; 93 | pub type CHAR = ::std::os::raw::c_char; 94 | pub type WCHAR = wchar_t; 95 | pub type LPCWSTR = *const WCHAR; 96 | #[repr(C)] 97 | #[derive(Debug, Copy, Clone)] 98 | pub struct _GUID { 99 | pub Data1: ::std::os::raw::c_ulong, 100 | pub Data2: ::std::os::raw::c_ushort, 101 | pub Data3: ::std::os::raw::c_ushort, 102 | pub Data4: [::std::os::raw::c_uchar; 8usize], 103 | } 104 | #[test] 105 | fn bindgen_test_layout__GUID() { 106 | assert_eq!( 107 | ::std::mem::size_of::<_GUID>(), 108 | 16usize, 109 | concat!("Size of: ", stringify!(_GUID)) 110 | ); 111 | assert_eq!( 112 | ::std::mem::align_of::<_GUID>(), 113 | 4usize, 114 | concat!("Alignment of ", stringify!(_GUID)) 115 | ); 116 | assert_eq!( 117 | unsafe { &(*(::std::ptr::null::<_GUID>())).Data1 as *const _ as usize }, 118 | 0usize, 119 | concat!( 120 | "Offset of field: ", 121 | stringify!(_GUID), 122 | "::", 123 | stringify!(Data1) 124 | ) 125 | ); 126 | assert_eq!( 127 | unsafe { &(*(::std::ptr::null::<_GUID>())).Data2 as *const _ as usize }, 128 | 4usize, 129 | concat!( 130 | "Offset of field: ", 131 | stringify!(_GUID), 132 | "::", 133 | stringify!(Data2) 134 | ) 135 | ); 136 | assert_eq!( 137 | unsafe { &(*(::std::ptr::null::<_GUID>())).Data3 as *const _ as usize }, 138 | 6usize, 139 | concat!( 140 | "Offset of field: ", 141 | stringify!(_GUID), 142 | "::", 143 | stringify!(Data3) 144 | ) 145 | ); 146 | assert_eq!( 147 | unsafe { &(*(::std::ptr::null::<_GUID>())).Data4 as *const _ as usize }, 148 | 8usize, 149 | concat!( 150 | "Offset of field: ", 151 | stringify!(_GUID), 152 | "::", 153 | stringify!(Data4) 154 | ) 155 | ); 156 | } 157 | pub type GUID = _GUID; 158 | #[repr(C)] 159 | #[derive(Copy, Clone)] 160 | pub struct in_addr { 161 | pub S_un: in_addr__bindgen_ty_1, 162 | } 163 | #[repr(C)] 164 | #[derive(Copy, Clone)] 165 | pub union in_addr__bindgen_ty_1 { 166 | pub S_un_b: in_addr__bindgen_ty_1__bindgen_ty_1, 167 | pub S_un_w: in_addr__bindgen_ty_1__bindgen_ty_2, 168 | pub S_addr: ULONG, 169 | } 170 | #[repr(C)] 171 | #[derive(Debug, Copy, Clone)] 172 | pub struct in_addr__bindgen_ty_1__bindgen_ty_1 { 173 | pub s_b1: UCHAR, 174 | pub s_b2: UCHAR, 175 | pub s_b3: UCHAR, 176 | pub s_b4: UCHAR, 177 | } 178 | #[test] 179 | fn bindgen_test_layout_in_addr__bindgen_ty_1__bindgen_ty_1() { 180 | assert_eq!( 181 | ::std::mem::size_of::(), 182 | 4usize, 183 | concat!("Size of: ", stringify!(in_addr__bindgen_ty_1__bindgen_ty_1)) 184 | ); 185 | assert_eq!( 186 | ::std::mem::align_of::(), 187 | 1usize, 188 | concat!( 189 | "Alignment of ", 190 | stringify!(in_addr__bindgen_ty_1__bindgen_ty_1) 191 | ) 192 | ); 193 | assert_eq!( 194 | unsafe { 195 | &(*(::std::ptr::null::())).s_b1 as *const _ 196 | as usize 197 | }, 198 | 0usize, 199 | concat!( 200 | "Offset of field: ", 201 | stringify!(in_addr__bindgen_ty_1__bindgen_ty_1), 202 | "::", 203 | stringify!(s_b1) 204 | ) 205 | ); 206 | assert_eq!( 207 | unsafe { 208 | &(*(::std::ptr::null::())).s_b2 as *const _ 209 | as usize 210 | }, 211 | 1usize, 212 | concat!( 213 | "Offset of field: ", 214 | stringify!(in_addr__bindgen_ty_1__bindgen_ty_1), 215 | "::", 216 | stringify!(s_b2) 217 | ) 218 | ); 219 | assert_eq!( 220 | unsafe { 221 | &(*(::std::ptr::null::())).s_b3 as *const _ 222 | as usize 223 | }, 224 | 2usize, 225 | concat!( 226 | "Offset of field: ", 227 | stringify!(in_addr__bindgen_ty_1__bindgen_ty_1), 228 | "::", 229 | stringify!(s_b3) 230 | ) 231 | ); 232 | assert_eq!( 233 | unsafe { 234 | &(*(::std::ptr::null::())).s_b4 as *const _ 235 | as usize 236 | }, 237 | 3usize, 238 | concat!( 239 | "Offset of field: ", 240 | stringify!(in_addr__bindgen_ty_1__bindgen_ty_1), 241 | "::", 242 | stringify!(s_b4) 243 | ) 244 | ); 245 | } 246 | #[repr(C)] 247 | #[derive(Debug, Copy, Clone)] 248 | pub struct in_addr__bindgen_ty_1__bindgen_ty_2 { 249 | pub s_w1: USHORT, 250 | pub s_w2: USHORT, 251 | } 252 | #[test] 253 | fn bindgen_test_layout_in_addr__bindgen_ty_1__bindgen_ty_2() { 254 | assert_eq!( 255 | ::std::mem::size_of::(), 256 | 4usize, 257 | concat!("Size of: ", stringify!(in_addr__bindgen_ty_1__bindgen_ty_2)) 258 | ); 259 | assert_eq!( 260 | ::std::mem::align_of::(), 261 | 2usize, 262 | concat!( 263 | "Alignment of ", 264 | stringify!(in_addr__bindgen_ty_1__bindgen_ty_2) 265 | ) 266 | ); 267 | assert_eq!( 268 | unsafe { 269 | &(*(::std::ptr::null::())).s_w1 as *const _ 270 | as usize 271 | }, 272 | 0usize, 273 | concat!( 274 | "Offset of field: ", 275 | stringify!(in_addr__bindgen_ty_1__bindgen_ty_2), 276 | "::", 277 | stringify!(s_w1) 278 | ) 279 | ); 280 | assert_eq!( 281 | unsafe { 282 | &(*(::std::ptr::null::())).s_w2 as *const _ 283 | as usize 284 | }, 285 | 2usize, 286 | concat!( 287 | "Offset of field: ", 288 | stringify!(in_addr__bindgen_ty_1__bindgen_ty_2), 289 | "::", 290 | stringify!(s_w2) 291 | ) 292 | ); 293 | } 294 | #[test] 295 | fn bindgen_test_layout_in_addr__bindgen_ty_1() { 296 | assert_eq!( 297 | ::std::mem::size_of::(), 298 | 4usize, 299 | concat!("Size of: ", stringify!(in_addr__bindgen_ty_1)) 300 | ); 301 | assert_eq!( 302 | ::std::mem::align_of::(), 303 | 4usize, 304 | concat!("Alignment of ", stringify!(in_addr__bindgen_ty_1)) 305 | ); 306 | assert_eq!( 307 | unsafe { &(*(::std::ptr::null::())).S_un_b as *const _ as usize }, 308 | 0usize, 309 | concat!( 310 | "Offset of field: ", 311 | stringify!(in_addr__bindgen_ty_1), 312 | "::", 313 | stringify!(S_un_b) 314 | ) 315 | ); 316 | assert_eq!( 317 | unsafe { &(*(::std::ptr::null::())).S_un_w as *const _ as usize }, 318 | 0usize, 319 | concat!( 320 | "Offset of field: ", 321 | stringify!(in_addr__bindgen_ty_1), 322 | "::", 323 | stringify!(S_un_w) 324 | ) 325 | ); 326 | assert_eq!( 327 | unsafe { &(*(::std::ptr::null::())).S_addr as *const _ as usize }, 328 | 0usize, 329 | concat!( 330 | "Offset of field: ", 331 | stringify!(in_addr__bindgen_ty_1), 332 | "::", 333 | stringify!(S_addr) 334 | ) 335 | ); 336 | } 337 | #[test] 338 | fn bindgen_test_layout_in_addr() { 339 | assert_eq!( 340 | ::std::mem::size_of::(), 341 | 4usize, 342 | concat!("Size of: ", stringify!(in_addr)) 343 | ); 344 | assert_eq!( 345 | ::std::mem::align_of::(), 346 | 4usize, 347 | concat!("Alignment of ", stringify!(in_addr)) 348 | ); 349 | assert_eq!( 350 | unsafe { &(*(::std::ptr::null::())).S_un as *const _ as usize }, 351 | 0usize, 352 | concat!( 353 | "Offset of field: ", 354 | stringify!(in_addr), 355 | "::", 356 | stringify!(S_un) 357 | ) 358 | ); 359 | } 360 | pub type IN_ADDR = in_addr; 361 | pub type ADDRESS_FAMILY = USHORT; 362 | #[repr(C)] 363 | #[derive(Copy, Clone)] 364 | pub struct SCOPE_ID { 365 | pub __bindgen_anon_1: SCOPE_ID__bindgen_ty_1, 366 | } 367 | #[repr(C)] 368 | #[derive(Copy, Clone)] 369 | pub union SCOPE_ID__bindgen_ty_1 { 370 | pub __bindgen_anon_1: SCOPE_ID__bindgen_ty_1__bindgen_ty_1, 371 | pub Value: ULONG, 372 | } 373 | #[repr(C)] 374 | #[repr(align(4))] 375 | #[derive(Debug, Copy, Clone)] 376 | pub struct SCOPE_ID__bindgen_ty_1__bindgen_ty_1 { 377 | pub _bitfield_align_1: [u32; 0], 378 | pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>, 379 | } 380 | #[test] 381 | fn bindgen_test_layout_SCOPE_ID__bindgen_ty_1__bindgen_ty_1() { 382 | assert_eq!( 383 | ::std::mem::size_of::(), 384 | 4usize, 385 | concat!( 386 | "Size of: ", 387 | stringify!(SCOPE_ID__bindgen_ty_1__bindgen_ty_1) 388 | ) 389 | ); 390 | assert_eq!( 391 | ::std::mem::align_of::(), 392 | 4usize, 393 | concat!( 394 | "Alignment of ", 395 | stringify!(SCOPE_ID__bindgen_ty_1__bindgen_ty_1) 396 | ) 397 | ); 398 | } 399 | impl SCOPE_ID__bindgen_ty_1__bindgen_ty_1 { 400 | #[inline] 401 | pub fn Zone(&self) -> ULONG { 402 | unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 28u8) as u32) } 403 | } 404 | #[inline] 405 | pub fn set_Zone(&mut self, val: ULONG) { 406 | unsafe { 407 | let val: u32 = ::std::mem::transmute(val); 408 | self._bitfield_1.set(0usize, 28u8, val as u64) 409 | } 410 | } 411 | #[inline] 412 | pub fn Level(&self) -> ULONG { 413 | unsafe { ::std::mem::transmute(self._bitfield_1.get(28usize, 4u8) as u32) } 414 | } 415 | #[inline] 416 | pub fn set_Level(&mut self, val: ULONG) { 417 | unsafe { 418 | let val: u32 = ::std::mem::transmute(val); 419 | self._bitfield_1.set(28usize, 4u8, val as u64) 420 | } 421 | } 422 | #[inline] 423 | pub fn new_bitfield_1(Zone: ULONG, Level: ULONG) -> __BindgenBitfieldUnit<[u8; 4usize]> { 424 | let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default(); 425 | __bindgen_bitfield_unit.set(0usize, 28u8, { 426 | let Zone: u32 = unsafe { ::std::mem::transmute(Zone) }; 427 | Zone as u64 428 | }); 429 | __bindgen_bitfield_unit.set(28usize, 4u8, { 430 | let Level: u32 = unsafe { ::std::mem::transmute(Level) }; 431 | Level as u64 432 | }); 433 | __bindgen_bitfield_unit 434 | } 435 | } 436 | #[test] 437 | fn bindgen_test_layout_SCOPE_ID__bindgen_ty_1() { 438 | assert_eq!( 439 | ::std::mem::size_of::(), 440 | 4usize, 441 | concat!("Size of: ", stringify!(SCOPE_ID__bindgen_ty_1)) 442 | ); 443 | assert_eq!( 444 | ::std::mem::align_of::(), 445 | 4usize, 446 | concat!("Alignment of ", stringify!(SCOPE_ID__bindgen_ty_1)) 447 | ); 448 | assert_eq!( 449 | unsafe { &(*(::std::ptr::null::())).Value as *const _ as usize }, 450 | 0usize, 451 | concat!( 452 | "Offset of field: ", 453 | stringify!(SCOPE_ID__bindgen_ty_1), 454 | "::", 455 | stringify!(Value) 456 | ) 457 | ); 458 | } 459 | #[test] 460 | fn bindgen_test_layout_SCOPE_ID() { 461 | assert_eq!( 462 | ::std::mem::size_of::(), 463 | 4usize, 464 | concat!("Size of: ", stringify!(SCOPE_ID)) 465 | ); 466 | assert_eq!( 467 | ::std::mem::align_of::(), 468 | 4usize, 469 | concat!("Alignment of ", stringify!(SCOPE_ID)) 470 | ); 471 | } 472 | #[repr(C)] 473 | #[derive(Copy, Clone)] 474 | pub struct sockaddr_in { 475 | pub sin_family: ADDRESS_FAMILY, 476 | pub sin_port: USHORT, 477 | pub sin_addr: IN_ADDR, 478 | pub sin_zero: [CHAR; 8usize], 479 | } 480 | #[test] 481 | fn bindgen_test_layout_sockaddr_in() { 482 | assert_eq!( 483 | ::std::mem::size_of::(), 484 | 16usize, 485 | concat!("Size of: ", stringify!(sockaddr_in)) 486 | ); 487 | assert_eq!( 488 | ::std::mem::align_of::(), 489 | 4usize, 490 | concat!("Alignment of ", stringify!(sockaddr_in)) 491 | ); 492 | assert_eq!( 493 | unsafe { &(*(::std::ptr::null::())).sin_family as *const _ as usize }, 494 | 0usize, 495 | concat!( 496 | "Offset of field: ", 497 | stringify!(sockaddr_in), 498 | "::", 499 | stringify!(sin_family) 500 | ) 501 | ); 502 | assert_eq!( 503 | unsafe { &(*(::std::ptr::null::())).sin_port as *const _ as usize }, 504 | 2usize, 505 | concat!( 506 | "Offset of field: ", 507 | stringify!(sockaddr_in), 508 | "::", 509 | stringify!(sin_port) 510 | ) 511 | ); 512 | assert_eq!( 513 | unsafe { &(*(::std::ptr::null::())).sin_addr as *const _ as usize }, 514 | 4usize, 515 | concat!( 516 | "Offset of field: ", 517 | stringify!(sockaddr_in), 518 | "::", 519 | stringify!(sin_addr) 520 | ) 521 | ); 522 | assert_eq!( 523 | unsafe { &(*(::std::ptr::null::())).sin_zero as *const _ as usize }, 524 | 8usize, 525 | concat!( 526 | "Offset of field: ", 527 | stringify!(sockaddr_in), 528 | "::", 529 | stringify!(sin_zero) 530 | ) 531 | ); 532 | } 533 | pub type SOCKADDR_IN = sockaddr_in; 534 | #[repr(C)] 535 | #[derive(Copy, Clone)] 536 | pub struct in6_addr { 537 | pub u: in6_addr__bindgen_ty_1, 538 | } 539 | #[repr(C)] 540 | #[derive(Copy, Clone)] 541 | pub union in6_addr__bindgen_ty_1 { 542 | pub Byte: [UCHAR; 16usize], 543 | pub Word: [USHORT; 8usize], 544 | } 545 | #[test] 546 | fn bindgen_test_layout_in6_addr__bindgen_ty_1() { 547 | assert_eq!( 548 | ::std::mem::size_of::(), 549 | 16usize, 550 | concat!("Size of: ", stringify!(in6_addr__bindgen_ty_1)) 551 | ); 552 | assert_eq!( 553 | ::std::mem::align_of::(), 554 | 2usize, 555 | concat!("Alignment of ", stringify!(in6_addr__bindgen_ty_1)) 556 | ); 557 | assert_eq!( 558 | unsafe { &(*(::std::ptr::null::())).Byte as *const _ as usize }, 559 | 0usize, 560 | concat!( 561 | "Offset of field: ", 562 | stringify!(in6_addr__bindgen_ty_1), 563 | "::", 564 | stringify!(Byte) 565 | ) 566 | ); 567 | assert_eq!( 568 | unsafe { &(*(::std::ptr::null::())).Word as *const _ as usize }, 569 | 0usize, 570 | concat!( 571 | "Offset of field: ", 572 | stringify!(in6_addr__bindgen_ty_1), 573 | "::", 574 | stringify!(Word) 575 | ) 576 | ); 577 | } 578 | #[test] 579 | fn bindgen_test_layout_in6_addr() { 580 | assert_eq!( 581 | ::std::mem::size_of::(), 582 | 16usize, 583 | concat!("Size of: ", stringify!(in6_addr)) 584 | ); 585 | assert_eq!( 586 | ::std::mem::align_of::(), 587 | 2usize, 588 | concat!("Alignment of ", stringify!(in6_addr)) 589 | ); 590 | assert_eq!( 591 | unsafe { &(*(::std::ptr::null::())).u as *const _ as usize }, 592 | 0usize, 593 | concat!( 594 | "Offset of field: ", 595 | stringify!(in6_addr), 596 | "::", 597 | stringify!(u) 598 | ) 599 | ); 600 | } 601 | pub type IN6_ADDR = in6_addr; 602 | #[repr(C)] 603 | #[derive(Copy, Clone)] 604 | pub union _NET_LUID_LH { 605 | pub Value: ULONG64, 606 | pub Info: _NET_LUID_LH__bindgen_ty_1, 607 | } 608 | #[repr(C)] 609 | #[repr(align(8))] 610 | #[derive(Debug, Copy, Clone)] 611 | pub struct _NET_LUID_LH__bindgen_ty_1 { 612 | pub _bitfield_align_1: [u32; 0], 613 | pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>, 614 | } 615 | #[test] 616 | fn bindgen_test_layout__NET_LUID_LH__bindgen_ty_1() { 617 | assert_eq!( 618 | ::std::mem::size_of::<_NET_LUID_LH__bindgen_ty_1>(), 619 | 8usize, 620 | concat!("Size of: ", stringify!(_NET_LUID_LH__bindgen_ty_1)) 621 | ); 622 | assert_eq!( 623 | ::std::mem::align_of::<_NET_LUID_LH__bindgen_ty_1>(), 624 | 8usize, 625 | concat!("Alignment of ", stringify!(_NET_LUID_LH__bindgen_ty_1)) 626 | ); 627 | } 628 | impl _NET_LUID_LH__bindgen_ty_1 { 629 | #[inline] 630 | pub fn Reserved(&self) -> ULONG64 { 631 | unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u64) } 632 | } 633 | #[inline] 634 | pub fn set_Reserved(&mut self, val: ULONG64) { 635 | unsafe { 636 | let val: u64 = ::std::mem::transmute(val); 637 | self._bitfield_1.set(0usize, 24u8, val as u64) 638 | } 639 | } 640 | #[inline] 641 | pub fn NetLuidIndex(&self) -> ULONG64 { 642 | unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 24u8) as u64) } 643 | } 644 | #[inline] 645 | pub fn set_NetLuidIndex(&mut self, val: ULONG64) { 646 | unsafe { 647 | let val: u64 = ::std::mem::transmute(val); 648 | self._bitfield_1.set(24usize, 24u8, val as u64) 649 | } 650 | } 651 | #[inline] 652 | pub fn IfType(&self) -> ULONG64 { 653 | unsafe { ::std::mem::transmute(self._bitfield_1.get(48usize, 16u8) as u64) } 654 | } 655 | #[inline] 656 | pub fn set_IfType(&mut self, val: ULONG64) { 657 | unsafe { 658 | let val: u64 = ::std::mem::transmute(val); 659 | self._bitfield_1.set(48usize, 16u8, val as u64) 660 | } 661 | } 662 | #[inline] 663 | pub fn new_bitfield_1( 664 | Reserved: ULONG64, 665 | NetLuidIndex: ULONG64, 666 | IfType: ULONG64, 667 | ) -> __BindgenBitfieldUnit<[u8; 8usize]> { 668 | let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default(); 669 | __bindgen_bitfield_unit.set(0usize, 24u8, { 670 | let Reserved: u64 = unsafe { ::std::mem::transmute(Reserved) }; 671 | Reserved as u64 672 | }); 673 | __bindgen_bitfield_unit.set(24usize, 24u8, { 674 | let NetLuidIndex: u64 = unsafe { ::std::mem::transmute(NetLuidIndex) }; 675 | NetLuidIndex as u64 676 | }); 677 | __bindgen_bitfield_unit.set(48usize, 16u8, { 678 | let IfType: u64 = unsafe { ::std::mem::transmute(IfType) }; 679 | IfType as u64 680 | }); 681 | __bindgen_bitfield_unit 682 | } 683 | } 684 | #[test] 685 | fn bindgen_test_layout__NET_LUID_LH() { 686 | assert_eq!( 687 | ::std::mem::size_of::<_NET_LUID_LH>(), 688 | 8usize, 689 | concat!("Size of: ", stringify!(_NET_LUID_LH)) 690 | ); 691 | assert_eq!( 692 | ::std::mem::align_of::<_NET_LUID_LH>(), 693 | 8usize, 694 | concat!("Alignment of ", stringify!(_NET_LUID_LH)) 695 | ); 696 | assert_eq!( 697 | unsafe { &(*(::std::ptr::null::<_NET_LUID_LH>())).Value as *const _ as usize }, 698 | 0usize, 699 | concat!( 700 | "Offset of field: ", 701 | stringify!(_NET_LUID_LH), 702 | "::", 703 | stringify!(Value) 704 | ) 705 | ); 706 | assert_eq!( 707 | unsafe { &(*(::std::ptr::null::<_NET_LUID_LH>())).Info as *const _ as usize }, 708 | 0usize, 709 | concat!( 710 | "Offset of field: ", 711 | stringify!(_NET_LUID_LH), 712 | "::", 713 | stringify!(Info) 714 | ) 715 | ); 716 | } 717 | pub type NET_LUID_LH = _NET_LUID_LH; 718 | pub type NET_LUID = NET_LUID_LH; 719 | #[repr(C)] 720 | #[derive(Copy, Clone)] 721 | pub struct sockaddr_in6 { 722 | pub sin6_family: ADDRESS_FAMILY, 723 | pub sin6_port: USHORT, 724 | pub sin6_flowinfo: ULONG, 725 | pub sin6_addr: IN6_ADDR, 726 | pub __bindgen_anon_1: sockaddr_in6__bindgen_ty_1, 727 | } 728 | #[repr(C)] 729 | #[derive(Copy, Clone)] 730 | pub union sockaddr_in6__bindgen_ty_1 { 731 | pub sin6_scope_id: ULONG, 732 | pub sin6_scope_struct: SCOPE_ID, 733 | } 734 | #[test] 735 | fn bindgen_test_layout_sockaddr_in6__bindgen_ty_1() { 736 | assert_eq!( 737 | ::std::mem::size_of::(), 738 | 4usize, 739 | concat!("Size of: ", stringify!(sockaddr_in6__bindgen_ty_1)) 740 | ); 741 | assert_eq!( 742 | ::std::mem::align_of::(), 743 | 4usize, 744 | concat!("Alignment of ", stringify!(sockaddr_in6__bindgen_ty_1)) 745 | ); 746 | assert_eq!( 747 | unsafe { 748 | &(*(::std::ptr::null::())).sin6_scope_id as *const _ 749 | as usize 750 | }, 751 | 0usize, 752 | concat!( 753 | "Offset of field: ", 754 | stringify!(sockaddr_in6__bindgen_ty_1), 755 | "::", 756 | stringify!(sin6_scope_id) 757 | ) 758 | ); 759 | assert_eq!( 760 | unsafe { 761 | &(*(::std::ptr::null::())).sin6_scope_struct as *const _ 762 | as usize 763 | }, 764 | 0usize, 765 | concat!( 766 | "Offset of field: ", 767 | stringify!(sockaddr_in6__bindgen_ty_1), 768 | "::", 769 | stringify!(sin6_scope_struct) 770 | ) 771 | ); 772 | } 773 | #[test] 774 | fn bindgen_test_layout_sockaddr_in6() { 775 | assert_eq!( 776 | ::std::mem::size_of::(), 777 | 28usize, 778 | concat!("Size of: ", stringify!(sockaddr_in6)) 779 | ); 780 | assert_eq!( 781 | ::std::mem::align_of::(), 782 | 4usize, 783 | concat!("Alignment of ", stringify!(sockaddr_in6)) 784 | ); 785 | assert_eq!( 786 | unsafe { &(*(::std::ptr::null::())).sin6_family as *const _ as usize }, 787 | 0usize, 788 | concat!( 789 | "Offset of field: ", 790 | stringify!(sockaddr_in6), 791 | "::", 792 | stringify!(sin6_family) 793 | ) 794 | ); 795 | assert_eq!( 796 | unsafe { &(*(::std::ptr::null::())).sin6_port as *const _ as usize }, 797 | 2usize, 798 | concat!( 799 | "Offset of field: ", 800 | stringify!(sockaddr_in6), 801 | "::", 802 | stringify!(sin6_port) 803 | ) 804 | ); 805 | assert_eq!( 806 | unsafe { &(*(::std::ptr::null::())).sin6_flowinfo as *const _ as usize }, 807 | 4usize, 808 | concat!( 809 | "Offset of field: ", 810 | stringify!(sockaddr_in6), 811 | "::", 812 | stringify!(sin6_flowinfo) 813 | ) 814 | ); 815 | assert_eq!( 816 | unsafe { &(*(::std::ptr::null::())).sin6_addr as *const _ as usize }, 817 | 8usize, 818 | concat!( 819 | "Offset of field: ", 820 | stringify!(sockaddr_in6), 821 | "::", 822 | stringify!(sin6_addr) 823 | ) 824 | ); 825 | } 826 | pub type SOCKADDR_IN6_LH = sockaddr_in6; 827 | pub type SOCKADDR_IN6 = SOCKADDR_IN6_LH; 828 | #[repr(C)] 829 | #[derive(Copy, Clone)] 830 | pub union _SOCKADDR_INET { 831 | pub Ipv4: SOCKADDR_IN, 832 | pub Ipv6: SOCKADDR_IN6, 833 | pub si_family: ADDRESS_FAMILY, 834 | } 835 | #[test] 836 | fn bindgen_test_layout__SOCKADDR_INET() { 837 | assert_eq!( 838 | ::std::mem::size_of::<_SOCKADDR_INET>(), 839 | 28usize, 840 | concat!("Size of: ", stringify!(_SOCKADDR_INET)) 841 | ); 842 | assert_eq!( 843 | ::std::mem::align_of::<_SOCKADDR_INET>(), 844 | 4usize, 845 | concat!("Alignment of ", stringify!(_SOCKADDR_INET)) 846 | ); 847 | assert_eq!( 848 | unsafe { &(*(::std::ptr::null::<_SOCKADDR_INET>())).Ipv4 as *const _ as usize }, 849 | 0usize, 850 | concat!( 851 | "Offset of field: ", 852 | stringify!(_SOCKADDR_INET), 853 | "::", 854 | stringify!(Ipv4) 855 | ) 856 | ); 857 | assert_eq!( 858 | unsafe { &(*(::std::ptr::null::<_SOCKADDR_INET>())).Ipv6 as *const _ as usize }, 859 | 0usize, 860 | concat!( 861 | "Offset of field: ", 862 | stringify!(_SOCKADDR_INET), 863 | "::", 864 | stringify!(Ipv6) 865 | ) 866 | ); 867 | assert_eq!( 868 | unsafe { &(*(::std::ptr::null::<_SOCKADDR_INET>())).si_family as *const _ as usize }, 869 | 0usize, 870 | concat!( 871 | "Offset of field: ", 872 | stringify!(_SOCKADDR_INET), 873 | "::", 874 | stringify!(si_family) 875 | ) 876 | ); 877 | } 878 | pub type SOCKADDR_INET = _SOCKADDR_INET; 879 | #[repr(C)] 880 | #[derive(Debug, Copy, Clone)] 881 | pub struct _WIREGUARD_ADAPTER { 882 | _unused: [u8; 0], 883 | } 884 | #[doc = " A handle representing WireGuard adapter"] 885 | pub type WIREGUARD_ADAPTER_HANDLE = *mut _WIREGUARD_ADAPTER; 886 | #[doc = "< Informational"] 887 | pub const WIREGUARD_LOGGER_LEVEL_WIREGUARD_LOG_INFO: WIREGUARD_LOGGER_LEVEL = 0; 888 | #[doc = "< Warning"] 889 | pub const WIREGUARD_LOGGER_LEVEL_WIREGUARD_LOG_WARN: WIREGUARD_LOGGER_LEVEL = 1; 890 | #[doc = "< Error"] 891 | pub const WIREGUARD_LOGGER_LEVEL_WIREGUARD_LOG_ERR: WIREGUARD_LOGGER_LEVEL = 2; 892 | #[doc = " Determines the level of logging, passed to WIREGUARD_LOGGER_CALLBACK."] 893 | pub type WIREGUARD_LOGGER_LEVEL = ::std::os::raw::c_int; 894 | #[doc = " Called by internal logger to report diagnostic messages"] 895 | #[doc = ""] 896 | #[doc = " @param Level Message level."] 897 | #[doc = ""] 898 | #[doc = " @param Timestamp Message timestamp in in 100ns intervals since 1601-01-01 UTC."] 899 | #[doc = ""] 900 | #[doc = " @param Message Message text."] 901 | pub type WIREGUARD_LOGGER_CALLBACK = ::std::option::Option< 902 | unsafe extern "C" fn(Level: WIREGUARD_LOGGER_LEVEL, Timestamp: DWORD64, Message: LPCWSTR), 903 | >; 904 | #[doc = "< No logs are generated from the driver."] 905 | pub const WIREGUARD_ADAPTER_LOG_STATE_WIREGUARD_ADAPTER_LOG_OFF: WIREGUARD_ADAPTER_LOG_STATE = 0; 906 | #[doc = "< Logs are generated from the driver."] 907 | pub const WIREGUARD_ADAPTER_LOG_STATE_WIREGUARD_ADAPTER_LOG_ON: WIREGUARD_ADAPTER_LOG_STATE = 1; 908 | #[doc = "< Logs are generated from the driver, index-prefixed."] 909 | pub const WIREGUARD_ADAPTER_LOG_STATE_WIREGUARD_ADAPTER_LOG_ON_WITH_PREFIX: 910 | WIREGUARD_ADAPTER_LOG_STATE = 2; 911 | #[doc = " Whether and how logs from the driver are collected for the callback function."] 912 | pub type WIREGUARD_ADAPTER_LOG_STATE = ::std::os::raw::c_int; 913 | #[doc = "< Down"] 914 | pub const WIREGUARD_ADAPTER_STATE_WIREGUARD_ADAPTER_STATE_DOWN: WIREGUARD_ADAPTER_STATE = 0; 915 | #[doc = "< Up"] 916 | pub const WIREGUARD_ADAPTER_STATE_WIREGUARD_ADAPTER_STATE_UP: WIREGUARD_ADAPTER_STATE = 1; 917 | #[doc = " Determines the state of the adapter."] 918 | pub type WIREGUARD_ADAPTER_STATE = ::std::os::raw::c_int; 919 | pub type WIREGUARD_ALLOWED_IP = _WIREGUARD_ALLOWED_IP; 920 | #[repr(C)] 921 | #[repr(align(8))] 922 | #[derive(Copy, Clone)] 923 | pub struct _WIREGUARD_ALLOWED_IP { 924 | #[doc = "< IP address"] 925 | pub Address: _WIREGUARD_ALLOWED_IP__bindgen_ty_1, 926 | #[doc = "< Address family, either AF_INET or AF_INET6"] 927 | pub AddressFamily: ADDRESS_FAMILY, 928 | #[doc = "< CIDR of allowed IPs"] 929 | pub Cidr: BYTE, 930 | } 931 | #[repr(C)] 932 | #[derive(Copy, Clone)] 933 | pub union _WIREGUARD_ALLOWED_IP__bindgen_ty_1 { 934 | pub V4: IN_ADDR, 935 | pub V6: IN6_ADDR, 936 | } 937 | #[test] 938 | fn bindgen_test_layout__WIREGUARD_ALLOWED_IP__bindgen_ty_1() { 939 | assert_eq!( 940 | ::std::mem::size_of::<_WIREGUARD_ALLOWED_IP__bindgen_ty_1>(), 941 | 16usize, 942 | concat!("Size of: ", stringify!(_WIREGUARD_ALLOWED_IP__bindgen_ty_1)) 943 | ); 944 | assert_eq!( 945 | ::std::mem::align_of::<_WIREGUARD_ALLOWED_IP__bindgen_ty_1>(), 946 | 4usize, 947 | concat!( 948 | "Alignment of ", 949 | stringify!(_WIREGUARD_ALLOWED_IP__bindgen_ty_1) 950 | ) 951 | ); 952 | assert_eq!( 953 | unsafe { 954 | &(*(::std::ptr::null::<_WIREGUARD_ALLOWED_IP__bindgen_ty_1>())).V4 as *const _ as usize 955 | }, 956 | 0usize, 957 | concat!( 958 | "Offset of field: ", 959 | stringify!(_WIREGUARD_ALLOWED_IP__bindgen_ty_1), 960 | "::", 961 | stringify!(V4) 962 | ) 963 | ); 964 | assert_eq!( 965 | unsafe { 966 | &(*(::std::ptr::null::<_WIREGUARD_ALLOWED_IP__bindgen_ty_1>())).V6 as *const _ as usize 967 | }, 968 | 0usize, 969 | concat!( 970 | "Offset of field: ", 971 | stringify!(_WIREGUARD_ALLOWED_IP__bindgen_ty_1), 972 | "::", 973 | stringify!(V6) 974 | ) 975 | ); 976 | } 977 | #[test] 978 | fn bindgen_test_layout__WIREGUARD_ALLOWED_IP() { 979 | assert_eq!( 980 | ::std::mem::size_of::<_WIREGUARD_ALLOWED_IP>(), 981 | 24usize, 982 | concat!("Size of: ", stringify!(_WIREGUARD_ALLOWED_IP)) 983 | ); 984 | assert_eq!( 985 | ::std::mem::align_of::<_WIREGUARD_ALLOWED_IP>(), 986 | 8usize, 987 | concat!("Alignment of ", stringify!(_WIREGUARD_ALLOWED_IP)) 988 | ); 989 | assert_eq!( 990 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_ALLOWED_IP>())).Address as *const _ as usize }, 991 | 0usize, 992 | concat!( 993 | "Offset of field: ", 994 | stringify!(_WIREGUARD_ALLOWED_IP), 995 | "::", 996 | stringify!(Address) 997 | ) 998 | ); 999 | assert_eq!( 1000 | unsafe { 1001 | &(*(::std::ptr::null::<_WIREGUARD_ALLOWED_IP>())).AddressFamily as *const _ as usize 1002 | }, 1003 | 16usize, 1004 | concat!( 1005 | "Offset of field: ", 1006 | stringify!(_WIREGUARD_ALLOWED_IP), 1007 | "::", 1008 | stringify!(AddressFamily) 1009 | ) 1010 | ); 1011 | assert_eq!( 1012 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_ALLOWED_IP>())).Cidr as *const _ as usize }, 1013 | 18usize, 1014 | concat!( 1015 | "Offset of field: ", 1016 | stringify!(_WIREGUARD_ALLOWED_IP), 1017 | "::", 1018 | stringify!(Cidr) 1019 | ) 1020 | ); 1021 | } 1022 | #[doc = "< The PublicKey field is set"] 1023 | pub const WIREGUARD_PEER_FLAG_WIREGUARD_PEER_HAS_PUBLIC_KEY: WIREGUARD_PEER_FLAG = 1; 1024 | #[doc = "< The PresharedKey field is set"] 1025 | pub const WIREGUARD_PEER_FLAG_WIREGUARD_PEER_HAS_PRESHARED_KEY: WIREGUARD_PEER_FLAG = 2; 1026 | #[doc = "< The PersistentKeepAlive field is set"] 1027 | pub const WIREGUARD_PEER_FLAG_WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE: WIREGUARD_PEER_FLAG = 4; 1028 | #[doc = "< The Endpoint field is set"] 1029 | pub const WIREGUARD_PEER_FLAG_WIREGUARD_PEER_HAS_ENDPOINT: WIREGUARD_PEER_FLAG = 8; 1030 | #[doc = "< Remove all allowed IPs before adding new ones"] 1031 | pub const WIREGUARD_PEER_FLAG_WIREGUARD_PEER_REPLACE_ALLOWED_IPS: WIREGUARD_PEER_FLAG = 32; 1032 | #[doc = "< Remove specified peer"] 1033 | pub const WIREGUARD_PEER_FLAG_WIREGUARD_PEER_REMOVE: WIREGUARD_PEER_FLAG = 64; 1034 | #[doc = "< Do not add a new peer"] 1035 | pub const WIREGUARD_PEER_FLAG_WIREGUARD_PEER_UPDATE: WIREGUARD_PEER_FLAG = 128; 1036 | pub type WIREGUARD_PEER_FLAG = ::std::os::raw::c_int; 1037 | pub type WIREGUARD_PEER = _WIREGUARD_PEER; 1038 | #[repr(C)] 1039 | #[derive(Copy, Clone)] 1040 | pub struct _WIREGUARD_PEER { 1041 | #[doc = "< Bitwise combination of flags"] 1042 | pub Flags: WIREGUARD_PEER_FLAG, 1043 | #[doc = "< Reserved; must be zero"] 1044 | pub Reserved: DWORD, 1045 | #[doc = "< Public key, the peer's primary identifier"] 1046 | pub PublicKey: [BYTE; 32usize], 1047 | #[doc = "< Preshared key for additional layer of post-quantum resistance"] 1048 | pub PresharedKey: [BYTE; 32usize], 1049 | #[doc = "< Seconds interval, or 0 to disable"] 1050 | pub PersistentKeepalive: WORD, 1051 | #[doc = "< Endpoint, with IP address and UDP port number"] 1052 | pub Endpoint: SOCKADDR_INET, 1053 | #[doc = "< Number of bytes transmitted"] 1054 | pub TxBytes: DWORD64, 1055 | #[doc = "< Number of bytes received"] 1056 | pub RxBytes: DWORD64, 1057 | #[doc = "< Time of the last handshake, in 100ns intervals since 1601-01-01 UTC"] 1058 | pub LastHandshake: DWORD64, 1059 | #[doc = "< Number of allowed IP structs following this struct"] 1060 | pub AllowedIPsCount: DWORD, 1061 | } 1062 | #[test] 1063 | fn bindgen_test_layout__WIREGUARD_PEER() { 1064 | assert_eq!( 1065 | ::std::mem::size_of::<_WIREGUARD_PEER>(), 1066 | 136usize, 1067 | concat!("Size of: ", stringify!(_WIREGUARD_PEER)) 1068 | ); 1069 | assert_eq!( 1070 | ::std::mem::align_of::<_WIREGUARD_PEER>(), 1071 | 8usize, 1072 | concat!("Alignment of ", stringify!(_WIREGUARD_PEER)) 1073 | ); 1074 | assert_eq!( 1075 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_PEER>())).Flags as *const _ as usize }, 1076 | 0usize, 1077 | concat!( 1078 | "Offset of field: ", 1079 | stringify!(_WIREGUARD_PEER), 1080 | "::", 1081 | stringify!(Flags) 1082 | ) 1083 | ); 1084 | assert_eq!( 1085 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_PEER>())).Reserved as *const _ as usize }, 1086 | 4usize, 1087 | concat!( 1088 | "Offset of field: ", 1089 | stringify!(_WIREGUARD_PEER), 1090 | "::", 1091 | stringify!(Reserved) 1092 | ) 1093 | ); 1094 | assert_eq!( 1095 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_PEER>())).PublicKey as *const _ as usize }, 1096 | 8usize, 1097 | concat!( 1098 | "Offset of field: ", 1099 | stringify!(_WIREGUARD_PEER), 1100 | "::", 1101 | stringify!(PublicKey) 1102 | ) 1103 | ); 1104 | assert_eq!( 1105 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_PEER>())).PresharedKey as *const _ as usize }, 1106 | 40usize, 1107 | concat!( 1108 | "Offset of field: ", 1109 | stringify!(_WIREGUARD_PEER), 1110 | "::", 1111 | stringify!(PresharedKey) 1112 | ) 1113 | ); 1114 | assert_eq!( 1115 | unsafe { 1116 | &(*(::std::ptr::null::<_WIREGUARD_PEER>())).PersistentKeepalive as *const _ as usize 1117 | }, 1118 | 72usize, 1119 | concat!( 1120 | "Offset of field: ", 1121 | stringify!(_WIREGUARD_PEER), 1122 | "::", 1123 | stringify!(PersistentKeepalive) 1124 | ) 1125 | ); 1126 | assert_eq!( 1127 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_PEER>())).Endpoint as *const _ as usize }, 1128 | 76usize, 1129 | concat!( 1130 | "Offset of field: ", 1131 | stringify!(_WIREGUARD_PEER), 1132 | "::", 1133 | stringify!(Endpoint) 1134 | ) 1135 | ); 1136 | assert_eq!( 1137 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_PEER>())).TxBytes as *const _ as usize }, 1138 | 104usize, 1139 | concat!( 1140 | "Offset of field: ", 1141 | stringify!(_WIREGUARD_PEER), 1142 | "::", 1143 | stringify!(TxBytes) 1144 | ) 1145 | ); 1146 | assert_eq!( 1147 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_PEER>())).RxBytes as *const _ as usize }, 1148 | 112usize, 1149 | concat!( 1150 | "Offset of field: ", 1151 | stringify!(_WIREGUARD_PEER), 1152 | "::", 1153 | stringify!(RxBytes) 1154 | ) 1155 | ); 1156 | assert_eq!( 1157 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_PEER>())).LastHandshake as *const _ as usize }, 1158 | 120usize, 1159 | concat!( 1160 | "Offset of field: ", 1161 | stringify!(_WIREGUARD_PEER), 1162 | "::", 1163 | stringify!(LastHandshake) 1164 | ) 1165 | ); 1166 | assert_eq!( 1167 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_PEER>())).AllowedIPsCount as *const _ as usize }, 1168 | 128usize, 1169 | concat!( 1170 | "Offset of field: ", 1171 | stringify!(_WIREGUARD_PEER), 1172 | "::", 1173 | stringify!(AllowedIPsCount) 1174 | ) 1175 | ); 1176 | } 1177 | #[doc = "< The PublicKey field is set"] 1178 | pub const WIREGUARD_INTERFACE_FLAG_WIREGUARD_INTERFACE_HAS_PUBLIC_KEY: WIREGUARD_INTERFACE_FLAG = 1; 1179 | #[doc = "< The PrivateKey field is set"] 1180 | pub const WIREGUARD_INTERFACE_FLAG_WIREGUARD_INTERFACE_HAS_PRIVATE_KEY: WIREGUARD_INTERFACE_FLAG = 1181 | 2; 1182 | #[doc = "< The ListenPort field is set"] 1183 | pub const WIREGUARD_INTERFACE_FLAG_WIREGUARD_INTERFACE_HAS_LISTEN_PORT: WIREGUARD_INTERFACE_FLAG = 1184 | 4; 1185 | #[doc = "< Remove all peers before adding new ones"] 1186 | pub const WIREGUARD_INTERFACE_FLAG_WIREGUARD_INTERFACE_REPLACE_PEERS: WIREGUARD_INTERFACE_FLAG = 8; 1187 | pub type WIREGUARD_INTERFACE_FLAG = ::std::os::raw::c_int; 1188 | pub type WIREGUARD_INTERFACE = _WIREGUARD_INTERFACE; 1189 | #[repr(C)] 1190 | #[repr(align(8))] 1191 | #[derive(Debug, Copy, Clone)] 1192 | pub struct _WIREGUARD_INTERFACE { 1193 | #[doc = "< Bitwise combination of flags"] 1194 | pub Flags: WIREGUARD_INTERFACE_FLAG, 1195 | #[doc = "< Port for UDP listen socket, or 0 to choose randomly"] 1196 | pub ListenPort: WORD, 1197 | #[doc = "< Private key of interface"] 1198 | pub PrivateKey: [BYTE; 32usize], 1199 | #[doc = "< Corresponding public key of private key"] 1200 | pub PublicKey: [BYTE; 32usize], 1201 | #[doc = "< Number of peer structs following this struct"] 1202 | pub PeersCount: DWORD, 1203 | } 1204 | #[test] 1205 | fn bindgen_test_layout__WIREGUARD_INTERFACE() { 1206 | assert_eq!( 1207 | ::std::mem::size_of::<_WIREGUARD_INTERFACE>(), 1208 | 80usize, 1209 | concat!("Size of: ", stringify!(_WIREGUARD_INTERFACE)) 1210 | ); 1211 | assert_eq!( 1212 | ::std::mem::align_of::<_WIREGUARD_INTERFACE>(), 1213 | 8usize, 1214 | concat!("Alignment of ", stringify!(_WIREGUARD_INTERFACE)) 1215 | ); 1216 | assert_eq!( 1217 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_INTERFACE>())).Flags as *const _ as usize }, 1218 | 0usize, 1219 | concat!( 1220 | "Offset of field: ", 1221 | stringify!(_WIREGUARD_INTERFACE), 1222 | "::", 1223 | stringify!(Flags) 1224 | ) 1225 | ); 1226 | assert_eq!( 1227 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_INTERFACE>())).ListenPort as *const _ as usize }, 1228 | 4usize, 1229 | concat!( 1230 | "Offset of field: ", 1231 | stringify!(_WIREGUARD_INTERFACE), 1232 | "::", 1233 | stringify!(ListenPort) 1234 | ) 1235 | ); 1236 | assert_eq!( 1237 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_INTERFACE>())).PrivateKey as *const _ as usize }, 1238 | 6usize, 1239 | concat!( 1240 | "Offset of field: ", 1241 | stringify!(_WIREGUARD_INTERFACE), 1242 | "::", 1243 | stringify!(PrivateKey) 1244 | ) 1245 | ); 1246 | assert_eq!( 1247 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_INTERFACE>())).PublicKey as *const _ as usize }, 1248 | 38usize, 1249 | concat!( 1250 | "Offset of field: ", 1251 | stringify!(_WIREGUARD_INTERFACE), 1252 | "::", 1253 | stringify!(PublicKey) 1254 | ) 1255 | ); 1256 | assert_eq!( 1257 | unsafe { &(*(::std::ptr::null::<_WIREGUARD_INTERFACE>())).PeersCount as *const _ as usize }, 1258 | 72usize, 1259 | concat!( 1260 | "Offset of field: ", 1261 | stringify!(_WIREGUARD_INTERFACE), 1262 | "::", 1263 | stringify!(PeersCount) 1264 | ) 1265 | ); 1266 | } 1267 | extern crate libloading; 1268 | pub struct wireguard { 1269 | __library: ::libloading::Library, 1270 | pub WireGuardCreateAdapter: unsafe extern "C" fn( 1271 | arg1: LPCWSTR, 1272 | arg2: LPCWSTR, 1273 | arg3: *const GUID, 1274 | ) -> WIREGUARD_ADAPTER_HANDLE, 1275 | pub WireGuardOpenAdapter: unsafe extern "C" fn(arg1: LPCWSTR) -> WIREGUARD_ADAPTER_HANDLE, 1276 | pub WireGuardCloseAdapter: unsafe extern "C" fn(arg1: WIREGUARD_ADAPTER_HANDLE), 1277 | pub WireGuardGetAdapterLUID: 1278 | unsafe extern "C" fn(arg1: WIREGUARD_ADAPTER_HANDLE, arg2: *mut NET_LUID), 1279 | pub WireGuardGetRunningDriverVersion: unsafe extern "C" fn() -> DWORD, 1280 | pub WireGuardDeleteDriver: unsafe extern "C" fn() -> BOOL, 1281 | pub WireGuardSetLogger: unsafe extern "C" fn(arg1: WIREGUARD_LOGGER_CALLBACK), 1282 | pub WireGuardSetAdapterLogging: unsafe extern "C" fn( 1283 | arg1: WIREGUARD_ADAPTER_HANDLE, 1284 | arg2: WIREGUARD_ADAPTER_LOG_STATE, 1285 | ) -> BOOL, 1286 | pub WireGuardGetAdapterState: unsafe extern "C" fn( 1287 | arg1: WIREGUARD_ADAPTER_HANDLE, 1288 | arg2: *mut WIREGUARD_ADAPTER_STATE, 1289 | ) -> BOOL, 1290 | pub WireGuardSetAdapterState: 1291 | unsafe extern "C" fn(arg1: WIREGUARD_ADAPTER_HANDLE, arg2: WIREGUARD_ADAPTER_STATE) -> BOOL, 1292 | pub WireGuardGetConfiguration: unsafe extern "C" fn( 1293 | arg1: WIREGUARD_ADAPTER_HANDLE, 1294 | arg2: *mut WIREGUARD_INTERFACE, 1295 | arg3: *mut DWORD, 1296 | ) -> BOOL, 1297 | pub WireGuardSetConfiguration: unsafe extern "C" fn( 1298 | arg1: WIREGUARD_ADAPTER_HANDLE, 1299 | arg2: *const WIREGUARD_INTERFACE, 1300 | arg3: DWORD, 1301 | ) -> BOOL, 1302 | } 1303 | impl wireguard { 1304 | pub unsafe fn new

(path: P) -> Result 1305 | where 1306 | P: AsRef<::std::ffi::OsStr>, 1307 | { 1308 | let library = ::libloading::Library::new(path)?; 1309 | Self::from_library(library) 1310 | } 1311 | pub unsafe fn from_library(library: L) -> Result 1312 | where 1313 | L: Into<::libloading::Library>, 1314 | { 1315 | let __library = library.into(); 1316 | let WireGuardCreateAdapter = __library.get(b"WireGuardCreateAdapter\0").map(|sym| *sym)?; 1317 | let WireGuardOpenAdapter = __library.get(b"WireGuardOpenAdapter\0").map(|sym| *sym)?; 1318 | let WireGuardCloseAdapter = __library.get(b"WireGuardCloseAdapter\0").map(|sym| *sym)?; 1319 | let WireGuardGetAdapterLUID = __library 1320 | .get(b"WireGuardGetAdapterLUID\0") 1321 | .map(|sym| *sym)?; 1322 | let WireGuardGetRunningDriverVersion = __library 1323 | .get(b"WireGuardGetRunningDriverVersion\0") 1324 | .map(|sym| *sym)?; 1325 | let WireGuardDeleteDriver = __library.get(b"WireGuardDeleteDriver\0").map(|sym| *sym)?; 1326 | let WireGuardSetLogger = __library.get(b"WireGuardSetLogger\0").map(|sym| *sym)?; 1327 | let WireGuardSetAdapterLogging = __library 1328 | .get(b"WireGuardSetAdapterLogging\0") 1329 | .map(|sym| *sym)?; 1330 | let WireGuardGetAdapterState = __library 1331 | .get(b"WireGuardGetAdapterState\0") 1332 | .map(|sym| *sym)?; 1333 | let WireGuardSetAdapterState = __library 1334 | .get(b"WireGuardSetAdapterState\0") 1335 | .map(|sym| *sym)?; 1336 | let WireGuardGetConfiguration = __library 1337 | .get(b"WireGuardGetConfiguration\0") 1338 | .map(|sym| *sym)?; 1339 | let WireGuardSetConfiguration = __library 1340 | .get(b"WireGuardSetConfiguration\0") 1341 | .map(|sym| *sym)?; 1342 | Ok(wireguard { 1343 | __library, 1344 | WireGuardCreateAdapter, 1345 | WireGuardOpenAdapter, 1346 | WireGuardCloseAdapter, 1347 | WireGuardGetAdapterLUID, 1348 | WireGuardGetRunningDriverVersion, 1349 | WireGuardDeleteDriver, 1350 | WireGuardSetLogger, 1351 | WireGuardSetAdapterLogging, 1352 | WireGuardGetAdapterState, 1353 | WireGuardSetAdapterState, 1354 | WireGuardGetConfiguration, 1355 | WireGuardSetConfiguration, 1356 | }) 1357 | } 1358 | pub unsafe fn WireGuardCreateAdapter( 1359 | &self, 1360 | arg1: LPCWSTR, 1361 | arg2: LPCWSTR, 1362 | arg3: *const GUID, 1363 | ) -> WIREGUARD_ADAPTER_HANDLE { 1364 | (self.WireGuardCreateAdapter)(arg1, arg2, arg3) 1365 | } 1366 | pub unsafe fn WireGuardOpenAdapter(&self, arg1: LPCWSTR) -> WIREGUARD_ADAPTER_HANDLE { 1367 | (self.WireGuardOpenAdapter)(arg1) 1368 | } 1369 | pub unsafe fn WireGuardCloseAdapter(&self, arg1: WIREGUARD_ADAPTER_HANDLE) -> () { 1370 | (self.WireGuardCloseAdapter)(arg1) 1371 | } 1372 | pub unsafe fn WireGuardGetAdapterLUID( 1373 | &self, 1374 | arg1: WIREGUARD_ADAPTER_HANDLE, 1375 | arg2: *mut NET_LUID, 1376 | ) -> () { 1377 | (self.WireGuardGetAdapterLUID)(arg1, arg2) 1378 | } 1379 | pub unsafe fn WireGuardGetRunningDriverVersion(&self) -> DWORD { 1380 | (self.WireGuardGetRunningDriverVersion)() 1381 | } 1382 | pub unsafe fn WireGuardDeleteDriver(&self) -> BOOL { 1383 | (self.WireGuardDeleteDriver)() 1384 | } 1385 | pub unsafe fn WireGuardSetLogger(&self, arg1: WIREGUARD_LOGGER_CALLBACK) -> () { 1386 | (self.WireGuardSetLogger)(arg1) 1387 | } 1388 | pub unsafe fn WireGuardSetAdapterLogging( 1389 | &self, 1390 | arg1: WIREGUARD_ADAPTER_HANDLE, 1391 | arg2: WIREGUARD_ADAPTER_LOG_STATE, 1392 | ) -> BOOL { 1393 | (self.WireGuardSetAdapterLogging)(arg1, arg2) 1394 | } 1395 | pub unsafe fn WireGuardGetAdapterState( 1396 | &self, 1397 | arg1: WIREGUARD_ADAPTER_HANDLE, 1398 | arg2: *mut WIREGUARD_ADAPTER_STATE, 1399 | ) -> BOOL { 1400 | (self.WireGuardGetAdapterState)(arg1, arg2) 1401 | } 1402 | pub unsafe fn WireGuardSetAdapterState( 1403 | &self, 1404 | arg1: WIREGUARD_ADAPTER_HANDLE, 1405 | arg2: WIREGUARD_ADAPTER_STATE, 1406 | ) -> BOOL { 1407 | (self.WireGuardSetAdapterState)(arg1, arg2) 1408 | } 1409 | pub unsafe fn WireGuardGetConfiguration( 1410 | &self, 1411 | arg1: WIREGUARD_ADAPTER_HANDLE, 1412 | arg2: *mut WIREGUARD_INTERFACE, 1413 | arg3: *mut DWORD, 1414 | ) -> BOOL { 1415 | (self.WireGuardGetConfiguration)(arg1, arg2, arg3) 1416 | } 1417 | pub unsafe fn WireGuardSetConfiguration( 1418 | &self, 1419 | arg1: WIREGUARD_ADAPTER_HANDLE, 1420 | arg2: *const WIREGUARD_INTERFACE, 1421 | arg3: DWORD, 1422 | ) -> BOOL { 1423 | (self.WireGuardSetConfiguration)(arg1, arg2, arg3) 1424 | } 1425 | } 1426 | -------------------------------------------------------------------------------- /wireguard_nt/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Prebuilt Binaries License 2 | ------------------------- 3 | 4 | 1. DEFINITIONS. "Software" means the precise contents of the "wireguard.dll" 5 | files that are included in the .zip file that contains this document as 6 | downloaded from download.wireguard.com. 7 | 8 | 2. LICENSE GRANT. WireGuard LLC grants to you a non-exclusive and 9 | non-transferable right to use Software for lawful purposes under certain 10 | obligations and limited rights as set forth in this agreement. 11 | 12 | 3. RESTRICTIONS. Software is owned and copyrighted by WireGuard LLC. It is 13 | licensed, not sold. Title to Software and all associated intellectual 14 | property rights are retained by WireGuard. You must not: 15 | a. reverse engineer, decompile, disassemble, extract from, or otherwise 16 | modify the Software; 17 | b. modify or create derivative work based upon Software in whole or in 18 | parts, except insofar as only the API interfaces of the "wireguard.h" file 19 | distributed alongside the Software (the "Permitted API") are used; 20 | c. remove any proprietary notices, labels, or copyrights from the Software; 21 | d. resell, redistribute, lease, rent, transfer, sublicense, or otherwise 22 | transfer rights of the Software without the prior written consent of 23 | WireGuard LLC, except insofar as the Software is distributed alongside 24 | other software that uses the Software only via the Permitted API; 25 | e. use the name of WireGuard LLC, the WireGuard project, the WireGuard 26 | project, or the names of its contributors to endorse or promote products 27 | derived from the Software without specific prior written consent. 28 | 29 | 4. LIMITED WARRANTY. THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF 30 | ANY KIND. WIREGUARD LLC HEREBY EXCLUDES AND DISCLAIMS ALL IMPLIED OR 31 | STATUTORY WARRANTIES, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS 32 | FOR A PARTICULAR PURPOSE, QUALITY, NON-INFRINGEMENT, TITLE, RESULTS, 33 | EFFORTS, OR QUIET ENJOYMENT. THERE IS NO WARRANTY THAT THE PRODUCT WILL BE 34 | ERROR-FREE OR WILL FUNCTION WITHOUT INTERRUPTION. YOU ASSUME THE ENTIRE 35 | RISK FOR THE RESULTS OBTAINED USING THE PRODUCT. TO THE EXTENT THAT 36 | WIREGUARD LLC MAY NOT DISCLAIM ANY WARRANTY AS A MATTER OF APPLICABLE LAW, 37 | THE SCOPE AND DURATION OF SUCH WARRANTY WILL BE THE MINIMUM PERMITTED UNDER 38 | SUCH LAW. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 39 | WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR 40 | A PARTICULAR PURPOSE OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE 41 | EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. 42 | 43 | 5. LIMITATION OF LIABILITY. To the extent not prohibited by law, in no event 44 | WireGuard LLC or any third-party-developer will be liable for any lost 45 | revenue, profit or data or for special, indirect, consequential, incidental 46 | or punitive damages, however caused regardless of the theory of liability, 47 | arising out of or related to the use of or inability to use Software, even 48 | if WireGuard LLC has been advised of the possibility of such damages. 49 | Solely you are responsible for determining the appropriateness of using 50 | Software and accept full responsibility for all risks associated with its 51 | exercise of rights under this agreement, including but not limited to the 52 | risks and costs of program errors, compliance with applicable laws, damage 53 | to or loss of data, programs or equipment, and unavailability or 54 | interruption of operations. The foregoing limitations will apply even if 55 | the above stated warranty fails of its essential purpose. You acknowledge, 56 | that it is in the nature of software that software is complex and not 57 | completely free of errors. In no event shall WireGuard LLC or any 58 | third-party-developer be liable to you under any theory for any damages 59 | suffered by you or any user of Software or for any special, incidental, 60 | indirect, consequential or similar damages (including without limitation 61 | damages for loss of business profits, business interruption, loss of 62 | business information or any other pecuniary loss) arising out of the use or 63 | inability to use Software, even if WireGuard LLC has been advised of the 64 | possibility of such damages and regardless of the legal or quitable theory 65 | (contract, tort, or otherwise) upon which the claim is based. 66 | 67 | 6. TERMINATION. This agreement is affected until terminated. You may 68 | terminate this agreement at any time. This agreement will terminate 69 | immediately without notice from WireGuard LLC if you fail to comply with 70 | the terms and conditions of this agreement. Upon termination, you must 71 | delete Software and all copies of Software and cease all forms of 72 | distribution of Software. 73 | 74 | 7. SEVERABILITY. If any provision of this agreement is held to be 75 | unenforceable, this agreement will remain in effect with the provision 76 | omitted, unless omission would frustrate the intent of the parties, in 77 | which case this agreement will immediately terminate. 78 | 79 | 8. RESERVATION OF RIGHTS. All rights not expressly granted in this agreement 80 | are reserved by WireGuard LLC. For example, WireGuard LLC reserves the 81 | right at any time to cease development of Software, to alter distribution 82 | details, features, specifications, capabilities, functions, licensing 83 | terms, release dates, APIs, ABIs, general availability, or other 84 | characteristics of the Software. 85 | -------------------------------------------------------------------------------- /wireguard_nt/README.md: -------------------------------------------------------------------------------- 1 | # [WireGuard](https://www.wireguard.com/) for the NT Kernel 2 | ### High performance in-kernel WireGuard implementation for Windows 3 | 4 | WireGuardNT is an implementation of WireGuard, for the NT Kernel as used in Windows 7, 8, 8.1, 10, and 11, supporting AMD64, x86, ARM64, and ARM processors. 5 | 6 | #### Not the droids you're looking for 7 | 8 | **If you've come here looking to run [WireGuard on Windows](https://git.zx2c4.com/wireguard-windows/about/), you're in the wrong place. Instead, head on over to the [WireGuard Download Page](https://www.wireguard.com/install/) to download the WireGuard application.** Alternatively, if you've come here looking to embed WireGuard into your Windows program, **you are still in the wrong place**. Instead, head on over to the [embeddable DLL service project](https://git.zx2c4.com/wireguard-windows/about/embeddable-dll-service/README.md), to get everything you need to bake WireGuard into your Windows programs. These projects use WireGuardNT inside. 9 | 10 | ## Usage 11 | 12 | #### Download 13 | 14 | WireGuardNT is deployed as a platform-specific `wireguard.dll` file. Install the `wireguard.dll` file side-by-side with your application. Download the dll from [the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/), alongside the header file for your application described below. 15 | 16 | #### API 17 | 18 | Include the [`wireguard.h` file](https://git.zx2c4.com/wireguard-nt/tree/api/wireguard.h) in your project simply by copying it there and dynamically load the `wireguard.dll` using [`LoadLibraryEx()`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa) and [`GetProcAddress()`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress) to resolve each function, using the typedefs provided in the header file. The [`InitializeWireGuardNT` function in the example.c code](https://git.zx2c4.com/wireguard-nt/tree/example/example.c) provides this in a function that you can simply copy and paste. 19 | 20 | With the library setup, WireGuardNT can then be used by first creating an adapter, configuring it, and then setting its status to "up". Adapters have names (e.g. "OfficeNet"), and each one belongs to a _pool_ (e.g. "WireGuard"). So, for example, the WireGuard application app creates multiple tunnels all inside of its "WireGuard" _pool_: 21 | 22 | ```C 23 | WIREGUARD_ADAPTER_HANDLE Adapter1 = WireGuardCreateAdapter(L"WireGuard", L"OfficeNet", &SomeFixedGUID1, NULL); 24 | WIREGUARD_ADAPTER_HANDLE Adapter2 = WireGuardCreateAdapter(L"WireGuard", L"HomeNet", &SomeFixedGUID2, NULL); 25 | WIREGUARD_ADAPTER_HANDLE Adapter3 = WireGuardCreateAdapter(L"WireGuard", L"Data Center", &SomeFixedGUID3, NULL); 26 | ``` 27 | 28 | After creating an adapter, we can use it by setting a configuration and setting its status to "up": 29 | 30 | ```C 31 | struct 32 | { 33 | WIREGUARD_INTERFACE Interface; 34 | WIREGUARD_PEER FirstPeer; 35 | WIREGUARD_ALLOWED_IP FirstPeerAllowedIP1; 36 | WIREGUARD_ALLOWED_IP FirstPeerAllowedIP2; 37 | WIREGUARD_PEER SecondPeer; 38 | WIREGUARD_ALLOWED_IP SecondtPeerAllowedIP1; 39 | } Config = { 40 | .Interface = { 41 | .Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY, 42 | .PrivateKey = ..., 43 | .PeersCount = 2 44 | }, 45 | .FirstPeer = { 46 | .Flags = WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_ENDPOINT, 47 | .PublicKey = ..., 48 | .Endpoint = ..., 49 | .AllowedIPsCount = 2 50 | }, 51 | .FirstPeerAllowedIP1 = { ... }, 52 | ... 53 | }; 54 | WireGuardSetConfiguration(Adapter1, &Config.Interface, sizeof(Config)); 55 | WireGuardSetAdapterState(Adapter1, WIREGUARD_ADAPTER_STATE_UP); 56 | ``` 57 | 58 | You are *highly encouraged* to read the [**example.c short example**](https://git.zx2c4.com/wireguard-nt/tree/example/example.c) to see how to put together a simple network tunnel. The example one connects to the [demo server](https://demo.wireguard.com/). 59 | 60 | The various functions and definitions are [documented in `wireguard.h`](https://git.zx2c4.com/wireguard-nt/tree/api/wireguard.h). 61 | 62 | ## Building 63 | 64 | **Do not distribute drivers or files named "WireGuard" or "wireguard" or similar, as they will most certainly clash with official deployments. Instead distribute [`wireguard.dll` as downloaded from the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/).** 65 | 66 | General requirements: 67 | 68 | - [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) with Windows SDK 69 | - [Windows Driver Kit](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk) 70 | 71 | `wireguard-nt.sln` may be opened in Visual Studio for development and building. Be sure to run `bcdedit /set testsigning on` and then reboot before to enable unsigned driver loading. The default run sequence (F5) in Visual Studio will build the example project and its dependencies. 72 | 73 | ## License 74 | 75 | The entire contents of [this repository](https://git.zx2c4.com/wireguard-nt/), including all documentation and example code, is "Copyright © 2018-2021 WireGuard LLC. All Rights Reserved." Source code is licensed under the [GPLv2](COPYING). Prebuilt binaries from [the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/) are released under a more permissive license suitable for more forms of software contained inside of the .zip files distributed there. 76 | -------------------------------------------------------------------------------- /wireguard_nt/wireguard.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT 2 | * 3 | * Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved. 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #ifndef ALIGNED 19 | # if defined(_MSC_VER) 20 | # define ALIGNED(n) __declspec(align(n)) 21 | # elif defined(__GNUC__) 22 | # define ALIGNED(n) __attribute__((aligned(n))) 23 | # else 24 | # error "Unable to define ALIGNED" 25 | # endif 26 | #endif 27 | 28 | /* MinGW is missing this one, unfortunately. */ 29 | #ifndef _Post_maybenull_ 30 | # define _Post_maybenull_ 31 | #endif 32 | 33 | #pragma warning(push) 34 | #pragma warning(disable : 4324) /* structure was padded due to alignment specifier */ 35 | 36 | /** 37 | * A handle representing WireGuard adapter 38 | */ 39 | typedef struct _WIREGUARD_ADAPTER *WIREGUARD_ADAPTER_HANDLE; 40 | 41 | /** 42 | * Creates a new WireGuard adapter. 43 | * 44 | * @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1 45 | * characters. 46 | * 47 | * @param TunnelType Name of the adapter tunnel type. Zero-terminated string of up to MAX_ADAPTER_NAME-1 48 | * characters. 49 | * 50 | * @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation deterministically. 51 | * If it is set to NULL, the GUID is chosen by the system at random, and hence a new NLA entry is 52 | * created for each new adapter. It is called "requested" GUID because the API it uses is 53 | * completely undocumented, and so there could be minor interesting complications with its usage. 54 | * 55 | * @return If the function succeeds, the return value is the adapter handle. Must be released with 56 | * WireGuardCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call 57 | * GetLastError. 58 | */ 59 | typedef _Must_inspect_result_ 60 | _Return_type_success_(return != NULL) 61 | _Post_maybenull_ 62 | WIREGUARD_ADAPTER_HANDLE(WINAPI WIREGUARD_CREATE_ADAPTER_FUNC) 63 | (_In_z_ LPCWSTR Name, _In_z_ LPCWSTR TunnelType, _In_opt_ const GUID *RequestedGUID); 64 | 65 | /** 66 | * Opens an existing WireGuard adapter. 67 | * 68 | * @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1 69 | * characters. 70 | * 71 | * @return If the function succeeds, the return value is the adapter handle. Must be released with 72 | * WireGuardCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call 73 | * GetLastError. 74 | */ 75 | typedef _Must_inspect_result_ 76 | _Return_type_success_(return != NULL) 77 | _Post_maybenull_ 78 | WIREGUARD_ADAPTER_HANDLE(WINAPI WIREGUARD_OPEN_ADAPTER_FUNC)(_In_z_ LPCWSTR Name); 79 | 80 | /** 81 | * Releases WireGuard adapter resources and, if adapter was created with WireGuardCreateAdapter, removes adapter. 82 | * 83 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter. 84 | */ 85 | typedef VOID(WINAPI WIREGUARD_CLOSE_ADAPTER_FUNC)(_In_opt_ WIREGUARD_ADAPTER_HANDLE Adapter); 86 | 87 | /** 88 | * Deletes the WireGuard driver if there are no more adapters in use. 89 | * 90 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 91 | * get extended error information, call GetLastError. 92 | */ 93 | typedef _Return_type_success_(return != FALSE) 94 | BOOL(WINAPI WIREGUARD_DELETE_DRIVER_FUNC)(VOID); 95 | 96 | /** 97 | * Returns the LUID of the adapter. 98 | * 99 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 100 | * 101 | * @param Luid Pointer to LUID to receive adapter LUID. 102 | */ 103 | typedef VOID(WINAPI WIREGUARD_GET_ADAPTER_LUID_FUNC)(_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid); 104 | 105 | /** 106 | * Determines the version of the WireGuard driver currently loaded. 107 | * 108 | * @return If the function succeeds, the return value is the version number. If the function fails, the return value is 109 | * zero. To get extended error information, call GetLastError. Possible errors include the following: 110 | * ERROR_FILE_NOT_FOUND WireGuard not loaded 111 | */ 112 | typedef _Return_type_success_(return != 0) 113 | DWORD(WINAPI WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC)(VOID); 114 | 115 | /** 116 | * Determines the level of logging, passed to WIREGUARD_LOGGER_CALLBACK. 117 | */ 118 | typedef enum 119 | { 120 | WIREGUARD_LOG_INFO, /**< Informational */ 121 | WIREGUARD_LOG_WARN, /**< Warning */ 122 | WIREGUARD_LOG_ERR /**< Error */ 123 | } WIREGUARD_LOGGER_LEVEL; 124 | 125 | /** 126 | * Called by internal logger to report diagnostic messages 127 | * 128 | * @param Level Message level. 129 | * 130 | * @param Timestamp Message timestamp in in 100ns intervals since 1601-01-01 UTC. 131 | * 132 | * @param Message Message text. 133 | */ 134 | typedef VOID(CALLBACK *WIREGUARD_LOGGER_CALLBACK)( 135 | _In_ WIREGUARD_LOGGER_LEVEL Level, 136 | _In_ DWORD64 Timestamp, 137 | _In_z_ LPCWSTR Message); 138 | 139 | /** 140 | * Sets logger callback function. 141 | * 142 | * @param NewLogger Pointer to callback function to use as a new global logger. NewLogger may be called from various 143 | * threads concurrently. Should the logging require serialization, you must handle serialization in 144 | * NewLogger. Set to NULL to disable. 145 | */ 146 | typedef VOID(WINAPI WIREGUARD_SET_LOGGER_FUNC)(_In_ WIREGUARD_LOGGER_CALLBACK NewLogger); 147 | 148 | /** 149 | * Whether and how logs from the driver are collected for the callback function. 150 | */ 151 | typedef enum 152 | { 153 | WIREGUARD_ADAPTER_LOG_OFF, /**< No logs are generated from the driver. */ 154 | WIREGUARD_ADAPTER_LOG_ON, /**< Logs are generated from the driver. */ 155 | WIREGUARD_ADAPTER_LOG_ON_WITH_PREFIX /**< Logs are generated from the driver, index-prefixed. */ 156 | } WIREGUARD_ADAPTER_LOG_STATE; 157 | 158 | /** 159 | * Sets whether and how the adapter logs to the logger previously set up with WireGuardSetLogger. 160 | * 161 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 162 | * 163 | * @param LogState Adapter logging state. 164 | * 165 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 166 | * get extended error information, call GetLastError. 167 | */ 168 | typedef _Return_type_success_(return != FALSE) 169 | BOOL(WINAPI WIREGUARD_SET_ADAPTER_LOGGING_FUNC) 170 | (_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_ WIREGUARD_ADAPTER_LOG_STATE LogState); 171 | 172 | /** 173 | * Determines the state of the adapter. 174 | */ 175 | typedef enum 176 | { 177 | WIREGUARD_ADAPTER_STATE_DOWN, /**< Down */ 178 | WIREGUARD_ADAPTER_STATE_UP, /**< Up */ 179 | } WIREGUARD_ADAPTER_STATE; 180 | 181 | /** 182 | * Sets the adapter state of the WireGuard adapter. Note: sockets are owned by the process that sets the state to up. 183 | * 184 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 185 | * 186 | * @param State Adapter state. 187 | * 188 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 189 | * get extended error information, call GetLastError. 190 | */ 191 | typedef _Return_type_success_(return != FALSE) 192 | BOOL(WINAPI WIREGUARD_SET_ADAPTER_STATE_FUNC) 193 | (_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_ WIREGUARD_ADAPTER_STATE State); 194 | 195 | /** 196 | * Gets the adapter state of the WireGuard adapter. 197 | * 198 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 199 | * 200 | * @param State Pointer to adapter state. 201 | * 202 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 203 | * get extended error information, call GetLastError. 204 | */ 205 | typedef _Must_inspect_result_ 206 | _Return_type_success_(return != FALSE) 207 | BOOL(WINAPI WIREGUARD_GET_ADAPTER_STATE_FUNC) 208 | (_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _Out_ WIREGUARD_ADAPTER_STATE *State); 209 | 210 | #define WIREGUARD_KEY_LENGTH 32 211 | 212 | typedef struct _WIREGUARD_ALLOWED_IP WIREGUARD_ALLOWED_IP; 213 | struct ALIGNED(8) _WIREGUARD_ALLOWED_IP 214 | { 215 | union 216 | { 217 | IN_ADDR V4; 218 | IN6_ADDR V6; 219 | } Address; /**< IP address */ 220 | ADDRESS_FAMILY AddressFamily; /**< Address family, either AF_INET or AF_INET6 */ 221 | BYTE Cidr; /**< CIDR of allowed IPs */ 222 | }; 223 | 224 | typedef enum 225 | { 226 | WIREGUARD_PEER_HAS_PUBLIC_KEY = 1 << 0, /**< The PublicKey field is set */ 227 | WIREGUARD_PEER_HAS_PRESHARED_KEY = 1 << 1, /**< The PresharedKey field is set */ 228 | WIREGUARD_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2, /**< The PersistentKeepAlive field is set */ 229 | WIREGUARD_PEER_HAS_ENDPOINT = 1 << 3, /**< The Endpoint field is set */ 230 | WIREGUARD_PEER_REPLACE_ALLOWED_IPS = 1 << 5, /**< Remove all allowed IPs before adding new ones */ 231 | WIREGUARD_PEER_REMOVE = 1 << 6, /**< Remove specified peer */ 232 | WIREGUARD_PEER_UPDATE = 1 << 7 /**< Do not add a new peer */ 233 | } WIREGUARD_PEER_FLAG; 234 | 235 | typedef struct _WIREGUARD_PEER WIREGUARD_PEER; 236 | struct ALIGNED(8) _WIREGUARD_PEER 237 | { 238 | WIREGUARD_PEER_FLAG Flags; /**< Bitwise combination of flags */ 239 | DWORD Reserved; /**< Reserved; must be zero */ 240 | BYTE PublicKey[WIREGUARD_KEY_LENGTH]; /**< Public key, the peer's primary identifier */ 241 | BYTE PresharedKey[WIREGUARD_KEY_LENGTH]; /**< Preshared key for additional layer of post-quantum resistance */ 242 | WORD PersistentKeepalive; /**< Seconds interval, or 0 to disable */ 243 | SOCKADDR_INET Endpoint; /**< Endpoint, with IP address and UDP port number*/ 244 | DWORD64 TxBytes; /**< Number of bytes transmitted */ 245 | DWORD64 RxBytes; /**< Number of bytes received */ 246 | DWORD64 LastHandshake; /**< Time of the last handshake, in 100ns intervals since 1601-01-01 UTC */ 247 | DWORD AllowedIPsCount; /**< Number of allowed IP structs following this struct */ 248 | }; 249 | 250 | typedef enum 251 | { 252 | WIREGUARD_INTERFACE_HAS_PUBLIC_KEY = (1 << 0), /**< The PublicKey field is set */ 253 | WIREGUARD_INTERFACE_HAS_PRIVATE_KEY = (1 << 1), /**< The PrivateKey field is set */ 254 | WIREGUARD_INTERFACE_HAS_LISTEN_PORT = (1 << 2), /**< The ListenPort field is set */ 255 | WIREGUARD_INTERFACE_REPLACE_PEERS = (1 << 3) /**< Remove all peers before adding new ones */ 256 | } WIREGUARD_INTERFACE_FLAG; 257 | 258 | typedef struct _WIREGUARD_INTERFACE WIREGUARD_INTERFACE; 259 | struct ALIGNED(8) _WIREGUARD_INTERFACE 260 | { 261 | WIREGUARD_INTERFACE_FLAG Flags; /**< Bitwise combination of flags */ 262 | WORD ListenPort; /**< Port for UDP listen socket, or 0 to choose randomly */ 263 | BYTE PrivateKey[WIREGUARD_KEY_LENGTH]; /**< Private key of interface */ 264 | BYTE PublicKey[WIREGUARD_KEY_LENGTH]; /**< Corresponding public key of private key */ 265 | DWORD PeersCount; /**< Number of peer structs following this struct */ 266 | }; 267 | 268 | /** 269 | * Sets the configuration of the WireGuard adapter. 270 | * 271 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 272 | * 273 | * @param Config Configuration for the adapter. 274 | * 275 | * @param Bytes Number of bytes in Config allocation. 276 | * 277 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 278 | * get extended error information, call GetLastError. 279 | */ 280 | typedef _Return_type_success_(return != FALSE) 281 | BOOL(WINAPI WIREGUARD_SET_CONFIGURATION_FUNC) 282 | (_In_ WIREGUARD_ADAPTER_HANDLE Adapter, _In_reads_bytes_(Bytes) const WIREGUARD_INTERFACE *Config, _In_ DWORD Bytes); 283 | 284 | /** 285 | * Gets the configuration of the WireGuard adapter. 286 | * 287 | * @param Adapter Adapter handle obtained with WireGuardCreateAdapter or WireGuardOpenAdapter 288 | * 289 | * @param Config Configuration for the adapter. 290 | * 291 | * @param Bytes Pointer to number of bytes in Config allocation. 292 | * 293 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 294 | * get extended error information, call GetLastError, which if ERROR_MORE_DATA, Bytes is updated with the 295 | * required size. 296 | */ 297 | typedef _Must_inspect_result_ 298 | _Return_type_success_(return != FALSE) 299 | BOOL(WINAPI WIREGUARD_GET_CONFIGURATION_FUNC) 300 | (_In_ WIREGUARD_ADAPTER_HANDLE Adapter, 301 | _Out_writes_bytes_all_(*Bytes) WIREGUARD_INTERFACE *Config, 302 | _Inout_ DWORD *Bytes); 303 | 304 | #pragma warning(pop) 305 | 306 | #ifdef __cplusplus 307 | } 308 | #endif 309 | -------------------------------------------------------------------------------- /wireguard_nt/wireguard_functions.h: -------------------------------------------------------------------------------- 1 | // info about function names taken from 2 | // https://git.zx2c4.com/wireguard-nt/tree/example/example.c 3 | 4 | #include "wireguard.h" 5 | 6 | WIREGUARD_CREATE_ADAPTER_FUNC WireGuardCreateAdapter; 7 | WIREGUARD_OPEN_ADAPTER_FUNC WireGuardOpenAdapter; 8 | WIREGUARD_CLOSE_ADAPTER_FUNC WireGuardCloseAdapter; 9 | WIREGUARD_GET_ADAPTER_LUID_FUNC WireGuardGetAdapterLUID; 10 | WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC WireGuardGetRunningDriverVersion; 11 | WIREGUARD_DELETE_DRIVER_FUNC WireGuardDeleteDriver; 12 | WIREGUARD_SET_LOGGER_FUNC WireGuardSetLogger; 13 | WIREGUARD_SET_ADAPTER_LOGGING_FUNC WireGuardSetAdapterLogging; 14 | WIREGUARD_GET_ADAPTER_STATE_FUNC WireGuardGetAdapterState; 15 | WIREGUARD_SET_ADAPTER_STATE_FUNC WireGuardSetAdapterState; 16 | WIREGUARD_GET_CONFIGURATION_FUNC WireGuardGetConfiguration; 17 | WIREGUARD_SET_CONFIGURATION_FUNC WireGuardSetConfiguration; --------------------------------------------------------------------------------