diff --git a/contrib/embeddable-wg-library/wireguard.c b/contrib/embeddable-wg-library/wireguard.c index 0ba767b..12234e5 100644 --- a/contrib/embeddable-wg-library/wireguard.c +++ b/contrib/embeddable-wg-library/wireguard.c @@ -72,7 +72,8 @@ enum wgdevice_attribute { enum wgpeer_flag { WGPEER_F_REMOVE_ME = 1U << 0, WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1, - WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3 + WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3, + WGPEER_F_HAS_SPECIAL_HANDSHAKE = 1U << 4 }; enum wgpeer_attribute { WGPEER_A_UNSPEC, @@ -87,6 +88,7 @@ enum wgpeer_attribute { WGPEER_A_ALLOWEDIPS, WGPEER_A_PROTOCOL_VERSION, WGPEER_A_ADVANCED_SECURITY, + WGPEER_A_SPECIAL_HANDSHAKE, __WGPEER_A_LAST }; diff --git a/contrib/peer-approver/approve.sh b/contrib/peer-approver/approve.sh index b4ecfe9..e711a6c 100755 --- a/contrib/peer-approver/approve.sh +++ b/contrib/peer-approver/approve.sh @@ -5,6 +5,7 @@ INTERFACE_NAME=$2 PUBLIC_KEY=$3 ENDPOINT=$4 ADVANCED_SECURITY=$5 +SPECIAL_HANDSHAKE=$6 ACCOUNT_STR=`grep "${PUBLIC_KEY}" "${ACCOUNTS_FILE}"` @@ -19,7 +20,7 @@ PSK=$(echo ${ACCOUNT[2]}|tr -d '"') PSK_FILE=$(tempfile) echo "${PSK}" > "${PSK_FILE}" -awg set "${INTERFACE_NAME}" peer "${PUBLIC_KEY}" allowed-ips "${ALLOWED_IPS}" endpoint "${ENDPOINT}" allowed-ips "${ALLOWED_IPS}" preshared-key "${PSK_FILE}" advanced-security "${ADVANCED_SECURITY}" +awg set "${INTERFACE_NAME}" peer "${PUBLIC_KEY}" allowed-ips "${ALLOWED_IPS}" endpoint "${ENDPOINT}" allowed-ips "${ALLOWED_IPS}" preshared-key "${PSK_FILE}" advanced-security "${ADVANCED_SECURITY}" special-handshake "${SPECIAL_HANDSHAKE}" EXIT_CODE=$? rm -f "{$PSK_FILE}" diff --git a/contrib/peer-approver/notification-listener.c b/contrib/peer-approver/notification-listener.c index a264673..0057e71 100644 --- a/contrib/peer-approver/notification-listener.c +++ b/contrib/peer-approver/notification-listener.c @@ -116,18 +116,19 @@ static int get_endpoint(struct nlattr *peer[], char **endpoint_ip) return 0; } -static int run_callback(char *ifname, char *pubkey, char *endpoint_ip, bool advanced_security) +static int run_callback(char *ifname, char *pubkey, char *endpoint_ip, bool advanced_security, bool special_handshake) { char** new_argv = malloc((cb_argc + 2) * sizeof *new_argv); new_argv[0] = cb_argv[1]; - for (int i = 2; i < cb_argc - 3; i++) { + for (int i = 2; i < cb_argc - 4; i++) { new_argv[i - 1] = cb_argv[i]; } - new_argv[cb_argc - 4] = ifname; - new_argv[cb_argc - 3] = pubkey; - new_argv[cb_argc - 2] = endpoint_ip; - new_argv[cb_argc - 1] = (advanced_security ? "on\0" : "off\0"); + new_argv[cb_argc - 5] = ifname; + new_argv[cb_argc - 4] = pubkey; + new_argv[cb_argc - 3] = endpoint_ip; + new_argv[cb_argc - 2] = (advanced_security ? "on\0" : "off\0"); + new_argv[cb_argc - 1] = (special_handshake ? "on\0" : "off\0"); new_argv[cb_argc] = NULL; int child_pid = fork(), ret; @@ -156,6 +157,7 @@ static int netlink_callback(struct nl_msg *msg, void *arg) char *ifname, *pubkey, *endpoint_ip; bool advanced_security = false; + bool special_handshake = false; int cb_ret; switch (gnlh->cmd) { @@ -179,7 +181,10 @@ static int netlink_callback(struct nl_msg *msg, void *arg) if (nla_get_flag(peer[WGPEER_A_ADVANCED_SECURITY])) { advanced_security = true; } - if (cb_ret = run_callback(ifname, pubkey, endpoint_ip, advanced_security)) { + if (nla_get_flag(peer[WGPEER_A_SPECIAL_HANDSHAKE])) { + special_handshake = true; + } + if (cb_ret = run_callback(ifname, pubkey, endpoint_ip, advanced_security, special_handshake)) { prerr("failed to execute callback script: %d!\n", cb_ret); return NL_SKIP; } @@ -260,4 +265,4 @@ int main(int argc, char *argv[]) } cleanup_and_exit(EXIT_FAILURE); -} \ No newline at end of file +} diff --git a/src/config.c b/src/config.c index 6a60f77..176dc15 100644 --- a/src/config.c +++ b/src/config.c @@ -606,7 +606,7 @@ static bool process_line(struct config_ctx *ctx, const char *line) ret = parse_string(&ctx->device->j3, "J3", value); if (ret) ctx->device->flags |= WGDEVICE_HAS_J3; - } else if (key_match("ITIME")) { + } else if (key_match("Itime")) { ret = parse_uint32(&ctx->device->itime, "Itime", value); if (ret) ctx->device->flags |= WGDEVICE_HAS_ITIME; @@ -631,6 +631,10 @@ static bool process_line(struct config_ctx *ctx, const char *line) ret = parse_bool(&ctx->last_peer->advanced_security, "AdvancedSecurity", value); if (ret) ctx->last_peer->flags |= WGPEER_HAS_ADVANCED_SECURITY; + } else if (key_match("SpecialHandshake")) { + ret = parse_bool(&ctx->last_peer->special_handshake, "SpecialHandshake", value); + if (ret) + ctx->last_peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE; } else goto error; } else @@ -934,6 +938,12 @@ struct wgdevice *config_read_cmd(const char *argv[], int argc) peer->flags |= WGPEER_HAS_ADVANCED_SECURITY; argv += 2; argc -= 2; + } else if (!strcmp(argv[0], "special-handshake") && argc >= 2 && peer) { + if (!parse_bool(&peer->special_handshake, "SpecialHandshake", argv[1])) + goto error; + peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE; + argv += 2; + argc -= 2; } else { fprintf(stderr, "Invalid argument: %s\n", argv[0]); goto error; diff --git a/src/containers.h b/src/containers.h index b8fabfc..376230e 100644 --- a/src/containers.h +++ b/src/containers.h @@ -53,7 +53,8 @@ enum WGPEER_HAS_PUBLIC_KEY = 1U << 2, WGPEER_HAS_PRESHARED_KEY = 1U << 3, WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4, - WGPEER_HAS_ADVANCED_SECURITY = 1U << 5 + WGPEER_HAS_ADVANCED_SECURITY = 1U << 5, + WGPEER_HAS_SPECIAL_HANDSHAKE = 1U << 6 }; struct wgpeer @@ -75,6 +76,7 @@ struct wgpeer uint16_t persistent_keepalive_interval; bool advanced_security; + bool special_handshake; struct wgallowedip *first_allowedip, *last_allowedip; struct wgpeer* next_peer; diff --git a/src/ipc-freebsd.h b/src/ipc-freebsd.h index 83f42fa..7fe3b12 100644 --- a/src/ipc-freebsd.h +++ b/src/ipc-freebsd.h @@ -251,7 +251,7 @@ static int kernel_get_device(struct wgdevice** device, const char* ifname) if (nvlist_exists_binary(nvl_device, "itime")) { number = nvlist_get_number(nvl_device, "itime"); - if (number <= INT32_MAX) + if (number <= UINT32_MAX) { dev->itime = number; dev->flags |= WGDEVICE_HAS_ITIME; diff --git a/src/ipc-linux.h b/src/ipc-linux.h index 862bb18..d228c67 100644 --- a/src/ipc-linux.h +++ b/src/ipc-linux.h @@ -6,6 +6,7 @@ #include "containers.h" #include "encoding.h" #include "netlink.h" +#include "uapi/linux/linux/wireguard.h" #include #include #include @@ -191,6 +192,25 @@ again: mnl_attr_put_u32(nlh, WGDEVICE_A_H3, dev->underload_packet_magic_header); if (dev->flags & WGDEVICE_HAS_H4) mnl_attr_put_u32(nlh, WGDEVICE_A_H4, dev->transport_packet_magic_header); + if (dev->flags & WGDEVICE_HAS_I1) + mnl_attr_put_strz(nlh, WGDEVICE_A_I1, dev->i1); + if (dev->flags & WGDEVICE_HAS_I2) + mnl_attr_put_strz(nlh, WGDEVICE_A_I2, dev->i2); + if (dev->flags & WGDEVICE_HAS_I3) + mnl_attr_put_strz(nlh, WGDEVICE_A_I3, dev->i3); + if (dev->flags & WGDEVICE_HAS_I4) + mnl_attr_put_strz(nlh, WGDEVICE_A_I4, dev->i4); + if (dev->flags & WGDEVICE_HAS_I5) + mnl_attr_put_strz(nlh, WGDEVICE_A_I5, dev->i5); + if (dev->flags & WGDEVICE_HAS_J1) + mnl_attr_put_strz(nlh, WGDEVICE_A_J1, dev->j1); + if (dev->flags & WGDEVICE_HAS_J2) + mnl_attr_put_strz(nlh, WGDEVICE_A_J2, dev->j2); + if (dev->flags & WGDEVICE_HAS_J3) + mnl_attr_put_strz(nlh, WGDEVICE_A_J3, dev->j3); + if (dev->flags & WGDEVICE_HAS_ITIME) + mnl_attr_put_u32(nlh, WGDEVICE_A_ITIME, dev->itime); + if (dev->flags & WGDEVICE_HAS_FWMARK) mnl_attr_put_u32(nlh, WGDEVICE_A_FWMARK, dev->fwmark); if (dev->flags & WGDEVICE_REPLACE_PEERS) @@ -269,6 +289,13 @@ again: nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ADVANCED_SECURITY, 0, NULL); flags |= WGPEER_F_HAS_ADVANCED_SECURITY; } + if (peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE) + { + if (peer->special_handshake) + mnl_attr_put_check( + nlh, SOCKET_BUFFER_SIZE, WGPEER_A_SPECIAL_HANDSHAKE, 0, NULL); + flags |= WGPEER_F_HAS_SPECIAL_HANDSHAKE; + } if (flags) { if (!mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_FLAGS, flags)) @@ -489,6 +516,13 @@ static int parse_peer(const struct nlattr* attr, void* data) peer->flags |= WGPEER_HAS_ADVANCED_SECURITY; peer->advanced_security = false; } + else if ( + flags & WGPEER_F_HAS_SPECIAL_HANDSHAKE && + !(peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE)) + { + peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE; + peer->special_handshake = false; + } } break; case WGPEER_A_ADVANCED_SECURITY: @@ -502,6 +536,17 @@ static int parse_peer(const struct nlattr* attr, void* data) } } break; + case WGPEER_A_SPECIAL_HANDSHAKE: + if (!mnl_attr_validate(attr, MNL_TYPE_FLAG)) + { + peer->special_handshake = true; + + if (!(peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE)) + { + peer->flags |= WGPEER_HAS_SPECIAL_HANDSHAKE; + } + } + break; case WGPEER_A_ALLOWEDIPS: return mnl_attr_parse_nested(attr, parse_allowedips, peer); } diff --git a/src/ipc-uapi.h b/src/ipc-uapi.h index da45969..563243f 100644 --- a/src/ipc-uapi.h +++ b/src/ipc-uapi.h @@ -89,6 +89,8 @@ static int userspace_set_device(struct wgdevice* dev) if (dev->flags & WGDEVICE_HAS_ITIME) fprintf(f, "itime=%u\n", dev->itime); + printf("i1: %s\n", dev->i1); + for_each_wgpeer(dev, peer) { key_to_hex(hex, peer->public_key); @@ -98,6 +100,11 @@ static int userspace_set_device(struct wgdevice* dev) ret = -EINVAL; goto out; } + if (peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE) + { + ret = -EINVAL; + goto out; + } if (peer->flags & WGPEER_REMOVE_ME) { fprintf(f, "remove=true\n"); diff --git a/src/ipc-windows.h b/src/ipc-windows.h index 7925cf0..7695446 100644 --- a/src/ipc-windows.h +++ b/src/ipc-windows.h @@ -4,529 +4,774 @@ */ #include "containers.h" -#include -#include #include -#include -#include -#include #include -#include +#include #include +#include +#include +#include +#include +#include #define IPC_SUPPORTS_KERNEL_INTERFACE -static bool have_cached_kernel_interfaces; +static bool have_cached_kernel_interfaces; static struct hashtable cached_kernel_interfaces; static const DEVPROPKEY devpkey_name = DEVPKEY_WG_NAME; -extern bool is_win7; +extern bool is_win7; -static int kernel_get_wireguard_interfaces(struct string_list *list) +static int kernel_get_wireguard_interfaces(struct string_list* list) { - HDEVINFO dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL); - bool will_have_cached_kernel_interfaces = true; + HDEVINFO dev_info = SetupDiGetClassDevsExW( + &GUID_DEVCLASS_NET, + is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard", + NULL, + DIGCF_PRESENT, + NULL, + NULL, + NULL); + bool will_have_cached_kernel_interfaces = true; - if (dev_info == INVALID_HANDLE_VALUE) { - errno = EACCES; - return -errno; - } + if (dev_info == INVALID_HANDLE_VALUE) + { + errno = EACCES; + return -errno; + } - for (DWORD i = 0;; ++i) { - DWORD buf_len; - WCHAR adapter_name[MAX_ADAPTER_NAME]; - SP_DEVINFO_DATA dev_info_data = { .cbSize = sizeof(SP_DEVINFO_DATA) }; - DEVPROPTYPE prop_type; - ULONG status, problem_code; - char *interface_name; - struct hashtable_entry *entry; + for (DWORD i = 0;; ++i) + { + DWORD buf_len; + WCHAR adapter_name[MAX_ADAPTER_NAME]; + SP_DEVINFO_DATA dev_info_data = {.cbSize = sizeof(SP_DEVINFO_DATA)}; + DEVPROPTYPE prop_type; + ULONG status, problem_code; + char* interface_name; + struct hashtable_entry* entry; - if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) { - if (GetLastError() == ERROR_NO_MORE_ITEMS) - break; - continue; - } + if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + break; + continue; + } - if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name, - &prop_type, (PBYTE)adapter_name, - sizeof(adapter_name), NULL, 0) || - prop_type != DEVPROP_TYPE_STRING) - continue; - adapter_name[_countof(adapter_name) - 1] = L'0'; - if (!adapter_name[0]) - continue; - buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, NULL, 0, NULL, NULL); - if (!buf_len) - continue; - interface_name = malloc(buf_len); - if (!interface_name) - continue; - buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL); - if (!buf_len) { - free(interface_name); - continue; - } + if (!SetupDiGetDevicePropertyW( + dev_info, + &dev_info_data, + &devpkey_name, + &prop_type, + (PBYTE)adapter_name, + sizeof(adapter_name), + NULL, + 0) || + prop_type != DEVPROP_TYPE_STRING) + continue; + adapter_name[_countof(adapter_name) - 1] = L'0'; + if (!adapter_name[0]) + continue; + buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, NULL, 0, NULL, NULL); + if (!buf_len) + continue; + interface_name = malloc(buf_len); + if (!interface_name) + continue; + buf_len = WideCharToMultiByte( + CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL); + if (!buf_len) + { + free(interface_name); + continue; + } - if (CM_Get_DevNode_Status(&status, &problem_code, dev_info_data.DevInst, 0) == CR_SUCCESS && - (status & (DN_DRIVER_LOADED | DN_STARTED)) == (DN_DRIVER_LOADED | DN_STARTED)) - string_list_add(list, interface_name); + if (CM_Get_DevNode_Status(&status, &problem_code, dev_info_data.DevInst, 0) == + CR_SUCCESS && + (status & (DN_DRIVER_LOADED | DN_STARTED)) == (DN_DRIVER_LOADED | DN_STARTED)) + string_list_add(list, interface_name); - entry = hashtable_find_or_insert_entry(&cached_kernel_interfaces, interface_name); - free(interface_name); - if (!entry) - continue; + entry = hashtable_find_or_insert_entry(&cached_kernel_interfaces, interface_name); + free(interface_name); + if (!entry) + continue; - if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) - continue; - entry->value = calloc(sizeof(WCHAR), buf_len); - if (!entry->value) - continue; - if (!SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, entry->value, buf_len, &buf_len)) { - free(entry->value); - entry->value = NULL; - continue; - } + if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) + continue; + entry->value = calloc(sizeof(WCHAR), buf_len); + if (!entry->value) + continue; + if (!SetupDiGetDeviceInstanceIdW( + dev_info, &dev_info_data, entry->value, buf_len, &buf_len)) + { + free(entry->value); + entry->value = NULL; + continue; + } - will_have_cached_kernel_interfaces = true; - } - SetupDiDestroyDeviceInfoList(dev_info); - have_cached_kernel_interfaces = will_have_cached_kernel_interfaces; - return 0; + will_have_cached_kernel_interfaces = true; + } + SetupDiDestroyDeviceInfoList(dev_info); + have_cached_kernel_interfaces = will_have_cached_kernel_interfaces; + return 0; } -static HANDLE kernel_interface_handle(const char *iface) +static HANDLE kernel_interface_handle(const char* iface) { - HDEVINFO dev_info; - WCHAR *interfaces = NULL; - HANDLE handle; + HDEVINFO dev_info; + WCHAR* interfaces = NULL; + HANDLE handle; - if (have_cached_kernel_interfaces) { - struct hashtable_entry *entry = hashtable_find_entry(&cached_kernel_interfaces, iface); - if (entry) { - DWORD buf_len; - if (CM_Get_Device_Interface_List_SizeW( - &buf_len, (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)entry->value, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS) - goto err_hash; - interfaces = calloc(buf_len, sizeof(*interfaces)); - if (!interfaces) - goto err_hash; - if (CM_Get_Device_Interface_ListW( - (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)entry->value, interfaces, buf_len, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || !interfaces[0]) { - free(interfaces); - interfaces = NULL; - goto err_hash; - } - handle = CreateFileW(interfaces, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, 0, NULL); - free(interfaces); - if (handle == INVALID_HANDLE_VALUE) - goto err_hash; - return handle; -err_hash: - errno = EACCES; - return NULL; - } - } + if (have_cached_kernel_interfaces) + { + struct hashtable_entry* entry = + hashtable_find_entry(&cached_kernel_interfaces, iface); + if (entry) + { + DWORD buf_len; + if (CM_Get_Device_Interface_List_SizeW( + &buf_len, + (GUID*)&GUID_DEVINTERFACE_NET, + (DEVINSTID_W)entry->value, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS) + goto err_hash; + interfaces = calloc(buf_len, sizeof(*interfaces)); + if (!interfaces) + goto err_hash; + if (CM_Get_Device_Interface_ListW( + (GUID*)&GUID_DEVINTERFACE_NET, + (DEVINSTID_W)entry->value, + interfaces, + buf_len, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || + !interfaces[0]) + { + free(interfaces); + interfaces = NULL; + goto err_hash; + } + handle = CreateFileW( + interfaces, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + 0, + NULL); + free(interfaces); + if (handle == INVALID_HANDLE_VALUE) + goto err_hash; + return handle; + err_hash: + errno = EACCES; + return NULL; + } + } - dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL); - if (dev_info == INVALID_HANDLE_VALUE) - return NULL; + dev_info = SetupDiGetClassDevsExW( + &GUID_DEVCLASS_NET, + is_win7 ? L"ROOT\\WIREGUARD" : L"SWD\\WireGuard", + NULL, + DIGCF_PRESENT, + NULL, + NULL, + NULL); + if (dev_info == INVALID_HANDLE_VALUE) + return NULL; - for (DWORD i = 0; !interfaces; ++i) { - bool found; - DWORD buf_len; - WCHAR *buf, adapter_name[MAX_ADAPTER_NAME]; - SP_DEVINFO_DATA dev_info_data = { .cbSize = sizeof(SP_DEVINFO_DATA) }; - DEVPROPTYPE prop_type; - char *interface_name; + for (DWORD i = 0; !interfaces; ++i) + { + bool found; + DWORD buf_len; + WCHAR * buf, adapter_name[MAX_ADAPTER_NAME]; + SP_DEVINFO_DATA dev_info_data = {.cbSize = sizeof(SP_DEVINFO_DATA)}; + DEVPROPTYPE prop_type; + char* interface_name; - if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) { - if (GetLastError() == ERROR_NO_MORE_ITEMS) - break; - continue; - } + if (!SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data)) + { + if (GetLastError() == ERROR_NO_MORE_ITEMS) + break; + continue; + } - if (!SetupDiGetDevicePropertyW(dev_info, &dev_info_data, &devpkey_name, - &prop_type, (PBYTE)adapter_name, - sizeof(adapter_name), NULL, 0) || - prop_type != DEVPROP_TYPE_STRING) - continue; - adapter_name[_countof(adapter_name) - 1] = L'0'; - if (!adapter_name[0]) - continue; - buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, NULL, 0, NULL, NULL); - if (!buf_len) - continue; - interface_name = malloc(buf_len); - if (!interface_name) - continue; - buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL); - if (!buf_len) { - free(interface_name); - continue; - } - found = !strcmp(interface_name, iface); - free(interface_name); - if (!found) - continue; + if (!SetupDiGetDevicePropertyW( + dev_info, + &dev_info_data, + &devpkey_name, + &prop_type, + (PBYTE)adapter_name, + sizeof(adapter_name), + NULL, + 0) || + prop_type != DEVPROP_TYPE_STRING) + continue; + adapter_name[_countof(adapter_name) - 1] = L'0'; + if (!adapter_name[0]) + continue; + buf_len = WideCharToMultiByte(CP_UTF8, 0, adapter_name, -1, NULL, 0, NULL, NULL); + if (!buf_len) + continue; + interface_name = malloc(buf_len); + if (!interface_name) + continue; + buf_len = WideCharToMultiByte( + CP_UTF8, 0, adapter_name, -1, interface_name, buf_len, NULL, NULL); + if (!buf_len) + { + free(interface_name); + continue; + } + found = !strcmp(interface_name, iface); + free(interface_name); + if (!found) + continue; - if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) - continue; - buf = calloc(sizeof(*buf), buf_len); - if (!buf) - continue; - if (!SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, buf, buf_len, &buf_len)) - goto cleanup_instance_id; - if (CM_Get_Device_Interface_List_SizeW( - &buf_len, (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)buf, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS) - goto cleanup_instance_id; - interfaces = calloc(buf_len, sizeof(*interfaces)); - if (!interfaces) - goto cleanup_instance_id; - if (CM_Get_Device_Interface_ListW( - (GUID *)&GUID_DEVINTERFACE_NET, (DEVINSTID_W)buf, interfaces, buf_len, - CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || !interfaces[0]) { - free(interfaces); - interfaces = NULL; - goto cleanup_instance_id; - } -cleanup_instance_id: - free(buf); - } - SetupDiDestroyDeviceInfoList(dev_info); - if (!interfaces) { - errno = ENOENT; - return NULL; - } - handle = CreateFileW(interfaces, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, 0, NULL); - free(interfaces); - if (handle == INVALID_HANDLE_VALUE) { - errno = EACCES; - return NULL; - } - return handle; + if (SetupDiGetDeviceInstanceIdW(dev_info, &dev_info_data, NULL, 0, &buf_len) || + GetLastError() != ERROR_INSUFFICIENT_BUFFER) + continue; + buf = calloc(sizeof(*buf), buf_len); + if (!buf) + continue; + if (!SetupDiGetDeviceInstanceIdW( + dev_info, &dev_info_data, buf, buf_len, &buf_len)) + goto cleanup_instance_id; + if (CM_Get_Device_Interface_List_SizeW( + &buf_len, + (GUID*)&GUID_DEVINTERFACE_NET, + (DEVINSTID_W)buf, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS) + goto cleanup_instance_id; + interfaces = calloc(buf_len, sizeof(*interfaces)); + if (!interfaces) + goto cleanup_instance_id; + if (CM_Get_Device_Interface_ListW( + (GUID*)&GUID_DEVINTERFACE_NET, + (DEVINSTID_W)buf, + interfaces, + buf_len, + CM_GET_DEVICE_INTERFACE_LIST_PRESENT) != CR_SUCCESS || + !interfaces[0]) + { + free(interfaces); + interfaces = NULL; + goto cleanup_instance_id; + } + cleanup_instance_id: + free(buf); + } + SetupDiDestroyDeviceInfoList(dev_info); + if (!interfaces) + { + errno = ENOENT; + return NULL; + } + handle = CreateFileW( + interfaces, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + 0, + NULL); + free(interfaces); + if (handle == INVALID_HANDLE_VALUE) + { + errno = EACCES; + return NULL; + } + return handle; } -static int kernel_get_device(struct wgdevice **device, const char *iface) +static int kernel_get_device(struct wgdevice** device, const char* iface) { - WG_IOCTL_INTERFACE *wg_iface; - WG_IOCTL_PEER *wg_peer; - WG_IOCTL_ALLOWED_IP *wg_aip; - void *buf = NULL; - DWORD buf_len = 0; - HANDLE handle = kernel_interface_handle(iface); - struct wgdevice *dev; - struct wgpeer *peer; - struct wgallowedip *aip; - int ret; + WG_IOCTL_INTERFACE* wg_iface; + WG_IOCTL_PEER* wg_peer; + WG_IOCTL_ALLOWED_IP* wg_aip; + void* buf = NULL; + DWORD buf_len = 0; + HANDLE handle = kernel_interface_handle(iface); + struct wgdevice* dev; + struct wgpeer* peer; + struct wgallowedip* aip; + int ret; - *device = NULL; + *device = NULL; - if (!handle) - return -errno; + if (!handle) + return -errno; - while (!DeviceIoControl(handle, WG_IOCTL_GET, NULL, 0, buf, buf_len, &buf_len, NULL)) { - free(buf); - if (GetLastError() != ERROR_MORE_DATA) { - errno = EACCES; - return -errno; - } - buf = malloc(buf_len); - if (!buf) - return -errno; - } + while (!DeviceIoControl(handle, WG_IOCTL_GET, NULL, 0, buf, buf_len, &buf_len, NULL)) + { + free(buf); + if (GetLastError() != ERROR_MORE_DATA) + { + errno = EACCES; + return -errno; + } + buf = malloc(buf_len); + if (!buf) + return -errno; + } - wg_iface = (WG_IOCTL_INTERFACE *)buf; - dev = calloc(1, sizeof(*dev)); - if (!dev) - goto out; - strncpy(dev->name, iface, sizeof(dev->name)); - dev->name[sizeof(dev->name) - 1] = '\0'; + wg_iface = (WG_IOCTL_INTERFACE*)buf; + dev = calloc(1, sizeof(*dev)); + if (!dev) + goto out; + strncpy(dev->name, iface, sizeof(dev->name)); + dev->name[sizeof(dev->name) - 1] = '\0'; - if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_LISTEN_PORT) { - dev->listen_port = wg_iface->ListenPort; - dev->flags |= WGDEVICE_HAS_LISTEN_PORT; - } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_LISTEN_PORT) + { + dev->listen_port = wg_iface->ListenPort; + dev->flags |= WGDEVICE_HAS_LISTEN_PORT; + } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY) { - memcpy(dev->public_key, wg_iface->PublicKey, sizeof(dev->public_key)); - dev->flags |= WGDEVICE_HAS_PUBLIC_KEY; - } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY) + { + memcpy(dev->public_key, wg_iface->PublicKey, sizeof(dev->public_key)); + dev->flags |= WGDEVICE_HAS_PUBLIC_KEY; + } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY) { - memcpy(dev->private_key, wg_iface->PrivateKey, sizeof(dev->private_key)); - dev->flags |= WGDEVICE_HAS_PRIVATE_KEY; - } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY) + { + memcpy(dev->private_key, wg_iface->PrivateKey, sizeof(dev->private_key)); + dev->flags |= WGDEVICE_HAS_PRIVATE_KEY; + } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_JC) { - dev->junk_packet_count = wg_iface->JunkPacketCount; - dev->flags |= WGDEVICE_HAS_JC; - } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMIN) { - dev->junk_packet_min_size = wg_iface->JunkPacketMinSize; - dev->flags |= WGDEVICE_HAS_JMIN; - } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMAX) { - dev->junk_packet_max_size = wg_iface->JunkPacketMaxSize; - dev->flags |= WGDEVICE_HAS_JMAX; - } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_S1) { - dev->init_packet_junk_size = wg_iface->InitPacketJunkSize; - dev->flags |= WGDEVICE_HAS_S1; - } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_S2) { - dev->response_packet_junk_size = wg_iface->ResponsePacketJunkSize; - dev->flags |= WGDEVICE_HAS_S2; - } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_H1) { - dev->init_packet_magic_header = wg_iface->InitPacketMagicHeader; - dev->flags |= WGDEVICE_HAS_H1; - } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_H2) { - dev->response_packet_magic_header = wg_iface->ResponsePacketMagicHeader; - dev->flags |= WGDEVICE_HAS_H2; - } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_H3) { - dev->underload_packet_magic_header = wg_iface->UnderloadPacketMagicHeader; - dev->flags |= WGDEVICE_HAS_H3; - } - if (wg_iface->Flags & WG_IOCTL_INTERFACE_H4) { - dev->transport_packet_magic_header = wg_iface->TransportPacketMagicHeader; - dev->flags |= WGDEVICE_HAS_H4; - } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_JC) + { + dev->junk_packet_count = wg_iface->JunkPacketCount; + dev->flags |= WGDEVICE_HAS_JC; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMIN) + { + dev->junk_packet_min_size = wg_iface->JunkPacketMinSize; + dev->flags |= WGDEVICE_HAS_JMIN; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_JMAX) + { + dev->junk_packet_max_size = wg_iface->JunkPacketMaxSize; + dev->flags |= WGDEVICE_HAS_JMAX; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_S1) + { + dev->init_packet_junk_size = wg_iface->InitPacketJunkSize; + dev->flags |= WGDEVICE_HAS_S1; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_S2) + { + dev->response_packet_junk_size = wg_iface->ResponsePacketJunkSize; + dev->flags |= WGDEVICE_HAS_S2; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_H1) + { + dev->init_packet_magic_header = wg_iface->InitPacketMagicHeader; + dev->flags |= WGDEVICE_HAS_H1; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_H2) + { + dev->response_packet_magic_header = wg_iface->ResponsePacketMagicHeader; + dev->flags |= WGDEVICE_HAS_H2; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_H3) + { + dev->underload_packet_magic_header = wg_iface->UnderloadPacketMagicHeader; + dev->flags |= WGDEVICE_HAS_H3; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_H4) + { + dev->transport_packet_magic_header = wg_iface->TransportPacketMagicHeader; + dev->flags |= WGDEVICE_HAS_H4; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_I1) + { + const size_t i1_size = strlen((char*)wg_iface->I1) + 1; + dev->i1 = (char*)malloc(i1_size); + memcpy(dev->i1, wg_iface->I1, i1_size); + dev->flags |= WGDEVICE_HAS_I1; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_I2) + { + const size_t i2_size = strlen((char*)wg_iface->I2) + 1; + dev->i2 = (char*)malloc(i2_size); + memcpy(dev->i2, wg_iface->I2, i2_size); + dev->flags |= WGDEVICE_HAS_I2; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_I3) + { + const size_t i3_size = strlen((char*)wg_iface->I3) + 1; + dev->i3 = (char*)malloc(i3_size); + memcpy(dev->i3, wg_iface->I3, i3_size); + dev->flags |= WGDEVICE_HAS_I3; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_I4) + { + const size_t i4_size = strlen((char*)wg_iface->I4) + 1; + dev->i4 = (char*)malloc(i4_size); + memcpy(dev->i4, wg_iface->I4, i4_size); + dev->flags |= WGDEVICE_HAS_I4; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_I5) + { + const size_t i5_size = strlen((char*)wg_iface->I5) + 1; + dev->i5 = (char*)malloc(i5_size); + memcpy(dev->i5, wg_iface->I5, i5_size); + dev->flags |= WGDEVICE_HAS_I5; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_J1) + { + const size_t j1_size = strlen((char*)wg_iface->J1) + 1; + dev->j1 = (char*)malloc(j1_size); + memcpy(dev->j1, wg_iface->J1, j1_size); + dev->flags |= WGDEVICE_HAS_J1; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_J2) + { + const size_t j2_size = strlen((char*)wg_iface->J2) + 1; + dev->j2 = (char*)malloc(j2_size); + memcpy(dev->j2, wg_iface->J2, j2_size); + dev->flags |= WGDEVICE_HAS_J2; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_J3) + { + const size_t j3_size = strlen((char*)wg_iface->J3) + 1; + dev->j3 = (char*)malloc(j3_size); + memcpy(dev->j3, wg_iface->J3, j3_size); + dev->flags |= WGDEVICE_HAS_J3; + } + if (wg_iface->Flags & WG_IOCTL_INTERFACE_ITIME) + { + dev->itime = wg_iface->Itime; + dev->flags |= WGDEVICE_HAS_ITIME; + } - wg_peer = buf + sizeof(WG_IOCTL_INTERFACE); - for (ULONG i = 0; i < wg_iface->PeersCount; ++i) { - peer = calloc(1, sizeof(*peer)); - if (!peer) - goto out; + wg_peer = buf + sizeof(WG_IOCTL_INTERFACE); + for (ULONG i = 0; i < wg_iface->PeersCount; ++i) + { + peer = calloc(1, sizeof(*peer)); + if (!peer) + goto out; - if (dev->first_peer == NULL) - dev->first_peer = peer; - else - dev->last_peer->next_peer = peer; - dev->last_peer = peer; + if (dev->first_peer == NULL) + dev->first_peer = peer; + else + dev->last_peer->next_peer = peer; + dev->last_peer = peer; - if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PUBLIC_KEY) { - memcpy(peer->public_key, wg_peer->PublicKey, sizeof(peer->public_key)); - peer->flags |= WGPEER_HAS_PUBLIC_KEY; - } + if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PUBLIC_KEY) + { + memcpy(peer->public_key, wg_peer->PublicKey, sizeof(peer->public_key)); + peer->flags |= WGPEER_HAS_PUBLIC_KEY; + } - if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PRESHARED_KEY) { - memcpy(peer->preshared_key, wg_peer->PresharedKey, sizeof(peer->preshared_key)); - if (!key_is_zero(peer->preshared_key)) - peer->flags |= WGPEER_HAS_PRESHARED_KEY; - } + if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PRESHARED_KEY) + { + memcpy( + peer->preshared_key, wg_peer->PresharedKey, sizeof(peer->preshared_key)); + if (!key_is_zero(peer->preshared_key)) + peer->flags |= WGPEER_HAS_PRESHARED_KEY; + } - if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE) { - peer->persistent_keepalive_interval = wg_peer->PersistentKeepalive; - peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; - } + if (wg_peer->Flags & WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE) + { + peer->persistent_keepalive_interval = wg_peer->PersistentKeepalive; + peer->flags |= WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL; + } - if (wg_peer->Flags & WG_IOCTL_PEER_HAS_ENDPOINT) { - if (wg_peer->Endpoint.si_family == AF_INET) - peer->endpoint.addr4 = wg_peer->Endpoint.Ipv4; - else if (wg_peer->Endpoint.si_family == AF_INET6) - peer->endpoint.addr6 = wg_peer->Endpoint.Ipv6; - } + if (wg_peer->Flags & WG_IOCTL_PEER_HAS_ENDPOINT) + { + if (wg_peer->Endpoint.si_family == AF_INET) + peer->endpoint.addr4 = wg_peer->Endpoint.Ipv4; + else if (wg_peer->Endpoint.si_family == AF_INET6) + peer->endpoint.addr6 = wg_peer->Endpoint.Ipv6; + } - peer->rx_bytes = wg_peer->RxBytes; - peer->tx_bytes = wg_peer->TxBytes; + peer->rx_bytes = wg_peer->RxBytes; + peer->tx_bytes = wg_peer->TxBytes; - if (wg_peer->LastHandshake) { - peer->last_handshake_time.tv_sec = wg_peer->LastHandshake / 10000000 - 11644473600LL; - peer->last_handshake_time.tv_nsec = wg_peer->LastHandshake % 10000000 * 100; - } + if (wg_peer->LastHandshake) + { + peer->last_handshake_time.tv_sec = + wg_peer->LastHandshake / 10000000 - 11644473600LL; + peer->last_handshake_time.tv_nsec = wg_peer->LastHandshake % 10000000 * 100; + } - wg_aip = (void *)wg_peer + sizeof(WG_IOCTL_PEER); - for (ULONG j = 0; j < wg_peer->AllowedIPsCount; ++j) { - aip = calloc(1, sizeof(*aip)); - if (!aip) - goto out; + wg_aip = (void*)wg_peer + sizeof(WG_IOCTL_PEER); + for (ULONG j = 0; j < wg_peer->AllowedIPsCount; ++j) + { + aip = calloc(1, sizeof(*aip)); + if (!aip) + goto out; - if (peer->first_allowedip == NULL) - peer->first_allowedip = aip; - else - peer->last_allowedip->next_allowedip = aip; - peer->last_allowedip = aip; + if (peer->first_allowedip == NULL) + peer->first_allowedip = aip; + else + peer->last_allowedip->next_allowedip = aip; + peer->last_allowedip = aip; - aip->family = wg_aip->AddressFamily; - if (wg_aip->AddressFamily == AF_INET) { - memcpy(&aip->ip4, &wg_aip->Address.V4, sizeof(aip->ip4)); - aip->cidr = wg_aip->Cidr; - } else if (wg_aip->AddressFamily == AF_INET6) { - memcpy(&aip->ip6, &wg_aip->Address.V6, sizeof(aip->ip6)); - aip->cidr = wg_aip->Cidr; - } - ++wg_aip; - } - wg_peer = (WG_IOCTL_PEER *)wg_aip; - } - *device = dev; - errno = 0; + aip->family = wg_aip->AddressFamily; + if (wg_aip->AddressFamily == AF_INET) + { + memcpy(&aip->ip4, &wg_aip->Address.V4, sizeof(aip->ip4)); + aip->cidr = wg_aip->Cidr; + } + else if (wg_aip->AddressFamily == AF_INET6) + { + memcpy(&aip->ip6, &wg_aip->Address.V6, sizeof(aip->ip6)); + aip->cidr = wg_aip->Cidr; + } + ++wg_aip; + } + wg_peer = (WG_IOCTL_PEER*)wg_aip; + } + *device = dev; + errno = 0; out: - ret = -errno; - free(buf); - CloseHandle(handle); - return ret; + ret = -errno; + free(buf); + CloseHandle(handle); + return ret; } -static int kernel_set_device(struct wgdevice *dev) +static int kernel_set_device(struct wgdevice* dev) { - WG_IOCTL_INTERFACE *wg_iface = NULL; - WG_IOCTL_PEER *wg_peer; - WG_IOCTL_ALLOWED_IP *wg_aip; - DWORD buf_len = sizeof(WG_IOCTL_INTERFACE); - HANDLE handle = kernel_interface_handle(dev->name); - struct wgpeer *peer; - struct wgallowedip *aip; - size_t peer_count, aip_count; - int ret = 0; + WG_IOCTL_INTERFACE* wg_iface = NULL; + WG_IOCTL_PEER* wg_peer; + WG_IOCTL_ALLOWED_IP* wg_aip; + DWORD buf_len = sizeof(WG_IOCTL_INTERFACE); + HANDLE handle = kernel_interface_handle(dev->name); + struct wgpeer* peer; + struct wgallowedip* aip; + size_t peer_count, aip_count; + int ret = 0; - if (!handle) - return -errno; + if (!handle) + return -errno; - for_each_wgpeer(dev, peer) { - if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_PEER)) { - errno = EOVERFLOW; - goto out; - } - buf_len += sizeof(WG_IOCTL_PEER); - for_each_wgallowedip(peer, aip) { - if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_ALLOWED_IP)) { - errno = EOVERFLOW; - goto out; - } - buf_len += sizeof(WG_IOCTL_ALLOWED_IP); - } - } - wg_iface = calloc(1, buf_len); - if (!wg_iface) - goto out; + for_each_wgpeer(dev, peer) + { + if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_PEER)) + { + errno = EOVERFLOW; + goto out; + } + buf_len += sizeof(WG_IOCTL_PEER); + for_each_wgallowedip(peer, aip) + { + if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_ALLOWED_IP)) + { + errno = EOVERFLOW; + goto out; + } + buf_len += sizeof(WG_IOCTL_ALLOWED_IP); + } + } + wg_iface = calloc(1, buf_len); + if (!wg_iface) + goto out; - if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) { - memcpy(wg_iface->PrivateKey, dev->private_key, sizeof(wg_iface->PrivateKey)); - wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY; - } + if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) + { + memcpy(wg_iface->PrivateKey, dev->private_key, sizeof(wg_iface->PrivateKey)); + wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY; + } - if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) { - wg_iface->ListenPort = dev->listen_port; - wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_LISTEN_PORT; - } + if (dev->flags & WGDEVICE_HAS_LISTEN_PORT) + { + wg_iface->ListenPort = dev->listen_port; + wg_iface->Flags |= WG_IOCTL_INTERFACE_HAS_LISTEN_PORT; + } - if (dev->flags & WGDEVICE_REPLACE_PEERS) - wg_iface->Flags |= WG_IOCTL_INTERFACE_REPLACE_PEERS; + if (dev->flags & WGDEVICE_REPLACE_PEERS) + wg_iface->Flags |= WG_IOCTL_INTERFACE_REPLACE_PEERS; - if (dev->flags & WGDEVICE_HAS_JC) { - wg_iface->JunkPacketCount = dev->junk_packet_count; - wg_iface->Flags |= WG_IOCTL_INTERFACE_JC; - } + if (dev->flags & WGDEVICE_HAS_JC) + { + wg_iface->JunkPacketCount = dev->junk_packet_count; + wg_iface->Flags |= WG_IOCTL_INTERFACE_JC; + } - if (dev->flags & WGDEVICE_HAS_JMIN) { - wg_iface->JunkPacketMinSize = dev->junk_packet_min_size; - wg_iface->Flags |= WG_IOCTL_INTERFACE_JMIN; - } + if (dev->flags & WGDEVICE_HAS_JMIN) + { + wg_iface->JunkPacketMinSize = dev->junk_packet_min_size; + wg_iface->Flags |= WG_IOCTL_INTERFACE_JMIN; + } - if (dev->flags & WGDEVICE_HAS_JMAX) { - wg_iface->JunkPacketMaxSize = dev->junk_packet_max_size; - wg_iface->Flags |= WG_IOCTL_INTERFACE_JMAX; - } + if (dev->flags & WGDEVICE_HAS_JMAX) + { + wg_iface->JunkPacketMaxSize = dev->junk_packet_max_size; + wg_iface->Flags |= WG_IOCTL_INTERFACE_JMAX; + } - if (dev->flags & WGDEVICE_HAS_S1) { - wg_iface->InitPacketJunkSize = dev->init_packet_junk_size; - wg_iface->Flags |= WG_IOCTL_INTERFACE_S1; - } + if (dev->flags & WGDEVICE_HAS_S1) + { + wg_iface->InitPacketJunkSize = dev->init_packet_junk_size; + wg_iface->Flags |= WG_IOCTL_INTERFACE_S1; + } - if (dev->flags & WGDEVICE_HAS_S2) { - wg_iface->ResponsePacketJunkSize = dev->response_packet_junk_size; - wg_iface->Flags |= WG_IOCTL_INTERFACE_S2; - } + if (dev->flags & WGDEVICE_HAS_S2) + { + wg_iface->ResponsePacketJunkSize = dev->response_packet_junk_size; + wg_iface->Flags |= WG_IOCTL_INTERFACE_S2; + } - if (dev->flags & WGDEVICE_HAS_H1) { - wg_iface->InitPacketMagicHeader = dev->init_packet_magic_header; - wg_iface->Flags |= WG_IOCTL_INTERFACE_H1; - } + if (dev->flags & WGDEVICE_HAS_H1) + { + wg_iface->InitPacketMagicHeader = dev->init_packet_magic_header; + wg_iface->Flags |= WG_IOCTL_INTERFACE_H1; + } - if (dev->flags & WGDEVICE_HAS_H2) { - wg_iface->ResponsePacketMagicHeader = dev->response_packet_magic_header; - wg_iface->Flags |= WG_IOCTL_INTERFACE_H2; - } + if (dev->flags & WGDEVICE_HAS_H2) + { + wg_iface->ResponsePacketMagicHeader = dev->response_packet_magic_header; + wg_iface->Flags |= WG_IOCTL_INTERFACE_H2; + } - if (dev->flags & WGDEVICE_HAS_H3) { - wg_iface->UnderloadPacketMagicHeader = dev->underload_packet_magic_header; - wg_iface->Flags |= WG_IOCTL_INTERFACE_H3; - } + if (dev->flags & WGDEVICE_HAS_H3) + { + wg_iface->UnderloadPacketMagicHeader = dev->underload_packet_magic_header; + wg_iface->Flags |= WG_IOCTL_INTERFACE_H3; + } - if (dev->flags & WGDEVICE_HAS_H4) { - wg_iface->TransportPacketMagicHeader = dev->transport_packet_magic_header; - wg_iface->Flags |= WG_IOCTL_INTERFACE_H4; - } + if (dev->flags & WGDEVICE_HAS_H4) + { + wg_iface->TransportPacketMagicHeader = dev->transport_packet_magic_header; + wg_iface->Flags |= WG_IOCTL_INTERFACE_H4; + } + if (dev->flags & WG_DEVICE_HAS_I1) + { + const size_t i1_size = strlen(dev->i1); + wg_iface->I1 = (UCHAR*)malloc(i1_size + 1); + memcpy(wg_iface->I1, dev->i1, i1_size); + dev->flags |= WG_IOCTL_INTERFACE_I1; + } + if (dev->flags & WG_DEVICE_HAS_I2) + { + const size_t i2_size = strlen(dev->i2); + wg_iface->I2 = (UCHAR*)malloc(i2_size + 1); + memcpy(wg_iface->I2, dev->i2, i2_size); + dev->flags |= WG_IOCTL_INTERFACE_I2; + } + if (dev->flags & WG_DEVICE_HAS_I3) + { + const size_t i3_size = strlen(dev->i3); + wg_iface->I3 = (UCHAR*)malloc(i3_size + 1); + memcpy(wg_iface->I3, dev->i3, i3_size); + dev->flags |= WG_IOCTL_INTERFACE_I3; + } + if (dev->flags & WG_DEVICE_HAS_I4) + { + const size_t i4_size = strlen(dev->i4); + wg_iface->I4 = (UCHAR*)malloc(i4_size + 1); + memcpy(wg_iface->I4, dev->i4, i4_size); + dev->flags |= WG_IOCTL_INTERFACE_I4; + } + if (dev->flags & WG_DEVICE_HAS_I5) + { + const size_t i5_size = strlen(dev->i5); + wg_iface->I5 = (UCHAR*)malloc(i5_size + 1); + memcpy(wg_iface->I5, dev->i5, i5_size); + dev->flags |= WG_IOCTL_INTERFACE_I5; + } + if (dev->flags & WG_DEVICE_HAS_J1) + { + const size_t j1_size = strlen(dev->j1); + wg_iface->J1 = (UCHAR*)malloc(j1_size + 1); + memcpy(wg_iface->J1, dev->j1, j1_size); + dev->flags |= WG_IOCTL_INTERFACE_J1; + } + if (dev->flags & WG_DEVICE_HAS_J2) + { + const size_t j2_size = strlen(dev->j2); + wg_iface->J2 = (UCHAR*)malloc(j2_size + 1); + memcpy(wg_iface->J2, dev->j2, j2_size); + dev->flags |= WG_IOCTL_INTERFACE_J2; + } + if (dev->flags & WG_DEVICE_HAS_J3) + { + const size_t j3_size = strlen(dev->j3); + wg_iface->J3 = (UCHAR*)malloc(j3_size + 1); + memcpy(wg_iface->J3, dev->j3, j3_size); + dev->flags |= WG_IOCTL_INTERFACE_J3; + } + if (dev->flags & WG_DEVICE_HAS_ITIME) + { + wg_iface->Itime = dev->Itime; + wg_iface->flags |= WG_IOCTL_INTERFACE_HAS_ITIME; + } - peer_count = 0; - wg_peer = (void *)wg_iface + sizeof(WG_IOCTL_INTERFACE); - for_each_wgpeer(dev, peer) { - wg_peer->Flags = WG_IOCTL_PEER_HAS_PUBLIC_KEY; - memcpy(wg_peer->PublicKey, peer->public_key, sizeof(wg_peer->PublicKey)); + peer_count = 0; + wg_peer = (void*)wg_iface + sizeof(WG_IOCTL_INTERFACE); + for_each_wgpeer(dev, peer) + { + wg_peer->Flags = WG_IOCTL_PEER_HAS_PUBLIC_KEY; + memcpy(wg_peer->PublicKey, peer->public_key, sizeof(wg_peer->PublicKey)); - if (peer->flags & WGPEER_HAS_PRESHARED_KEY) { - memcpy(wg_peer->PresharedKey, peer->preshared_key, sizeof(wg_peer->PresharedKey)); - wg_peer->Flags |= WG_IOCTL_PEER_HAS_PRESHARED_KEY; - } + if (peer->flags & WGPEER_HAS_PRESHARED_KEY) + { + memcpy( + wg_peer->PresharedKey, + peer->preshared_key, + sizeof(wg_peer->PresharedKey)); + wg_peer->Flags |= WG_IOCTL_PEER_HAS_PRESHARED_KEY; + } - if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) { - wg_peer->PersistentKeepalive = peer->persistent_keepalive_interval; - wg_peer->Flags |= WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE; - } + if (peer->flags & WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL) + { + wg_peer->PersistentKeepalive = peer->persistent_keepalive_interval; + wg_peer->Flags |= WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE; + } - if (peer->endpoint.addr.sa_family == AF_INET) { - wg_peer->Endpoint.Ipv4 = peer->endpoint.addr4; - wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT; - } else if (peer->endpoint.addr.sa_family == AF_INET6) { - wg_peer->Endpoint.Ipv6 = peer->endpoint.addr6; - wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT; - } + if (peer->endpoint.addr.sa_family == AF_INET) + { + wg_peer->Endpoint.Ipv4 = peer->endpoint.addr4; + wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT; + } + else if (peer->endpoint.addr.sa_family == AF_INET6) + { + wg_peer->Endpoint.Ipv6 = peer->endpoint.addr6; + wg_peer->Flags |= WG_IOCTL_PEER_HAS_ENDPOINT; + } - if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) - wg_peer->Flags |= WG_IOCTL_PEER_REPLACE_ALLOWED_IPS; + if (peer->flags & WGPEER_REPLACE_ALLOWEDIPS) + wg_peer->Flags |= WG_IOCTL_PEER_REPLACE_ALLOWED_IPS; - if (peer->flags & WGPEER_REMOVE_ME) - wg_peer->Flags |= WG_IOCTL_PEER_REMOVE; + if (peer->flags & WGPEER_REMOVE_ME) + wg_peer->Flags |= WG_IOCTL_PEER_REMOVE; - aip_count = 0; - wg_aip = (void *)wg_peer + sizeof(WG_IOCTL_PEER); - for_each_wgallowedip(peer, aip) { - wg_aip->AddressFamily = aip->family; - wg_aip->Cidr = aip->cidr; + aip_count = 0; + wg_aip = (void*)wg_peer + sizeof(WG_IOCTL_PEER); + for_each_wgallowedip(peer, aip) + { + wg_aip->AddressFamily = aip->family; + wg_aip->Cidr = aip->cidr; - if (aip->family == AF_INET) - wg_aip->Address.V4 = aip->ip4; - else if (aip->family == AF_INET6) - wg_aip->Address.V6 = aip->ip6; - else - continue; - ++aip_count; - ++wg_aip; - } - wg_peer->AllowedIPsCount = aip_count; - ++peer_count; - wg_peer = (WG_IOCTL_PEER *)wg_aip; - } - wg_iface->PeersCount = peer_count; + if (aip->family == AF_INET) + wg_aip->Address.V4 = aip->ip4; + else if (aip->family == AF_INET6) + wg_aip->Address.V6 = aip->ip6; + else + continue; + ++aip_count; + ++wg_aip; + } + wg_peer->AllowedIPsCount = aip_count; + ++peer_count; + wg_peer = (WG_IOCTL_PEER*)wg_aip; + } + wg_iface->PeersCount = peer_count; - if (!DeviceIoControl(handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len, NULL)) { - errno = EACCES; - goto out; - } - errno = 0; + if (!DeviceIoControl( + handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len, NULL)) + { + errno = EACCES; + goto out; + } + errno = 0; out: - ret = -errno; - free(wg_iface); - CloseHandle(handle); - return ret; + ret = -errno; + free(wg_iface); + CloseHandle(handle); + return ret; } diff --git a/src/netlink.h b/src/netlink.h index f9729ee..08f1382 100644 --- a/src/netlink.h +++ b/src/netlink.h @@ -6,792 +6,853 @@ /* This is a minimized version of libmnl meant to be #include'd */ -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define MNL_SOCKET_AUTOPID 0 #define MNL_ALIGNTO 4 -#define MNL_ALIGN(len) (((len)+MNL_ALIGNTO-1) & ~(MNL_ALIGNTO-1)) +#define MNL_ALIGN(len) (((len) + MNL_ALIGNTO - 1) & ~(MNL_ALIGNTO - 1)) #define MNL_NLMSG_HDRLEN MNL_ALIGN(sizeof(struct nlmsghdr)) #define MNL_ATTR_HDRLEN MNL_ALIGN(sizeof(struct nlattr)) -enum mnl_attr_data_type { - MNL_TYPE_UNSPEC, - MNL_TYPE_U8, - MNL_TYPE_U16, - MNL_TYPE_U32, - MNL_TYPE_U64, - MNL_TYPE_STRING, - MNL_TYPE_FLAG, - MNL_TYPE_MSECS, - MNL_TYPE_NESTED, - MNL_TYPE_NESTED_COMPAT, - MNL_TYPE_NUL_STRING, - MNL_TYPE_BINARY, - MNL_TYPE_MAX, +enum mnl_attr_data_type +{ + MNL_TYPE_UNSPEC, + MNL_TYPE_U8, + MNL_TYPE_U16, + MNL_TYPE_U32, + MNL_TYPE_U64, + MNL_TYPE_STRING, + MNL_TYPE_FLAG, + MNL_TYPE_MSECS, + MNL_TYPE_NESTED, + MNL_TYPE_NESTED_COMPAT, + MNL_TYPE_NUL_STRING, + MNL_TYPE_BINARY, + MNL_TYPE_MAX, }; -#define mnl_attr_for_each(attr, nlh, offset) \ - for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \ - mnl_attr_ok((attr), (char *)mnl_nlmsg_get_payload_tail(nlh) - (char *)(attr)); \ - (attr) = mnl_attr_next(attr)) +#define mnl_attr_for_each(attr, nlh, offset) \ + for ((attr) = mnl_nlmsg_get_payload_offset((nlh), (offset)); \ + mnl_attr_ok((attr), (char*)mnl_nlmsg_get_payload_tail(nlh) - (char*)(attr)); \ + (attr) = mnl_attr_next(attr)) -#define mnl_attr_for_each_nested(attr, nest) \ - for ((attr) = mnl_attr_get_payload(nest); \ - mnl_attr_ok((attr), (char *)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - (char *)(attr)); \ - (attr) = mnl_attr_next(attr)) +#define mnl_attr_for_each_nested(attr, nest) \ + for ((attr) = mnl_attr_get_payload(nest); mnl_attr_ok( \ + (attr), \ + (char*)mnl_attr_get_payload(nest) + mnl_attr_get_payload_len(nest) - \ + (char*)(attr)); \ + (attr) = mnl_attr_next(attr)) -#define mnl_attr_for_each_payload(payload, payload_size) \ - for ((attr) = (payload); \ - mnl_attr_ok((attr), (char *)(payload) + payload_size - (char *)(attr)); \ - (attr) = mnl_attr_next(attr)) +#define mnl_attr_for_each_payload(payload, payload_size) \ + for ((attr) = (payload); \ + mnl_attr_ok((attr), (char*)(payload) + payload_size - (char*)(attr)); \ + (attr) = mnl_attr_next(attr)) -#define MNL_CB_ERROR -1 -#define MNL_CB_STOP 0 -#define MNL_CB_OK 1 +#define MNL_CB_ERROR -1 +#define MNL_CB_STOP 0 +#define MNL_CB_OK 1 -typedef int (*mnl_attr_cb_t)(const struct nlattr *attr, void *data); -typedef int (*mnl_cb_t)(const struct nlmsghdr *nlh, void *data); +typedef int (*mnl_attr_cb_t)(const struct nlattr* attr, void* data); +typedef int (*mnl_cb_t)(const struct nlmsghdr* nlh, void* data); #ifndef MNL_ARRAY_SIZE -#define MNL_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) +#define MNL_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #endif static size_t mnl_ideal_socket_buffer_size(void) { - static size_t size = 0; + static size_t size = 0; - if (size) - return size; - size = (size_t)sysconf(_SC_PAGESIZE); - if (size > 8192) - size = 8192; - return size; + if (size) + return size; + size = (size_t)sysconf(_SC_PAGESIZE); + if (size > 8192) + size = 8192; + return size; } -static size_t mnl_nlmsg_size(size_t len) +static size_t mnl_nlmsg_size(size_t len) { return len + MNL_NLMSG_HDRLEN; } + +static struct nlmsghdr* mnl_nlmsg_put_header(void* buf) { - return len + MNL_NLMSG_HDRLEN; + int len = MNL_ALIGN(sizeof(struct nlmsghdr)); + struct nlmsghdr* nlh = buf; + + memset(buf, 0, len); + nlh->nlmsg_len = len; + return nlh; } -static struct nlmsghdr *mnl_nlmsg_put_header(void *buf) +static void* mnl_nlmsg_put_extra_header(struct nlmsghdr* nlh, size_t size) { - int len = MNL_ALIGN(sizeof(struct nlmsghdr)); - struct nlmsghdr *nlh = buf; - - memset(buf, 0, len); - nlh->nlmsg_len = len; - return nlh; + char* ptr = (char*)nlh + nlh->nlmsg_len; + size_t len = MNL_ALIGN(size); + nlh->nlmsg_len += len; + memset(ptr, 0, len); + return ptr; } -static void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size) +static void* mnl_nlmsg_get_payload(const struct nlmsghdr* nlh) { - char *ptr = (char *)nlh + nlh->nlmsg_len; - size_t len = MNL_ALIGN(size); - nlh->nlmsg_len += len; - memset(ptr, 0, len); - return ptr; + return (void*)nlh + MNL_NLMSG_HDRLEN; } -static void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh) +static void* mnl_nlmsg_get_payload_offset(const struct nlmsghdr* nlh, size_t offset) { - return (void *)nlh + MNL_NLMSG_HDRLEN; + return (void*)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset); } -static void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset) +static bool mnl_nlmsg_ok(const struct nlmsghdr* nlh, int len) { - return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset); + return len >= (int)sizeof(struct nlmsghdr) && + nlh->nlmsg_len >= sizeof(struct nlmsghdr) && (int)nlh->nlmsg_len <= len; } -static bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len) +static struct nlmsghdr* mnl_nlmsg_next(const struct nlmsghdr* nlh, int* len) { - return len >= (int)sizeof(struct nlmsghdr) && - nlh->nlmsg_len >= sizeof(struct nlmsghdr) && - (int)nlh->nlmsg_len <= len; + *len -= MNL_ALIGN(nlh->nlmsg_len); + return (struct nlmsghdr*)((void*)nlh + MNL_ALIGN(nlh->nlmsg_len)); } -static struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len) +static void* mnl_nlmsg_get_payload_tail(const struct nlmsghdr* nlh) { - *len -= MNL_ALIGN(nlh->nlmsg_len); - return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len)); + return (void*)nlh + MNL_ALIGN(nlh->nlmsg_len); } -static void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh) +static bool mnl_nlmsg_seq_ok(const struct nlmsghdr* nlh, unsigned int seq) { - return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len); + return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true; } -static bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq) +static bool mnl_nlmsg_portid_ok(const struct nlmsghdr* nlh, unsigned int portid) { - return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true; + return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true; } -static bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid) +static uint16_t mnl_attr_get_type(const struct nlattr* attr) { - return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true; + return attr->nla_type & NLA_TYPE_MASK; } -static uint16_t mnl_attr_get_type(const struct nlattr *attr) +static uint16_t mnl_attr_get_payload_len(const struct nlattr* attr) { - return attr->nla_type & NLA_TYPE_MASK; + return attr->nla_len - MNL_ATTR_HDRLEN; } -static uint16_t mnl_attr_get_payload_len(const struct nlattr *attr) +static void* mnl_attr_get_payload(const struct nlattr* attr) { - return attr->nla_len - MNL_ATTR_HDRLEN; + return (void*)attr + MNL_ATTR_HDRLEN; } -static void *mnl_attr_get_payload(const struct nlattr *attr) +static bool mnl_attr_ok(const struct nlattr* attr, int len) { - return (void *)attr + MNL_ATTR_HDRLEN; + return len >= (int)sizeof(struct nlattr) && attr->nla_len >= sizeof(struct nlattr) && + (int)attr->nla_len <= len; } -static bool mnl_attr_ok(const struct nlattr *attr, int len) +static struct nlattr* mnl_attr_next(const struct nlattr* attr) { - return len >= (int)sizeof(struct nlattr) && - attr->nla_len >= sizeof(struct nlattr) && - (int)attr->nla_len <= len; + return (struct nlattr*)((void*)attr + MNL_ALIGN(attr->nla_len)); } -static struct nlattr *mnl_attr_next(const struct nlattr *attr) +static int mnl_attr_type_valid(const struct nlattr* attr, uint16_t max) { - return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len)); + if (mnl_attr_get_type(attr) > max) + { + errno = EOPNOTSUPP; + return -1; + } + return 1; } -static int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max) +static int __mnl_attr_validate( + const struct nlattr* attr, + enum mnl_attr_data_type type, + size_t exp_len) { - if (mnl_attr_get_type(attr) > max) { - errno = EOPNOTSUPP; - return -1; - } - return 1; -} + uint16_t attr_len = mnl_attr_get_payload_len(attr); + const char* attr_data = mnl_attr_get_payload(attr); -static int __mnl_attr_validate(const struct nlattr *attr, - enum mnl_attr_data_type type, size_t exp_len) -{ - uint16_t attr_len = mnl_attr_get_payload_len(attr); - const char *attr_data = mnl_attr_get_payload(attr); + if (attr_len < exp_len) + { + errno = ERANGE; + return -1; + } + switch (type) + { + case MNL_TYPE_FLAG: + if (attr_len > 0) + { + errno = ERANGE; + return -1; + } + break; + case MNL_TYPE_NUL_STRING: + if (attr_len == 0) + { + errno = ERANGE; + return -1; + } + if (attr_data[attr_len - 1] != '\0') + { + errno = EINVAL; + return -1; + } + break; + case MNL_TYPE_STRING: + if (attr_len == 0) + { + errno = ERANGE; + return -1; + } + break; + case MNL_TYPE_NESTED: - if (attr_len < exp_len) { - errno = ERANGE; - return -1; - } - switch(type) { - case MNL_TYPE_FLAG: - if (attr_len > 0) { - errno = ERANGE; - return -1; - } - break; - case MNL_TYPE_NUL_STRING: - if (attr_len == 0) { - errno = ERANGE; - return -1; - } - if (attr_data[attr_len-1] != '\0') { - errno = EINVAL; - return -1; - } - break; - case MNL_TYPE_STRING: - if (attr_len == 0) { - errno = ERANGE; - return -1; - } - break; - case MNL_TYPE_NESTED: + if (attr_len == 0) + break; - if (attr_len == 0) - break; + if (attr_len < MNL_ATTR_HDRLEN) + { + errno = ERANGE; + return -1; + } + break; + default: - if (attr_len < MNL_ATTR_HDRLEN) { - errno = ERANGE; - return -1; - } - break; - default: - - break; - } - if (exp_len && attr_len > exp_len) { - errno = ERANGE; - return -1; - } - return 0; + break; + } + if (exp_len && attr_len > exp_len) + { + errno = ERANGE; + return -1; + } + return 0; } static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = { - [MNL_TYPE_U8] = sizeof(uint8_t), - [MNL_TYPE_U16] = sizeof(uint16_t), - [MNL_TYPE_U32] = sizeof(uint32_t), - [MNL_TYPE_U64] = sizeof(uint64_t), - [MNL_TYPE_MSECS] = sizeof(uint64_t), + [MNL_TYPE_U8] = sizeof(uint8_t), + [MNL_TYPE_U16] = sizeof(uint16_t), + [MNL_TYPE_U32] = sizeof(uint32_t), + [MNL_TYPE_U64] = sizeof(uint64_t), + [MNL_TYPE_MSECS] = sizeof(uint64_t), }; -static int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type) +static int mnl_attr_validate(const struct nlattr* attr, enum mnl_attr_data_type type) { - int exp_len; + int exp_len; - if (type >= MNL_TYPE_MAX) { - errno = EINVAL; - return -1; - } - exp_len = mnl_attr_data_type_len[type]; - return __mnl_attr_validate(attr, type, exp_len); + if (type >= MNL_TYPE_MAX) + { + errno = EINVAL; + return -1; + } + exp_len = mnl_attr_data_type_len[type]; + return __mnl_attr_validate(attr, type, exp_len); } -static int mnl_attr_parse(const struct nlmsghdr *nlh, unsigned int offset, - mnl_attr_cb_t cb, void *data) +static int mnl_attr_parse( + const struct nlmsghdr* nlh, + unsigned int offset, + mnl_attr_cb_t cb, + void* data) { - int ret = MNL_CB_OK; - const struct nlattr *attr; + int ret = MNL_CB_OK; + const struct nlattr* attr; - mnl_attr_for_each(attr, nlh, offset) - if ((ret = cb(attr, data)) <= MNL_CB_STOP) - return ret; - return ret; + mnl_attr_for_each( + attr, nlh, offset) if ((ret = cb(attr, data)) <= MNL_CB_STOP) return ret; + return ret; } -static int mnl_attr_parse_nested(const struct nlattr *nested, mnl_attr_cb_t cb, - void *data) +static int +mnl_attr_parse_nested(const struct nlattr* nested, mnl_attr_cb_t cb, void* data) { - int ret = MNL_CB_OK; - const struct nlattr *attr; + int ret = MNL_CB_OK; + const struct nlattr* attr; - mnl_attr_for_each_nested(attr, nested) - if ((ret = cb(attr, data)) <= MNL_CB_STOP) - return ret; - return ret; + mnl_attr_for_each_nested( + attr, nested) if ((ret = cb(attr, data)) <= MNL_CB_STOP) return ret; + return ret; } -static uint8_t mnl_attr_get_u8(const struct nlattr *attr) +static uint8_t mnl_attr_get_u8(const struct nlattr* attr) { - return *((uint8_t *)mnl_attr_get_payload(attr)); + return *((uint8_t*)mnl_attr_get_payload(attr)); } -static uint16_t mnl_attr_get_u16(const struct nlattr *attr) +static uint16_t mnl_attr_get_u16(const struct nlattr* attr) { - return *((uint16_t *)mnl_attr_get_payload(attr)); + return *((uint16_t*)mnl_attr_get_payload(attr)); } -static uint32_t mnl_attr_get_u32(const struct nlattr *attr) +static uint32_t mnl_attr_get_u32(const struct nlattr* attr) { - return *((uint32_t *)mnl_attr_get_payload(attr)); + return *((uint32_t*)mnl_attr_get_payload(attr)); } -static uint64_t mnl_attr_get_u64(const struct nlattr *attr) +static uint64_t mnl_attr_get_u64(const struct nlattr* attr) { - uint64_t tmp; - memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp)); - return tmp; + uint64_t tmp; + memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp)); + return tmp; } -static const char *mnl_attr_get_str(const struct nlattr *attr) +static const char* mnl_attr_get_str(const struct nlattr* attr) { - return mnl_attr_get_payload(attr); + return mnl_attr_get_payload(attr); } -static void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type, size_t len, - const void *data) +static void +mnl_attr_put(struct nlmsghdr* nlh, uint16_t type, size_t len, const void* data) { - struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh); - uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len; - int pad; + struct nlattr* attr = mnl_nlmsg_get_payload_tail(nlh); + uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len; + int pad; - attr->nla_type = type; - attr->nla_len = payload_len; - memcpy(mnl_attr_get_payload(attr), data, len); - nlh->nlmsg_len += MNL_ALIGN(payload_len); - pad = MNL_ALIGN(len) - len; - if (pad > 0) - memset(mnl_attr_get_payload(attr) + len, 0, pad); + attr->nla_type = type; + attr->nla_len = payload_len; + memcpy(mnl_attr_get_payload(attr), data, len); + + nlh->nlmsg_len += MNL_ALIGN(payload_len); + pad = MNL_ALIGN(len) - len; + if (pad > 0) + memset(mnl_attr_get_payload(attr) + len, 0, pad); } -static void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type, uint16_t data) +static void mnl_attr_put_u16(struct nlmsghdr* nlh, uint16_t type, uint16_t data) { - mnl_attr_put(nlh, type, sizeof(uint16_t), &data); + mnl_attr_put(nlh, type, sizeof(uint16_t), &data); } -static void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type, uint32_t data) +static void mnl_attr_put_u32(struct nlmsghdr* nlh, uint16_t type, uint32_t data) { - mnl_attr_put(nlh, type, sizeof(uint32_t), &data); + mnl_attr_put(nlh, type, sizeof(uint32_t), &data); } -static void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type, const char *data) +static void mnl_attr_put_strz(struct nlmsghdr* nlh, uint16_t type, const char* data) { - mnl_attr_put(nlh, type, strlen(data)+1, data); + mnl_attr_put(nlh, type, strlen(data) + 1, data); } -static struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh, uint16_t type) +static struct nlattr* mnl_attr_nest_start(struct nlmsghdr* nlh, uint16_t type) { - struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh); + struct nlattr* start = mnl_nlmsg_get_payload_tail(nlh); - start->nla_type = NLA_F_NESTED | type; - nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr)); - return start; + start->nla_type = NLA_F_NESTED | type; + nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr)); + return start; } -static bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, size_t len, const void *data) +static bool mnl_attr_put_check( + struct nlmsghdr* nlh, + size_t buflen, + uint16_t type, + size_t len, + const void* data) { - if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen) - return false; - mnl_attr_put(nlh, type, len, data); - return true; + if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen) + return false; + mnl_attr_put(nlh, type, len, data); + return true; } -static bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, uint8_t data) +static bool +mnl_attr_put_u8_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint8_t data) { - return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data); + return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data); } -static bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, uint16_t data) +static bool +mnl_attr_put_u16_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint16_t data) { - return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data); + return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data); } -static bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type, uint32_t data) +static bool +mnl_attr_put_u32_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type, uint32_t data) { - return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data); + return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data); } -static struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh, size_t buflen, - uint16_t type) +static struct nlattr* +mnl_attr_nest_start_check(struct nlmsghdr* nlh, size_t buflen, uint16_t type) { - if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen) - return NULL; - return mnl_attr_nest_start(nlh, type); + if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen) + return NULL; + return mnl_attr_nest_start(nlh, type); } -static void mnl_attr_nest_end(struct nlmsghdr *nlh, struct nlattr *start) +static void mnl_attr_nest_end(struct nlmsghdr* nlh, struct nlattr* start) { - start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start; + start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void*)start; } -static void mnl_attr_nest_cancel(struct nlmsghdr *nlh, struct nlattr *start) +static void mnl_attr_nest_cancel(struct nlmsghdr* nlh, struct nlattr* start) { - nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start; + nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void*)start; } -static int mnl_cb_noop(__attribute__((unused)) const struct nlmsghdr *nlh, __attribute__((unused)) void *data) +static int mnl_cb_noop( + __attribute__((unused)) const struct nlmsghdr* nlh, + __attribute__((unused)) void* data) { - return MNL_CB_OK; + return MNL_CB_OK; } -static int mnl_cb_error(const struct nlmsghdr *nlh, __attribute__((unused)) void *data) +static int mnl_cb_error(const struct nlmsghdr* nlh, __attribute__((unused)) void* data) { - const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh); + const struct nlmsgerr* err = mnl_nlmsg_get_payload(nlh); - if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) { - errno = EBADMSG; - return MNL_CB_ERROR; - } + if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) + { + errno = EBADMSG; + return MNL_CB_ERROR; + } - if (err->error < 0) - errno = -err->error; - else - errno = err->error; + if (err->error < 0) + errno = -err->error; + else + errno = err->error; - return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR; + return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR; } -static int mnl_cb_stop(__attribute__((unused)) const struct nlmsghdr *nlh, __attribute__((unused)) void *data) +static int mnl_cb_stop( + __attribute__((unused)) const struct nlmsghdr* nlh, + __attribute__((unused)) void* data) { - return MNL_CB_STOP; + return MNL_CB_STOP; } static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = { - [NLMSG_NOOP] = mnl_cb_noop, - [NLMSG_ERROR] = mnl_cb_error, - [NLMSG_DONE] = mnl_cb_stop, - [NLMSG_OVERRUN] = mnl_cb_noop, + [NLMSG_NOOP] = mnl_cb_noop, + [NLMSG_ERROR] = mnl_cb_error, + [NLMSG_DONE] = mnl_cb_stop, + [NLMSG_OVERRUN] = mnl_cb_noop, }; -static int __mnl_cb_run(const void *buf, size_t numbytes, - unsigned int seq, unsigned int portid, - mnl_cb_t cb_data, void *data, - const mnl_cb_t *cb_ctl_array, - unsigned int cb_ctl_array_len) +static int __mnl_cb_run( + const void* buf, + size_t numbytes, + unsigned int seq, + unsigned int portid, + mnl_cb_t cb_data, + void* data, + const mnl_cb_t* cb_ctl_array, + unsigned int cb_ctl_array_len) { - int ret = MNL_CB_OK, len = numbytes; - const struct nlmsghdr *nlh = buf; + int ret = MNL_CB_OK, len = numbytes; + const struct nlmsghdr* nlh = buf; - while (mnl_nlmsg_ok(nlh, len)) { + while (mnl_nlmsg_ok(nlh, len)) + { - if (!mnl_nlmsg_portid_ok(nlh, portid)) { - errno = ESRCH; - return -1; - } + if (!mnl_nlmsg_portid_ok(nlh, portid)) + { + errno = ESRCH; + return -1; + } - if (!mnl_nlmsg_seq_ok(nlh, seq)) { - errno = EPROTO; - return -1; - } + if (!mnl_nlmsg_seq_ok(nlh, seq)) + { + errno = EPROTO; + return -1; + } - if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) { - errno = EINTR; - return -1; - } + if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) + { + errno = EINTR; + return -1; + } - if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) { - if (cb_data){ - ret = cb_data(nlh, data); - if (ret <= MNL_CB_STOP) - goto out; - } - } else if (nlh->nlmsg_type < cb_ctl_array_len) { - if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) { - ret = cb_ctl_array[nlh->nlmsg_type](nlh, data); - if (ret <= MNL_CB_STOP) - goto out; - } - } else if (default_cb_array[nlh->nlmsg_type]) { - ret = default_cb_array[nlh->nlmsg_type](nlh, data); - if (ret <= MNL_CB_STOP) - goto out; - } - nlh = mnl_nlmsg_next(nlh, &len); - } + if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) + { + if (cb_data) + { + ret = cb_data(nlh, data); + if (ret <= MNL_CB_STOP) + goto out; + } + } + else if (nlh->nlmsg_type < cb_ctl_array_len) + { + if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) + { + ret = cb_ctl_array[nlh->nlmsg_type](nlh, data); + if (ret <= MNL_CB_STOP) + goto out; + } + } + else if (default_cb_array[nlh->nlmsg_type]) + { + ret = default_cb_array[nlh->nlmsg_type](nlh, data); + if (ret <= MNL_CB_STOP) + goto out; + } + nlh = mnl_nlmsg_next(nlh, &len); + } out: - return ret; + return ret; } -static int mnl_cb_run2(const void *buf, size_t numbytes, unsigned int seq, - unsigned int portid, mnl_cb_t cb_data, void *data, - const mnl_cb_t *cb_ctl_array, unsigned int cb_ctl_array_len) +static int mnl_cb_run2( + const void* buf, + size_t numbytes, + unsigned int seq, + unsigned int portid, + mnl_cb_t cb_data, + void* data, + const mnl_cb_t* cb_ctl_array, + unsigned int cb_ctl_array_len) { - return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, - cb_ctl_array, cb_ctl_array_len); + return __mnl_cb_run( + buf, numbytes, seq, portid, cb_data, data, cb_ctl_array, cb_ctl_array_len); } -static int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq, - unsigned int portid, mnl_cb_t cb_data, void *data) +static int mnl_cb_run( + const void* buf, + size_t numbytes, + unsigned int seq, + unsigned int portid, + mnl_cb_t cb_data, + void* data) { - return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0); + return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0); } -struct mnl_socket { - int fd; - struct sockaddr_nl addr; +struct mnl_socket +{ + int fd; + struct sockaddr_nl addr; }; -static unsigned int mnl_socket_get_portid(const struct mnl_socket *nl) +static unsigned int mnl_socket_get_portid(const struct mnl_socket* nl) { - return nl->addr.nl_pid; + return nl->addr.nl_pid; } -static struct mnl_socket *__mnl_socket_open(int bus, int flags) +static struct mnl_socket* __mnl_socket_open(int bus, int flags) { - struct mnl_socket *nl; + struct mnl_socket* nl; - nl = calloc(1, sizeof(struct mnl_socket)); - if (nl == NULL) - return NULL; + nl = calloc(1, sizeof(struct mnl_socket)); + if (nl == NULL) + return NULL; - nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus); - if (nl->fd == -1) { - free(nl); - return NULL; - } + nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus); + if (nl->fd == -1) + { + free(nl); + return NULL; + } - return nl; + return nl; } -static struct mnl_socket *mnl_socket_open(int bus) +static struct mnl_socket* mnl_socket_open(int bus) { return __mnl_socket_open(bus, 0); } + +static int mnl_socket_bind(struct mnl_socket* nl, unsigned int groups, pid_t pid) { - return __mnl_socket_open(bus, 0); + int ret; + socklen_t addr_len; + + nl->addr.nl_family = AF_NETLINK; + nl->addr.nl_groups = groups; + nl->addr.nl_pid = pid; + + ret = bind(nl->fd, (struct sockaddr*)&nl->addr, sizeof(nl->addr)); + if (ret < 0) + return ret; + + addr_len = sizeof(nl->addr); + ret = getsockname(nl->fd, (struct sockaddr*)&nl->addr, &addr_len); + if (ret < 0) + return ret; + + if (addr_len != sizeof(nl->addr)) + { + errno = EINVAL; + return -1; + } + if (nl->addr.nl_family != AF_NETLINK) + { + errno = EINVAL; + return -1; + } + return 0; } -static int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid) +static ssize_t mnl_socket_sendto(const struct mnl_socket* nl, const void* buf, size_t len) { - int ret; - socklen_t addr_len; - - nl->addr.nl_family = AF_NETLINK; - nl->addr.nl_groups = groups; - nl->addr.nl_pid = pid; - - ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr)); - if (ret < 0) - return ret; - - addr_len = sizeof(nl->addr); - ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len); - if (ret < 0) - return ret; - - if (addr_len != sizeof(nl->addr)) { - errno = EINVAL; - return -1; - } - if (nl->addr.nl_family != AF_NETLINK) { - errno = EINVAL; - return -1; - } - return 0; + static const struct sockaddr_nl snl = {.nl_family = AF_NETLINK}; + return sendto(nl->fd, buf, len, 0, (struct sockaddr*)&snl, sizeof(snl)); } -static ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *buf, - size_t len) +static ssize_t mnl_socket_recvfrom(const struct mnl_socket* nl, void* buf, size_t bufsiz) { - static const struct sockaddr_nl snl = { - .nl_family = AF_NETLINK - }; - return sendto(nl->fd, buf, len, 0, - (struct sockaddr *) &snl, sizeof(snl)); + ssize_t ret; + struct sockaddr_nl addr; + struct iovec iov = { + .iov_base = buf, + .iov_len = bufsiz, + }; + struct msghdr msg = { + .msg_name = &addr, + .msg_namelen = sizeof(struct sockaddr_nl), + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = NULL, + .msg_controllen = 0, + .msg_flags = 0, + }; + ret = recvmsg(nl->fd, &msg, 0); + if (ret == -1) + return ret; + + if (msg.msg_flags & MSG_TRUNC) + { + errno = ENOSPC; + return -1; + } + if (msg.msg_namelen != sizeof(struct sockaddr_nl)) + { + errno = EINVAL; + return -1; + } + return ret; } -static ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, - size_t bufsiz) +static int mnl_socket_close(struct mnl_socket* nl) { - ssize_t ret; - struct sockaddr_nl addr; - struct iovec iov = { - .iov_base = buf, - .iov_len = bufsiz, - }; - struct msghdr msg = { - .msg_name = &addr, - .msg_namelen = sizeof(struct sockaddr_nl), - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = NULL, - .msg_controllen = 0, - .msg_flags = 0, - }; - ret = recvmsg(nl->fd, &msg, 0); - if (ret == -1) - return ret; - - if (msg.msg_flags & MSG_TRUNC) { - errno = ENOSPC; - return -1; - } - if (msg.msg_namelen != sizeof(struct sockaddr_nl)) { - errno = EINVAL; - return -1; - } - return ret; -} - -static int mnl_socket_close(struct mnl_socket *nl) -{ - int ret = close(nl->fd); - free(nl); - return ret; + int ret = close(nl->fd); + free(nl); + return ret; } /* This is a wrapper for generic netlink, originally from Jiri Pirko : */ -struct mnlg_socket { - struct mnl_socket *nl; - char *buf; - uint16_t id; - uint8_t version; - unsigned int seq; - unsigned int portid; +struct mnlg_socket +{ + struct mnl_socket* nl; + char* buf; + uint16_t id; + uint8_t version; + unsigned int seq; + unsigned int portid; }; -static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd, - uint16_t flags, uint16_t id, - uint8_t version) +static struct nlmsghdr* __mnlg_msg_prepare( + struct mnlg_socket* nlg, + uint8_t cmd, + uint16_t flags, + uint16_t id, + uint8_t version) { - struct nlmsghdr *nlh; - struct genlmsghdr *genl; + struct nlmsghdr* nlh; + struct genlmsghdr* genl; - nlh = mnl_nlmsg_put_header(nlg->buf); - nlh->nlmsg_type = id; - nlh->nlmsg_flags = flags; - nlg->seq = time(NULL); - nlh->nlmsg_seq = nlg->seq; + nlh = mnl_nlmsg_put_header(nlg->buf); + nlh->nlmsg_type = id; + nlh->nlmsg_flags = flags; + nlg->seq = time(NULL); + nlh->nlmsg_seq = nlg->seq; - genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); - genl->cmd = cmd; - genl->version = version; + genl = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); + genl->cmd = cmd; + genl->version = version; - return nlh; + return nlh; } -static struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd, - uint16_t flags) +static struct nlmsghdr* +mnlg_msg_prepare(struct mnlg_socket* nlg, uint8_t cmd, uint16_t flags) { - return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version); + return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version); } -static int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh) +static int mnlg_socket_send(struct mnlg_socket* nlg, const struct nlmsghdr* nlh) { - return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len); + return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len); } -static int mnlg_cb_noop(const struct nlmsghdr *nlh, void *data) +static int mnlg_cb_noop(const struct nlmsghdr* nlh, void* data) { - (void)nlh; - (void)data; - return MNL_CB_OK; + (void)nlh; + (void)data; + return MNL_CB_OK; } -static int mnlg_cb_error(const struct nlmsghdr *nlh, void *data) +static int mnlg_cb_error(const struct nlmsghdr* nlh, void* data) { - const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh); - (void)data; + const struct nlmsgerr* err = mnl_nlmsg_get_payload(nlh); + (void)data; - if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) { - errno = EBADMSG; - return MNL_CB_ERROR; - } - /* Netlink subsystems returns the errno value with different signess */ - if (err->error < 0) - errno = -err->error; - else - errno = err->error; + if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) + { + errno = EBADMSG; + return MNL_CB_ERROR; + } + /* Netlink subsystems returns the errno value with different signess */ + if (err->error < 0) + errno = -err->error; + else + errno = err->error; - return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR; + return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR; } -static int mnlg_cb_stop(const struct nlmsghdr *nlh, void *data) +static int mnlg_cb_stop(const struct nlmsghdr* nlh, void* data) { - (void)data; - if (nlh->nlmsg_flags & NLM_F_MULTI && nlh->nlmsg_len == mnl_nlmsg_size(sizeof(int))) { - int error = *(int *)mnl_nlmsg_get_payload(nlh); - /* Netlink subsystems returns the errno value with different signess */ - if (error < 0) - errno = -error; - else - errno = error; + (void)data; + if (nlh->nlmsg_flags & NLM_F_MULTI && nlh->nlmsg_len == mnl_nlmsg_size(sizeof(int))) + { + int error = *(int*)mnl_nlmsg_get_payload(nlh); + /* Netlink subsystems returns the errno value with different signess */ + if (error < 0) + errno = -error; + else + errno = error; - return error == 0 ? MNL_CB_STOP : MNL_CB_ERROR; - } - return MNL_CB_STOP; + return error == 0 ? MNL_CB_STOP : MNL_CB_ERROR; + } + return MNL_CB_STOP; } static const mnl_cb_t mnlg_cb_array[] = { - [NLMSG_NOOP] = mnlg_cb_noop, - [NLMSG_ERROR] = mnlg_cb_error, - [NLMSG_DONE] = mnlg_cb_stop, - [NLMSG_OVERRUN] = mnlg_cb_noop, + [NLMSG_NOOP] = mnlg_cb_noop, + [NLMSG_ERROR] = mnlg_cb_error, + [NLMSG_DONE] = mnlg_cb_stop, + [NLMSG_OVERRUN] = mnlg_cb_noop, }; -static int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data) +static int mnlg_socket_recv_run(struct mnlg_socket* nlg, mnl_cb_t data_cb, void* data) { - int err; + int err; - do { - err = mnl_socket_recvfrom(nlg->nl, nlg->buf, - mnl_ideal_socket_buffer_size()); - if (err <= 0) - break; - err = mnl_cb_run2(nlg->buf, err, nlg->seq, nlg->portid, - data_cb, data, mnlg_cb_array, MNL_ARRAY_SIZE(mnlg_cb_array)); - } while (err > 0); + do + { + err = mnl_socket_recvfrom(nlg->nl, nlg->buf, mnl_ideal_socket_buffer_size()); + if (err <= 0) + break; + err = mnl_cb_run2( + nlg->buf, + err, + nlg->seq, + nlg->portid, + data_cb, + data, + mnlg_cb_array, + MNL_ARRAY_SIZE(mnlg_cb_array)); + } while (err > 0); - return err; + return err; } -static int get_family_id_attr_cb(const struct nlattr *attr, void *data) +static int get_family_id_attr_cb(const struct nlattr* attr, void* data) { - const struct nlattr **tb = data; - int type = mnl_attr_get_type(attr); + const struct nlattr** tb = data; + int type = mnl_attr_get_type(attr); - if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0) - return MNL_CB_ERROR; + if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0) + return MNL_CB_ERROR; - if (type == CTRL_ATTR_FAMILY_ID && - mnl_attr_validate(attr, MNL_TYPE_U16) < 0) - return MNL_CB_ERROR; - tb[type] = attr; - return MNL_CB_OK; + if (type == CTRL_ATTR_FAMILY_ID && mnl_attr_validate(attr, MNL_TYPE_U16) < 0) + return MNL_CB_ERROR; + tb[type] = attr; + return MNL_CB_OK; } -static int get_family_id_cb(const struct nlmsghdr *nlh, void *data) +static int get_family_id_cb(const struct nlmsghdr* nlh, void* data) { - uint16_t *p_id = data; - struct nlattr *tb[CTRL_ATTR_MAX + 1] = { 0 }; + uint16_t* p_id = data; + struct nlattr* tb[CTRL_ATTR_MAX + 1] = {0}; - mnl_attr_parse(nlh, sizeof(struct genlmsghdr), get_family_id_attr_cb, tb); - if (!tb[CTRL_ATTR_FAMILY_ID]) - return MNL_CB_ERROR; - *p_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]); - return MNL_CB_OK; + mnl_attr_parse(nlh, sizeof(struct genlmsghdr), get_family_id_attr_cb, tb); + if (!tb[CTRL_ATTR_FAMILY_ID]) + return MNL_CB_ERROR; + *p_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]); + return MNL_CB_OK; } -static struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version) +static struct mnlg_socket* mnlg_socket_open(const char* family_name, uint8_t version) { - struct mnlg_socket *nlg; - struct nlmsghdr *nlh; - int err; + struct mnlg_socket* nlg; + struct nlmsghdr* nlh; + int err; - nlg = malloc(sizeof(*nlg)); - if (!nlg) - return NULL; - nlg->id = 0; + nlg = malloc(sizeof(*nlg)); + if (!nlg) + return NULL; + nlg->id = 0; - err = -ENOMEM; - nlg->buf = malloc(mnl_ideal_socket_buffer_size()); - if (!nlg->buf) - goto err_buf_alloc; + err = -ENOMEM; + nlg->buf = malloc(mnl_ideal_socket_buffer_size()); + if (!nlg->buf) + goto err_buf_alloc; - nlg->nl = mnl_socket_open(NETLINK_GENERIC); - if (!nlg->nl) { - err = -errno; - goto err_mnl_socket_open; - } + nlg->nl = mnl_socket_open(NETLINK_GENERIC); + if (!nlg->nl) + { + err = -errno; + goto err_mnl_socket_open; + } - if (mnl_socket_bind(nlg->nl, 0, MNL_SOCKET_AUTOPID) < 0) { - err = -errno; - goto err_mnl_socket_bind; - } + if (mnl_socket_bind(nlg->nl, 0, MNL_SOCKET_AUTOPID) < 0) + { + err = -errno; + goto err_mnl_socket_bind; + } - nlg->portid = mnl_socket_get_portid(nlg->nl); + nlg->portid = mnl_socket_get_portid(nlg->nl); - nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY, - NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1); - mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, family_name); + nlh = __mnlg_msg_prepare( + nlg, CTRL_CMD_GETFAMILY, NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1); + mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, family_name); - if (mnlg_socket_send(nlg, nlh) < 0) { - err = -errno; - goto err_mnlg_socket_send; - } + if (mnlg_socket_send(nlg, nlh) < 0) + { + err = -errno; + goto err_mnlg_socket_send; + } - errno = 0; - if (mnlg_socket_recv_run(nlg, get_family_id_cb, &nlg->id) < 0) { - errno = errno == ENOENT ? EPROTONOSUPPORT : errno; - err = errno ? -errno : -ENOSYS; - goto err_mnlg_socket_recv_run; - } + errno = 0; + if (mnlg_socket_recv_run(nlg, get_family_id_cb, &nlg->id) < 0) + { + errno = errno == ENOENT ? EPROTONOSUPPORT : errno; + err = errno ? -errno : -ENOSYS; + goto err_mnlg_socket_recv_run; + } - nlg->version = version; - errno = 0; - return nlg; + nlg->version = version; + errno = 0; + return nlg; err_mnlg_socket_recv_run: err_mnlg_socket_send: err_mnl_socket_bind: - mnl_socket_close(nlg->nl); + mnl_socket_close(nlg->nl); err_mnl_socket_open: - free(nlg->buf); + free(nlg->buf); err_buf_alloc: - free(nlg); - errno = -err; - return NULL; + free(nlg); + errno = -err; + return NULL; } -static void mnlg_socket_close(struct mnlg_socket *nlg) +static void mnlg_socket_close(struct mnlg_socket* nlg) { - mnl_socket_close(nlg->nl); - free(nlg->buf); - free(nlg); + mnl_socket_close(nlg->nl); + free(nlg->buf); + free(nlg); } diff --git a/src/showconf.c b/src/showconf.c index 0f9622c..5aba185 100644 --- a/src/showconf.c +++ b/src/showconf.c @@ -94,6 +94,9 @@ int showconf_main(int argc, const char *argv[]) if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) { printf("AdvancedSecurity = %s\n", peer->advanced_security ? "on" : "off"); } + if (peer->flags & WGPEER_HAS_SPECIAL_HANDSHAKE) { + printf("SpecialHandshake = %s\n", peer->special_handshake ? "on" : "off"); + } if (peer->first_allowedip) printf("AllowedIPs = "); for_each_wgallowedip(peer, allowedip) { diff --git a/src/uapi/linux/linux/wireguard.h b/src/uapi/linux/linux/wireguard.h index c4849bb..cca01ab 100644 --- a/src/uapi/linux/linux/wireguard.h +++ b/src/uapi/linux/linux/wireguard.h @@ -114,6 +114,9 @@ * WGPEER_A_ADVANCED_SECURITY: flag indicating that advanced security * techniques provided by AmneziaWG should * be used. + * WGPEER_A_SPECIAL_HANDSHAKE: flag indicating that special handshake + * techniques provided by AmneziaWG should + * be used. * 0: NLA_NESTED * ... * ... @@ -147,6 +150,9 @@ * WGPEER_A_ADVANCED_SECURITY: flag indicating that advanced security * techniques provided by AmneziaWG should * be used. + * WGPEER_A_SPECIAL_HANDSHAKE: flag indicating that special handshake + * techniques provided by AmneziaWG should + * be used. * */ @@ -210,6 +216,7 @@ enum wgpeer_flag { WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1, WGPEER_F_UPDATE_ONLY = 1U << 2, WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3, + WGPEER_F_HAS_SPECIAL_HANDSHAKE = 1U << 4, __WGPEER_F_ALL = WGPEER_F_REMOVE_ME | WGPEER_F_REPLACE_ALLOWEDIPS | WGPEER_F_UPDATE_ONLY }; @@ -226,6 +233,7 @@ enum wgpeer_attribute { WGPEER_A_ALLOWEDIPS, WGPEER_A_PROTOCOL_VERSION, WGPEER_A_ADVANCED_SECURITY, + WGPEER_A_SPECIAL_HANDSHAKE, __WGPEER_A_LAST }; #define WGPEER_A_MAX (__WGPEER_A_LAST - 1) diff --git a/src/uapi/openbsd/net/if_wg.h b/src/uapi/openbsd/net/if_wg.h index f768a32..9bc3b91 100644 --- a/src/uapi/openbsd/net/if_wg.h +++ b/src/uapi/openbsd/net/if_wg.h @@ -7,13 +7,12 @@ #ifndef __IF_WG_H__ #define __IF_WG_H__ -#include #include +#include #include #include - /* * This is the public interface to the WireGuard network interface. * @@ -25,87 +24,112 @@ #define SIOCSWG _IOWR('i', 210, struct wg_data_io) #define SIOCGWG _IOWR('i', 211, struct wg_data_io) -#define a_ipv4 a_addr.addr_ipv4 -#define a_ipv6 a_addr.addr_ipv6 +#define a_ipv4 a_addr.addr_ipv4 +#define a_ipv6 a_addr.addr_ipv6 -struct wg_aip_io { - sa_family_t a_af; - int a_cidr; - union wg_aip_addr { - struct in_addr addr_ipv4; - struct in6_addr addr_ipv6; - } a_addr; +struct wg_aip_io +{ + sa_family_t a_af; + int a_cidr; + union wg_aip_addr + { + struct in_addr addr_ipv4; + struct in6_addr addr_ipv6; + } a_addr; }; -#define WG_PEER_HAS_PUBLIC (1 << 0) -#define WG_PEER_HAS_PSK (1 << 1) -#define WG_PEER_HAS_PKA (1 << 2) -#define WG_PEER_HAS_ENDPOINT (1 << 3) -#define WG_PEER_REPLACE_AIPS (1 << 4) -#define WG_PEER_REMOVE (1 << 5) -#define WG_PEER_UPDATE (1 << 6) +#define WG_PEER_HAS_PUBLIC (1 << 0) +#define WG_PEER_HAS_PSK (1 << 1) +#define WG_PEER_HAS_PKA (1 << 2) +#define WG_PEER_HAS_ENDPOINT (1 << 3) +#define WG_PEER_REPLACE_AIPS (1 << 4) +#define WG_PEER_REMOVE (1 << 5) +#define WG_PEER_UPDATE (1 << 6) -#define p_sa p_endpoint.sa_sa -#define p_sin p_endpoint.sa_sin -#define p_sin6 p_endpoint.sa_sin6 +#define p_sa p_endpoint.sa_sa +#define p_sin p_endpoint.sa_sin +#define p_sin6 p_endpoint.sa_sin6 -struct wg_peer_io { - int p_flags; - int p_protocol_version; - uint8_t p_public[WG_KEY_LEN]; - uint8_t p_psk[WG_KEY_LEN]; - uint16_t p_pka; - union wg_peer_endpoint { - struct sockaddr sa_sa; - struct sockaddr_in sa_sin; - struct sockaddr_in6 sa_sin6; - } p_endpoint; - uint64_t p_txbytes; - uint64_t p_rxbytes; - struct timespec p_last_handshake; /* nanotime */ - size_t p_aips_count; - struct wg_aip_io p_aips[]; +struct wg_peer_io +{ + int p_flags; + int p_protocol_version; + uint8_t p_public[WG_KEY_LEN]; + uint8_t p_psk[WG_KEY_LEN]; + uint16_t p_pka; + union wg_peer_endpoint + { + struct sockaddr sa_sa; + struct sockaddr_in sa_sin; + struct sockaddr_in6 sa_sin6; + } p_endpoint; + uint64_t p_txbytes; + uint64_t p_rxbytes; + struct timespec p_last_handshake; /* nanotime */ + size_t p_aips_count; + struct wg_aip_io p_aips[]; }; -#define WG_INTERFACE_HAS_PUBLIC (1 << 0) -#define WG_INTERFACE_HAS_PRIVATE (1 << 1) -#define WG_INTERFACE_HAS_PORT (1 << 2) -#define WG_INTERFACE_HAS_RTABLE (1 << 3) -#define WG_INTERFACE_REPLACE_PEERS (1 << 4) -#define WG_INTERFACE_DEVICE_HAS_JC (1 << 5) +#define WG_INTERFACE_HAS_PUBLIC (1 << 0) +#define WG_INTERFACE_HAS_PRIVATE (1 << 1) +#define WG_INTERFACE_HAS_PORT (1 << 2) +#define WG_INTERFACE_HAS_RTABLE (1 << 3) +#define WG_INTERFACE_REPLACE_PEERS (1 << 4) +#define WG_INTERFACE_DEVICE_HAS_JC (1 << 5) #define WG_INTERFACE_DEVICE_HAS_JMIN (1 << 6) #define WG_INTERFACE_DEVICE_HAS_JMAX (1 << 7) -#define WG_INTERFACE_DEVICE_HAS_S1 (1 << 8) -#define WG_INTERFACE_DEVICE_HAS_S2 (1 << 9) -#define WG_INTERFACE_DEVICE_HAS_H1 (1 << 10) -#define WG_INTERFACE_DEVICE_HAS_H2 (1 << 11) -#define WG_INTERFACE_DEVICE_HAS_H3 (1 << 12) -#define WG_INTERFACE_DEVICE_HAS_H4 (1 << 13) +#define WG_INTERFACE_DEVICE_HAS_S1 (1 << 8) +#define WG_INTERFACE_DEVICE_HAS_S2 (1 << 9) +#define WG_INTERFACE_DEVICE_HAS_H1 (1 << 10) +#define WG_INTERFACE_DEVICE_HAS_H2 (1 << 11) +#define WG_INTERFACE_DEVICE_HAS_H3 (1 << 12) +#define WG_INTERFACE_DEVICE_HAS_H4 (1 << 13) +#define WG_INTERFACE_DEVICE_HAS_I1 (1 << 14) +#define WG_INTERFACE_DEVICE_HAS_I2 (1 << 15) +#define WG_INTERFACE_DEVICE_HAS_I3 (1 << 16) +#define WG_INTERFACE_DEVICE_HAS_I4 (1 << 17) +#define WG_INTERFACE_DEVICE_HAS_I5 (1 << 18) +#define WG_INTERFACE_DEVICE_HAS_J1 (1 << 19) +#define WG_INTERFACE_DEVICE_HAS_J2 (1 << 20) +#define WG_INTERFACE_DEVICE_HAS_J3 (1 << 21) +#define WG_INTERFACE_DEVICE_HAS_ITIME (1 << 22) -struct wg_interface_io { - uint16_t i_flags; - in_port_t i_port; - int i_rtable; - uint8_t i_public[WG_KEY_LEN]; - uint8_t i_private[WG_KEY_LEN]; - size_t i_peers_count; - struct wg_peer_io i_peers[]; +struct wg_interface_io +{ + uint16_t i_flags; + in_port_t i_port; + int i_rtable; + uint8_t i_public[WG_KEY_LEN]; + uint8_t i_private[WG_KEY_LEN]; + size_t i_peers_count; + struct wg_peer_io i_peers[]; - uint16_t i_junk_packet_count; - uint16_t i_junk_packet_min_size; - uint16_t i_junk_packet_max_size; - uint16_t i_init_packet_junk_size; - uint16_t i_response_packet_junk_size; - uint32_t i_init_packet_magic_header; - uint32_t i_response_packet_magic_header; - uint32_t i_underload_packet_magic_header; - uint32_t i_transport_packet_magic_header; + uint16_t i_junk_packet_count; + uint16_t i_junk_packet_min_size; + uint16_t i_junk_packet_max_size; + uint16_t i_init_packet_junk_size; + uint16_t i_response_packet_junk_size; + uint32_t i_init_packet_magic_header; + uint32_t i_response_packet_magic_header; + uint32_t i_underload_packet_magic_header; + uint32_t i_transport_packet_magic_header; + + uint8_t* i_i1; + uint8_t* i_i2; + uint8_t* i_i3; + uint8_t* i_i4; + uint8_t* i_i5; + uint8_t* i_j1; + uint8_t* i_j2; + uint8_t* i_j3; + uint32_t i_itime; }; -struct wg_data_io { - char wgd_name[IFNAMSIZ]; - size_t wgd_size; /* total size of the memory pointed to by wgd_interface */ - struct wg_interface_io *wgd_interface; +struct wg_data_io +{ + char wgd_name[IFNAMSIZ]; + size_t wgd_size; /* total size of the memory pointed to by wgd_interface */ + struct wg_interface_io* wgd_interface; }; #endif /* __IF_WG_H__ */ diff --git a/src/uapi/windows/wireguard.h b/src/uapi/windows/wireguard.h index 917d785..1b99427 100644 --- a/src/uapi/windows/wireguard.h +++ b/src/uapi/windows/wireguard.h @@ -6,94 +6,113 @@ #ifndef _WIREGUARD_NT_H #define _WIREGUARD_NT_H +#include +#include #include #include #include -#include -#include #define WG_KEY_LEN 32 typedef struct _WG_IOCTL_ALLOWED_IP { - union - { - IN_ADDR V4; - IN6_ADDR V6; - } Address; - ADDRESS_FAMILY AddressFamily; - UCHAR Cidr; + union + { + IN_ADDR V4; + IN6_ADDR V6; + } Address; + ADDRESS_FAMILY AddressFamily; + UCHAR Cidr; } __attribute__((aligned(8))) WG_IOCTL_ALLOWED_IP; typedef enum { - WG_IOCTL_PEER_HAS_PUBLIC_KEY = 1 << 0, - WG_IOCTL_PEER_HAS_PRESHARED_KEY = 1 << 1, - WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2, - WG_IOCTL_PEER_HAS_ENDPOINT = 1 << 3, - WG_IOCTL_PEER_HAS_PROTOCOL_VERSION = 1 << 4, - WG_IOCTL_PEER_REPLACE_ALLOWED_IPS = 1 << 5, - WG_IOCTL_PEER_REMOVE = 1 << 6, - WG_IOCTL_PEER_UPDATE = 1 << 7 + WG_IOCTL_PEER_HAS_PUBLIC_KEY = 1 << 0, + WG_IOCTL_PEER_HAS_PRESHARED_KEY = 1 << 1, + WG_IOCTL_PEER_HAS_PERSISTENT_KEEPALIVE = 1 << 2, + WG_IOCTL_PEER_HAS_ENDPOINT = 1 << 3, + WG_IOCTL_PEER_HAS_PROTOCOL_VERSION = 1 << 4, + WG_IOCTL_PEER_REPLACE_ALLOWED_IPS = 1 << 5, + WG_IOCTL_PEER_REMOVE = 1 << 6, + WG_IOCTL_PEER_UPDATE = 1 << 7 } WG_IOCTL_PEER_FLAG; typedef struct _WG_IOCTL_PEER { - WG_IOCTL_PEER_FLAG Flags; - ULONG ProtocolVersion; /* 0 = latest protocol, 1 = this protocol. */ - UCHAR PublicKey[WG_KEY_LEN]; - UCHAR PresharedKey[WG_KEY_LEN]; - USHORT PersistentKeepalive; - SOCKADDR_INET Endpoint; - ULONG64 TxBytes; - ULONG64 RxBytes; - ULONG64 LastHandshake; - ULONG AllowedIPsCount; + WG_IOCTL_PEER_FLAG Flags; + ULONG ProtocolVersion; /* 0 = latest protocol, 1 = this protocol. */ + UCHAR PublicKey[WG_KEY_LEN]; + UCHAR PresharedKey[WG_KEY_LEN]; + USHORT PersistentKeepalive; + SOCKADDR_INET Endpoint; + ULONG64 TxBytes; + ULONG64 RxBytes; + ULONG64 LastHandshake; + ULONG AllowedIPsCount; } __attribute__((aligned(8))) WG_IOCTL_PEER; typedef enum { - WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY = 1 << 0, - WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY = 1 << 1, - WG_IOCTL_INTERFACE_HAS_LISTEN_PORT = 1 << 2, - WG_IOCTL_INTERFACE_REPLACE_PEERS = 1 << 3, - WG_IOCTL_INTERFACE_PEERS = 1 << 4, - WG_IOCTL_INTERFACE_JC = 1 << 5, - WG_IOCTL_INTERFACE_JMIN = 1 << 6, - WG_IOCTL_INTERFACE_JMAX = 1 << 7, - WG_IOCTL_INTERFACE_S1 = 1 << 8, - WG_IOCTL_INTERFACE_S2 = 1 << 9, - WG_IOCTL_INTERFACE_H1 = 1 << 10, - WG_IOCTL_INTERFACE_H2 = 1 << 11, - WG_IOCTL_INTERFACE_H3 = 1 << 12, - WG_IOCTL_INTERFACE_H4 = 1 << 13 + WG_IOCTL_INTERFACE_HAS_PUBLIC_KEY = 1 << 0, + WG_IOCTL_INTERFACE_HAS_PRIVATE_KEY = 1 << 1, + WG_IOCTL_INTERFACE_HAS_LISTEN_PORT = 1 << 2, + WG_IOCTL_INTERFACE_REPLACE_PEERS = 1 << 3, + WG_IOCTL_INTERFACE_PEERS = 1 << 4, + WG_IOCTL_INTERFACE_JC = 1 << 5, + WG_IOCTL_INTERFACE_JMIN = 1 << 6, + WG_IOCTL_INTERFACE_JMAX = 1 << 7, + WG_IOCTL_INTERFACE_S1 = 1 << 8, + WG_IOCTL_INTERFACE_S2 = 1 << 9, + WG_IOCTL_INTERFACE_H1 = 1 << 10, + WG_IOCTL_INTERFACE_H2 = 1 << 11, + WG_IOCTL_INTERFACE_H3 = 1 << 12, + WG_IOCTL_INTERFACE_H4 = 1 << 13, + WG_IOCTL_INTERFACE_I1 = 1U << 14, + WG_IOCTL_INTERFACE_I2 = 1U << 15, + WG_IOCTL_INTERFACE_I3 = 1U << 16, + WG_IOCTL_INTERFACE_I4 = 1U << 17, + WG_IOCTL_INTERFACE_I5 = 1U << 18, + WG_IOCTL_INTERFACE_J1 = 1U << 19, + WG_IOCTL_INTERFACE_J2 = 1U << 20, + WG_IOCTL_INTERFACE_J3 = 1U << 21, + WG_IOCTL_INTERFACE_ITIME = 1U << 22 } WG_IOCTL_INTERFACE_FLAG; typedef struct _WG_IOCTL_INTERFACE { - WG_IOCTL_INTERFACE_FLAG Flags; - USHORT ListenPort; - UCHAR PrivateKey[WG_KEY_LEN]; - UCHAR PublicKey[WG_KEY_LEN]; - ULONG PeersCount; - USHORT JunkPacketCount; - USHORT JunkPacketMinSize; - USHORT JunkPacketMaxSize; - USHORT InitPacketJunkSize; - USHORT ResponsePacketJunkSize; - ULONG InitPacketMagicHeader; - ULONG ResponsePacketMagicHeader; - ULONG UnderloadPacketMagicHeader; - ULONG TransportPacketMagicHeader; + WG_IOCTL_INTERFACE_FLAG Flags; + USHORT ListenPort; + UCHAR PrivateKey[WG_KEY_LEN]; + UCHAR PublicKey[WG_KEY_LEN]; + ULONG PeersCount; + USHORT JunkPacketCount; + USHORT JunkPacketMinSize; + USHORT JunkPacketMaxSize; + USHORT InitPacketJunkSize; + USHORT ResponsePacketJunkSize; + ULONG InitPacketMagicHeader; + ULONG ResponsePacketMagicHeader; + ULONG UnderloadPacketMagicHeader; + ULONG TransportPacketMagicHeader; + UCHAR* I1; + UCHAR* I2; + UCHAR* I3; + UCHAR* I4; + UCHAR* I5; + UCHAR* J1; + UCHAR* J2; + UCHAR* J3; + ULONG Itime; } __attribute__((aligned(8))) WG_IOCTL_INTERFACE; -#define WG_IOCTL_GET CTL_CODE(45208U, 321, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) -#define WG_IOCTL_SET CTL_CODE(45208U, 322, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) - -#define DEVPKEY_WG_NAME (DEVPROPKEY) { \ - { 0x65726957, 0x7547, 0x7261, { 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79 } }, \ - DEVPROPID_FIRST_USABLE + 1 \ - } +#define WG_IOCTL_GET \ + CTL_CODE(45208U, 321, METHOD_OUT_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) +#define WG_IOCTL_SET \ + CTL_CODE(45208U, 322, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA) +#define DEVPKEY_WG_NAME \ + (DEVPROPKEY){ \ + {0x65726957, 0x7547, 0x7261, {0x64, 0x4e, 0x61, 0x6d, 0x65, 0x4b, 0x65, 0x79}}, \ + DEVPROPID_FIRST_USABLE + 1} #endif