You can subscribe to this list here.
| 2002 | Jan | Feb | Mar | Apr (24) | May (14) | Jun (29) | Jul (33) | Aug (3) | Sep (8) | Oct (18) | Nov (1) | Dec (10) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 | Jan (3) | Feb (33) | Mar (7) | Apr (28) | May (30) | Jun (5) | Jul (10) | Aug (7) | Sep (32) | Oct (41) | Nov (20) | Dec (10) |
| 2004 | Jan (24) | Feb (18) | Mar (57) | Apr (40) | May (55) | Jun (48) | Jul (77) | Aug (15) | Sep (56) | Oct (80) | Nov (74) | Dec (52) |
| 2005 | Jan (38) | Feb (42) | Mar (39) | Apr (56) | May (79) | Jun (73) | Jul (16) | Aug (23) | Sep (68) | Oct (77) | Nov (52) | Dec (27) |
| 2006 | Jan (27) | Feb (18) | Mar (51) | Apr (62) | May (28) | Jun (50) | Jul (36) | Aug (33) | Sep (47) | Oct (50) | Nov (77) | Dec (13) |
| 2007 | Jan (15) | Feb (8) | Mar (14) | Apr (18) | May (25) | Jun (16) | Jul (16) | Aug (19) | Sep (32) | Oct (17) | Nov (5) | Dec (5) |
| 2008 | Jan (64) | Feb (25) | Mar (25) | Apr (6) | May (28) | Jun (20) | Jul (10) | Aug (27) | Sep (28) | Oct (59) | Nov (37) | Dec (43) |
| 2009 | Jan (40) | Feb (25) | Mar (12) | Apr (57) | May (46) | Jun (29) | Jul (39) | Aug (10) | Sep (20) | Oct (42) | Nov (50) | Dec (57) |
| 2010 | Jan (82) | Feb (165) | Mar (256) | Apr (260) | May (36) | Jun (87) | Jul (53) | Aug (89) | Sep (107) | Oct (51) | Nov (88) | Dec (117) |
| 2011 | Jan (69) | Feb (60) | Mar (113) | Apr (71) | May (67) | Jun (90) | Jul (88) | Aug (90) | Sep (48) | Oct (64) | Nov (69) | Dec (118) |
| 2012 | Jan (49) | Feb (528) | Mar (351) | Apr (190) | May (238) | Jun (193) | Jul (104) | Aug (100) | Sep (57) | Oct (41) | Nov (47) | Dec (51) |
| 2013 | Jan (94) | Feb (57) | Mar (96) | Apr (105) | May (77) | Jun (102) | Jul (27) | Aug (81) | Sep (32) | Oct (53) | Nov (127) | Dec (65) |
| 2014 | Jan (113) | Feb (59) | Mar (104) | Apr (259) | May (70) | Jun (70) | Jul (146) | Aug (45) | Sep (58) | Oct (149) | Nov (77) | Dec (83) |
| 2015 | Jan (53) | Feb (66) | Mar (86) | Apr (50) | May (135) | Jun (76) | Jul (151) | Aug (83) | Sep (97) | Oct (262) | Nov (245) | Dec (231) |
| 2016 | Jan (131) | Feb (233) | Mar (97) | Apr (138) | May (221) | Jun (254) | Jul (92) | Aug (248) | Sep (168) | Oct (275) | Nov (477) | Dec (445) |
| 2017 | Jan (218) | Feb (217) | Mar (146) | Apr (172) | May (216) | Jun (252) | Jul (164) | Aug (192) | Sep (190) | Oct (143) | Nov (255) | Dec (182) |
| 2018 | Jan (295) | Feb (164) | Mar (113) | Apr (147) | May (64) | Jun (262) | Jul (184) | Aug (90) | Sep (69) | Oct (364) | Nov (102) | Dec (101) |
| 2019 | Jan (119) | Feb (64) | Mar (64) | Apr (102) | May (57) | Jun (154) | Jul (84) | Aug (81) | Sep (76) | Oct (102) | Nov (233) | Dec (89) |
| 2020 | Jan (38) | Feb (170) | Mar (155) | Apr (172) | May (120) | Jun (223) | Jul (461) | Aug (227) | Sep (268) | Oct (113) | Nov (56) | Dec (124) |
| 2021 | Jan (121) | Feb (48) | Mar (334) | Apr (345) | May (207) | Jun (136) | Jul (71) | Aug (112) | Sep (122) | Oct (173) | Nov (184) | Dec (223) |
| 2022 | Jan (197) | Feb (206) | Mar (156) | Apr (212) | May (192) | Jun (170) | Jul (143) | Aug (380) | Sep (182) | Oct (148) | Nov (128) | Dec (269) |
| 2023 | Jan (248) | Feb (196) | Mar (264) | Apr (36) | May (123) | Jun (66) | Jul (120) | Aug (48) | Sep (157) | Oct (198) | Nov (300) | Dec (273) |
| 2024 | Jan (271) | Feb (147) | Mar (207) | Apr (78) | May (107) | Jun (168) | Jul (151) | Aug (51) | Sep (438) | Oct (221) | Nov (302) | Dec (357) |
| 2025 | Jan (451) | Feb (219) | Mar (326) | Apr (232) | May (306) | Jun (181) | Jul (452) | Aug (282) | Sep (620) | Oct (793) | Nov (682) | Dec |
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
| | | | | | | 1 |
| 2 | 3 (3) | 4 (1) | 5 (26) | 6 (34) | 7 (6) | 8 (17) |
| 9 (15) | 10 | 11 (8) | 12 (22) | 13 (3) | 14 (10) | 15 |
| 16 | 17 (4) | 18 (32) | 19 (18) | 20 (11) | 21 (5) | 22 |
| 23 (3) | 24 (35) | 25 (16) | 26 (14) | 27 (26) | 28 (7) | 29 (1) |
| 30 | 31 (9) | | | | | |
| From: d12fk (C. Review) <ge...@op...> - 2025-03-19 23:22:13 |
Attention is currently required from: plaisthos, stipa. Hello flichtenheld, plaisthos, stipa, I'd like you to reexamine a change. Please visit http://gerrit.openvpn.net/c/openvpn/+/837?usp=email to look at the new patch set (#14). Change subject: win: implement --dns option support with NRPT ...................................................................... win: implement --dns option support with NRPT Implement support for setting options from --dns. This is hugely different than what we had so far with DNS related --dhcp-option. The main difference it that we support split DNS and DNSSEC by making use of NRPT (Name Resolution Policy Table). Also OpenVPN tries to keep local DNS resolution working when DNS is redirected into the tunnel. To prevent this from happening we have --block-outside-dns, in case you wonder. Basically we collect domains and name server addresses from network adapters and add so called exclude NRPT rules in addition to the catch all rule that is pushed by the server. All is done via the interactive service, since modifying all this requires the elevated privileges that the openvpn process hopefully doesn't have. Change-Id: I576e74f3276362606e9cbd50bb5adbebaaf209cc Signed-off-by: Heiko Hund <he...@is...> --- M include/openvpn-msg.h M src/openvpn/dns.c M src/openvpn/dns.h M src/openvpn/init.c M src/openvpnserv/interactive.c 5 files changed, 1,129 insertions(+), 7 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/37/837/14 diff --git a/include/openvpn-msg.h b/include/openvpn-msg.h index 7a99335..8b48053 100644 --- a/include/openvpn-msg.h +++ b/include/openvpn-msg.h @@ -35,6 +35,8 @@ msg_del_route, msg_add_dns_cfg, msg_del_dns_cfg, + msg_add_nrpt_cfg, + msg_del_nrpt_cfg, msg_add_nbt_cfg, msg_del_nbt_cfg, msg_flush_neighbors, @@ -96,6 +98,23 @@ inet_address_t addr[4]; /* support up to 4 dns addresses */ } dns_cfg_message_t; + +typedef enum { + nrpt_dnssec +} nrpt_flags_t; + +#define NRPT_ADDR_NUM 8 /* Max. number of addresses */ +#define NRPT_ADDR_SIZE 48 /* Max. address strlen + some */ +typedef char nrpt_address_t[NRPT_ADDR_SIZE]; +typedef struct { + message_header_t header; + interface_t iface; + nrpt_address_t addresses[NRPT_ADDR_NUM]; + char resolve_domains[512]; /* double \0 terminated */ + char search_domains[512]; + nrpt_flags_t flags; +} nrpt_dns_cfg_message_t; + typedef struct { message_header_t header; interface_t iface; diff --git a/src/openvpn/dns.c b/src/openvpn/dns.c index cf48c22..b6e524f 100644 --- a/src/openvpn/dns.c +++ b/src/openvpn/dns.c @@ -29,6 +29,12 @@ #include "dns.h" #include "socket.h" +#include "options.h" + +#ifdef _WIN32 +#include "win32.h" +#include "openvpn-msg.h" +#endif /** * Parses a string as port and stores it @@ -428,6 +434,122 @@ gc_free(&gc); } +#ifdef _WIN32 + +static void +make_domain_list(const char *what, const struct dns_domain *src, + bool nrpt_domains, char *dst, size_t dst_size) +{ + /* NRPT domains need two \0 at the end for REG_MULTI_SZ + * and a leading '.' added in front of the domain name */ + size_t term_size = nrpt_domains ? 2 : 1; + size_t leading_dot = nrpt_domains ? 1 : 0; + size_t offset = 0; + + memset(dst, 0, dst_size); + + while (src) + { + size_t len = strlen(src->name); + if (offset + leading_dot + len + term_size > dst_size) + { + msg(M_WARN, "WARNING: %s truncated", what); + if (offset) + { + /* Remove trailing comma */ + *(dst + offset - 1) = '\0'; + } + break; + } + + if (leading_dot) + { + *(dst + offset++) = '.'; + } + strncpy(dst + offset, src->name, len); + offset += len; + + src = src->next; + if (src) + { + *(dst + offset++) = ','; + } + } +} + +static void +run_up_down_service(bool add, const struct options *o, const struct tuntap *tt) +{ + const struct dns_server *server = o->dns_options.servers; + const struct dns_domain *search_domains = o->dns_options.search_domains; + + while (true) + { + if (!server) + { + if (add) + { + msg(M_WARN, "WARNING: setting DNS failed, no compatible server profile"); + } + return; + } + + bool only_standard_server_ports = true; + for (size_t i = 0; i < NRPT_ADDR_NUM; ++i) + { + if (server->addr[i].port && server->addr[i].port != 53) + { + only_standard_server_ports = false; + break; + } + } + if ((server->transport == DNS_TRANSPORT_UNSET || server->transport == DNS_TRANSPORT_PLAIN) + && only_standard_server_ports) + { + break; /* found compatible server */ + } + + server = server->next; + } + + ack_message_t ack; + nrpt_dns_cfg_message_t nrpt = { + .header = { + (add ? msg_add_nrpt_cfg : msg_del_nrpt_cfg), + sizeof(nrpt_dns_cfg_message_t), + 0 + }, + .iface = { .index = tt->adapter_index, .name = "" }, + .flags = server->dnssec == DNS_SECURITY_NO ? 0 : nrpt_dnssec, + }; + strncpynt(nrpt.iface.name, tt->actual_name, sizeof(nrpt.iface.name)); + + for (size_t i = 0; i < NRPT_ADDR_NUM; ++i) + { + if (server->addr[i].family == AF_UNSPEC) + { + /* No more addresses */ + break; + } + + if (inet_ntop(server->addr[i].family, &server->addr[i].in, + nrpt.addresses[i], NRPT_ADDR_SIZE) == NULL) + { + msg(M_WARN, "WARNING: could not convert dns server address"); + } + } + + make_domain_list("dns server resolve domains", server->domains, true, + nrpt.resolve_domains, sizeof(nrpt.resolve_domains)); + + make_domain_list("dns search domains", search_domains, false, + nrpt.search_domains, sizeof(nrpt.search_domains)); + + send_msg_iservice(o->msg_channel, &nrpt, sizeof(nrpt), &ack, "DNS"); +} + +#endif /* _WIN32 */ + void show_dns_options(const struct dns_options *o) { @@ -506,3 +628,43 @@ gc_free(&gc); } + +void +run_dns_up_down(bool up, struct options *o, const struct tuntap *tt) +{ + if (!o->dns_options.servers) + { + return; + } + + /* Warn about adding servers of unsupported AF */ + const struct dns_server *s = o->dns_options.servers; + while (up && s) + { + size_t bad_count = 0; + for (size_t i = 0; i < s->addr_count; ++i) + { + if ((s->addr[i].family == AF_INET6 && !tt->did_ifconfig_ipv6_setup) + || (s->addr[i].family == AF_INET && !tt->did_ifconfig_setup)) + { + ++bad_count; + } + } + if (bad_count == s->addr_count) + { + msg(M_WARN, "DNS server %ld only has address(es) from a family " + "the tunnel is not configured for - it will not be reachable", + s->priority); + } + else if (bad_count) + { + msg(M_WARN, "DNS server %ld has address(es) from a family " + "the tunnel is not configured for", s->priority); + } + s = s->next; + } + +#ifdef _WIN32 + run_up_down_service(up, o, tt); +#endif /* ifdef _WIN32 */ +} diff --git a/src/openvpn/dns.h b/src/openvpn/dns.h index 838ebe1..f24e30b 100644 --- a/src/openvpn/dns.h +++ b/src/openvpn/dns.h @@ -26,6 +26,7 @@ #include "buffer.h" #include "env_set.h" +#include "tun.h" enum dns_security { DNS_SECURITY_UNSET, @@ -147,6 +148,14 @@ void dns_options_postprocess_pull(struct dns_options *o); /** + * Invokes the action associated with bringing DNS up or down + * @param up Boolean to set this call to "up" when true + * @param o Pointer to the program options + * @param tt Pointer to the connection's tuntap struct + */ +void run_dns_up_down(bool up, struct options *o, const struct tuntap *tt); + +/** * Puts the DNS options into an environment set. * * @param o Pointer to the DNS options to set diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 1be205b..9eb8290 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -2026,6 +2026,8 @@ c->c2.frame.tun_mtu, c->c2.es, &c->net_ctx); } + run_dns_up_down(true, &c->options, c->c1.tuntap); + /* run the up script */ run_up_down(c->options.up_script, c->plugins, @@ -2064,6 +2066,8 @@ /* explicitly set the ifconfig_* env vars */ do_ifconfig_setenv(c->c1.tuntap, c->c2.es); + run_dns_up_down(true, &c->options, c->c1.tuntap); + /* run the up script if user specified --up-restart */ if (c->options.up_restart) { @@ -2152,6 +2156,8 @@ adapter_index = c->c1.tuntap->adapter_index; #endif + run_dns_up_down(false, &c->options, c->c1.tuntap); + if (force || !(c->sig->signal_received == SIGUSR1 && c->options.persist_tun)) { static_context = NULL; diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c index 50363b6..1e4289d 100644 --- a/src/openvpnserv/interactive.c +++ b/src/openvpnserv/interactive.c @@ -88,6 +88,7 @@ wfp_block, undo_dns4, undo_dns6, + undo_nrpt, undo_domains, undo_ring_buffer, undo_wins, @@ -119,12 +120,20 @@ flush_neighbors_message_t flush_neighbors; wfp_block_message_t wfp_block; dns_cfg_message_t dns; + nrpt_dns_cfg_message_t nrpt_dns; enable_dhcp_message_t dhcp; register_ring_buffers_message_t rrb; set_mtu_message_t mtu; wins_cfg_message_t wins; } pipe_message_t; +typedef struct { + CHAR addresses[NRPT_ADDR_NUM * NRPT_ADDR_SIZE]; + WCHAR domains[512]; /* MULTI_SZ string */ + DWORD domains_size; /* bytes in domains */ +} nrpt_exclude_data_t; + + static DWORD AddListItem(list_item_t **pfirst, LPVOID data) { @@ -1944,6 +1953,906 @@ return err; } +/** + * Checks if DHCP is enabled for an interface + * + * @param key HKEY of the interface to check for + * + * @return BOOL set to TRUE if DHCP is enabled, or FALSE if + * disabled or an error occurred + */ +static BOOL +IsDhcpEnabled(HKEY key) +{ + DWORD dhcp; + DWORD size = sizeof(dhcp); + LSTATUS err; + + err = RegGetValueA(key, NULL, "EnableDHCP", RRF_RT_REG_DWORD, NULL, (PBYTE)&dhcp, &size); + if (err != NO_ERROR) + { + MsgToEventLog(M_SYSERR, TEXT("IsDhcpEnabled: " + "Could not read DHCP status (%lu)"), err); + return FALSE; + } + + return dhcp ? TRUE : FALSE; +} + +/** + * Set name servers from a NRPT address list + * + * @param itf_id the VPN interface ID to set the name servers for + * @param addresses the list of NRPT addresses + * + * @return LSTATUS NO_ERROR in case of success, a Windows error code otherwise + */ +static LSTATUS +SetNameServerAddresses(PWSTR itf_id, const nrpt_address_t *addresses) +{ + const short families[] = { AF_INET, AF_INET6 }; + for (int i = 0; i < _countof(families); i++) + { + short family = families[i]; + + /* Create a comma sparated list of addresses of this family */ + int offset = 0; + char addr_list[NRPT_ADDR_SIZE * NRPT_ADDR_NUM]; + for (int j = 0; j < NRPT_ADDR_NUM && addresses[j][0]; j++) + { + if ((family == AF_INET6 && strchr(addresses[j], ':') == NULL) + || (family == AF_INET && strchr(addresses[j], ':') != NULL)) + { + /* Address family doesn't match, skip this one */ + continue; + } + if (offset) + { + addr_list[offset++] = ','; + } + strcpy(addr_list + offset, addresses[j]); + offset += strlen(addresses[j]); + } + + if (offset == 0) + { + /* No address for this family to set */ + continue; + } + + /* Set name server addresses */ + LSTATUS err = SetNameServers(itf_id, family, addr_list); + if (err) + { + return err; + } + } + return NO_ERROR; +} + +/** + * Get DNS server IPv4 addresses of an interface + * + * @param itf_key registry key of the IPv4 interface data + * @param addrs pointer to the buffer addresses are returned in + * @param size pointer to the size of the buffer, contains the + * size of the addresses on return + * + * @return LSTATUS NO_ERROR on success, a Windows error code otherwise + */ +static LSTATUS +GetItfDnsServersV4(HKEY itf_key, PSTR addrs, PDWORD size) +{ + addrs[*size - 1] = '\0'; + + LSTATUS err; + DWORD s = *size; + err = RegGetValueA(itf_key, NULL, "NameServer", RRF_RT_REG_SZ, NULL, (PBYTE)addrs, &s); + if (err && err != ERROR_FILE_NOT_FOUND) + { + *size = 0; + return err; + } + + /* Try DHCP addresses if we don't have some already */ + if (!strchr(addrs, '.') && IsDhcpEnabled(itf_key)) + { + s = *size; + RegGetValueA(itf_key, NULL, "DhcpNameServer", RRF_RT_REG_SZ, NULL, (PBYTE)addrs, &s); + if (err) + { + *size = 0; + return err; + } + } + + if (strchr(addrs, '.')) + { + *size = s; + return NO_ERROR; + } + + *size = 0; + return ERROR_FILE_NOT_FOUND; +} + +/** + * Get DNS server IPv6 addresses of an interface + * + * @param itf_key registry key of the IPv6 interface data + * @param addrs pointer to the buffer addresses are returned in + * @param size pointer to the size of the buffer + * + * @return LSTATUS NO_ERROR on success, a Windows error code otherwise + */ +static LSTATUS +GetItfDnsServersV6(HKEY itf_key, PSTR addrs, PDWORD size) +{ + addrs[*size - 1] = '\0'; + + LSTATUS err; + DWORD s = *size; + err = RegGetValueA(itf_key, NULL, "NameServer", RRF_RT_REG_SZ, NULL, (PBYTE)addrs, &s); + if (err && err != ERROR_FILE_NOT_FOUND) + { + *size = 0; + return err; + } + + /* Try DHCP addresses if we don't have some already */ + if (!strchr(addrs, ':') && IsDhcpEnabled(itf_key)) + { + IN6_ADDR in_addrs[8]; + DWORD in_addrs_size = sizeof(in_addrs); + err = RegGetValueA(itf_key, NULL, "Dhcpv6DNSServers", RRF_RT_REG_BINARY, NULL, + (PBYTE)in_addrs, &in_addrs_size); + if (err) + { + *size = 0; + return err; + } + + s = *size; + PSTR pos = addrs; + size_t in_addrs_read = in_addrs_size / sizeof(IN6_ADDR); + for (size_t i = 0; i < in_addrs_read; ++i) + { + if (i != 0) + { + /* Add separator */ + *pos++ = ','; + s--; + } + + if (inet_ntop(AF_INET6, &in_addrs[i], + pos, s) != NULL) + { + *size = 0; + return ERROR_MORE_DATA; + } + + size_t addr_len = strlen(pos); + pos += addr_len; + s -= addr_len; + } + s = strlen(addrs) + 1; + } + + if (strchr(addrs, ':')) + { + *size = s; + return NO_ERROR; + } + + *size = 0; + return ERROR_FILE_NOT_FOUND; +} + +/** + * Return interface specific domain suffix(es) + * + * The \p domains paramter will be set to a MULTI_SZ domains string. + * In case of an error or if no domains are found for the interface + * \p size is set to 0 and the contents of \p domains are invalid. + * Note that the domains could have been set by DHCP or manually. + * + * @param itf HKEY of the interface to read from + * @param domains PWSTR buffer to return the domain(s) in + * @param size pointer to size of the domains buffer in bytes. Will be + * set to the size of the string returned, including + * the terminating zeros or 0. + * + * @return LSTATUS NO_ERROR if the domain suffix(es) were read successfully, + * ERROR_FILE_NOT_FOUND if no domain was found for the interface, + * ERROR_MORE_DATA if the list did not fit into the buffer, + * any other error indicates an error while reading from the registry. + */ +static LSTATUS +GetItfDnsDomains(HKEY itf, PWSTR domains, PDWORD size) +{ + if (domains == NULL || size == 0) + { + return ERROR_INVALID_PARAMETER; + } + + LSTATUS err = ERROR_FILE_NOT_FOUND; + const DWORD buf_size = *size; + const size_t one_glyph = sizeof(*domains); + PWSTR values[] = { L"SearchList", L"Domain", L"DhcpDomainSearchList", L"DhcpDomain", NULL}; + + for (int i = 0; values[i]; i++) + { + err = RegGetValueW(itf, NULL, values[i], RRF_RT_REG_SZ, NULL, (PBYTE)domains, size); + if (!err && *size > one_glyph && wcschr(domains, '.')) + { + /* + * Found domain(s), now convert them: + * - prefix each domain with a dot + * - convert comma separated list to MULTI_SZ + */ + PWCHAR pos = domains; + const DWORD buf_len = buf_size / one_glyph; + while (TRUE) + { + /* Terminate the domain at the next comma */ + PWCHAR comma = wcschr(pos, ','); + if (comma) + { + *comma = '\0'; + } + + /* Check for enough space to convert this domain */ + size_t converted_size = pos - domains; + size_t domain_len = wcslen(pos) + 1; + size_t domain_size = domain_len * one_glyph; + size_t extra_size = 2 * one_glyph; + if (converted_size + domain_size + extra_size > buf_size) + { + /* Domain doesn't fit, bad luck if it's the first one */ + *pos = '\0'; + *size = converted_size == 0 ? 0 : *size + 1; + return ERROR_MORE_DATA; + } + + /* Prefix domain at pos with the dot */ + memmove(pos + 1, pos, buf_size - converted_size - one_glyph); + domains[buf_len - 1] = '\0'; + *pos = '.'; + *size += 1; + + if (!comma) + { + /* Conversion is done */ + *(pos + domain_len) = '\0'; + *size += 1; + return NO_ERROR; + } + + pos = comma + 1; + } + } + } + + *size = 0; + return err; +} + +/** + * Check if an interface is connected and up + * + * @param iid_str the interface GUID as string + * + * @return TRUE if the interface is connected and up, FALSE otherwise or in + * case an error happened + */ +static BOOL +IsInterfaceConnected(PWSTR iid_str) +{ + GUID iid; + BOOL res = FALSE; + MIB_IF_ROW2 itf_row; + + /* Get LUID from GUID string */ + if (IIDFromString(iid_str, &iid) != S_OK + || ConvertInterfaceGuidToLuid(&iid, &itf_row.InterfaceLuid) != NO_ERROR) + { + MsgToEventLog(M_SYSERR, TEXT("IsInterfaceConnected: " + "could not convert interface %s GUID to LUID"), iid_str); + goto out; + } + + /* Look up interface status */ + if (GetIfEntry2(&itf_row) != NO_ERROR) + { + MsgToEventLog(M_SYSERR, TEXT("IsInterfaceConnected: " + "could not get interface %s status"), iid_str); + goto out; + } + + if (itf_row.MediaConnectState == MediaConnectStateConnected + && itf_row.OperStatus == IfOperStatusUp) + { + res = TRUE; + } + +out: + return res; +} + +/** + * Collect interface DNS settings to be used in excluding NRPT rules. This is + * needed so that local DNS keeps working even when a catch all NRPT rule is + * installed by a VPN connection. + * + * @param data pointer to the data structures the values are returned in + * @param data_size number of exclude data structures pointed to + */ +static void +GetNrptExcludeData(nrpt_exclude_data_t *data, size_t data_size) +{ + HKEY v4_itfs = INVALID_HANDLE_VALUE; + HKEY v6_itfs = INVALID_HANDLE_VALUE; + + if (!GetInterfacesKey(AF_INET, &v4_itfs) + || !GetInterfacesKey(AF_INET6, &v6_itfs)) + { + goto out; + } + + size_t i = 0; + DWORD enum_index = 0; + while (i < data_size) + { + WCHAR itf_guid[MAX_PATH]; + DWORD itf_guid_len = _countof(itf_guid); + LSTATUS err = RegEnumKeyExW(v4_itfs, enum_index++, itf_guid, &itf_guid_len, + NULL, NULL, NULL, NULL); + if (err) + { + if (err != ERROR_NO_MORE_ITEMS) + { + MsgToEventLog(M_SYSERR, TEXT("GetNrptExcludeData: " + "could not enumerate interfaces (%lu)"), err); + } + goto out; + } + + /* Ignore interfaces that are not connected or disabled */ + if (!IsInterfaceConnected(itf_guid)) + { + continue; + } + + HKEY v4_itf; + if (RegOpenKeyExW(v4_itfs, itf_guid, 0, KEY_READ, &v4_itf) != NO_ERROR) + { + MsgToEventLog(M_SYSERR, TEXT("GetNrptExcludeData: " + "could not open interface %s v4 registry key"), itf_guid); + goto out; + } + + /* Get the DNS domain(s) for exclude routing */ + data[i].domains_size = sizeof(data[0].domains); + memset(data[i].domains, 0, data[i].domains_size); + err = GetItfDnsDomains(v4_itf, data[i].domains, &data[i].domains_size); + if (err) + { + if (err != ERROR_FILE_NOT_FOUND) + { + MsgToEventLog(M_SYSERR, TEXT("GetNrptExcludeData: " + "could not read interface %s domain suffix"), itf_guid); + } + goto next_itf; + } + + /* Get the IPv4 DNS servers */ + DWORD v4_addrs_size = sizeof(data[0].addresses); + err = GetItfDnsServersV4(v4_itf, data[i].addresses, &v4_addrs_size); + if (err && err != ERROR_FILE_NOT_FOUND) + { + MsgToEventLog(M_SYSERR, + TEXT("GetNrptExcludeData: could not read interface %s v4 name servers (%ld)"), + itf_guid, err); + goto next_itf; + } + + /* Get the IPv6 DNS servers, if there's space left */ + PSTR v6_addrs = data[i].addresses + v4_addrs_size; + DWORD v6_addrs_size = sizeof(data[0].addresses) - v4_addrs_size; + if (v6_addrs_size > NRPT_ADDR_SIZE) + { + HKEY v6_itf; + if (RegOpenKeyExW(v6_itfs, itf_guid, 0, KEY_READ, &v6_itf) != NO_ERROR) + { + MsgToEventLog(M_SYSERR, TEXT("GetNrptExcludeData: " + "could not open interface %s v6 registry key"), itf_guid); + goto next_itf; + } + err = GetItfDnsServersV6(v6_itf, v6_addrs, &v6_addrs_size); + RegCloseKey(v6_itf); + if (err && err != ERROR_FILE_NOT_FOUND) + { + MsgToEventLog(M_SYSERR, + TEXT("GetNrptExcludeData: could not read interface %s v6 name servers (%ld)"), + itf_guid, err); + goto next_itf; + } + } + + if (v4_addrs_size || v6_addrs_size) + { + /* Replace comma-delimters with semicolons, as required by NRPT */ + for (int j = 0; j < sizeof(data[0].addresses) && data[i].addresses[j]; j++) + { + if (data[i].addresses[j] == ',') + { + data[i].addresses[j] = ';'; + } + } + ++i; + } + +next_itf: + RegCloseKey(v4_itf); + } + +out: + RegCloseKey(v6_itfs); + RegCloseKey(v4_itfs); +} + +/** + * Set a NRPT rule (subkey) and its values in the registry + * + * @param nrpt_key NRPT registry key handle + * @param subkey subkey string to create + * @param address name server address string + * @param domains domains to resolve by this server as MULTI_SZ + * @param dom_size size of domains in bytes including the terminators + * @param dnssec boolean to determine if DNSSEC is to be enabled + * + * @return NO_ERROR on success, or Windows error code + */ +static DWORD +SetNrptRule(HKEY nrpt_key, PCWSTR subkey, PCSTR address, + PCWSTR domains, DWORD dom_size, BOOL dnssec) +{ + /* Create rule subkey */ + DWORD err = NO_ERROR; + HKEY rule_key; + err = RegCreateKeyExW(nrpt_key, subkey, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &rule_key, NULL); + if (err) + { + return err; + } + + /* Set name(s) for DNS routing */ + err = RegSetValueExW(rule_key, L"Name", 0, REG_MULTI_SZ, (PBYTE)domains, dom_size); + if (err) + { + goto out; + } + + /* Set DNS Server address */ + err = RegSetValueExA(rule_key, "GenericDNSServers", 0, REG_SZ, (PBYTE)address, strlen(address) + 1); + if (err) + { + goto out; + } + + DWORD reg_val; + /* Set DNSSEC if required */ + if (dnssec) + { + reg_val = 1; + err = RegSetValueExA(rule_key, "DNSSECValidationRequired", 0, REG_DWORD, (PBYTE)®_val, sizeof(reg_val)); + if (err) + { + goto out; + } + + reg_val = 0; + err = RegSetValueExA(rule_key, "DNSSECQueryIPSECRequired", 0, REG_DWORD, (PBYTE)®_val, sizeof(reg_val)); + if (err) + { + goto out; + } + + reg_val = 0; + err = RegSetValueExA(rule_key, "DNSSECQueryIPSECEncryption", 0, REG_DWORD, (PBYTE)®_val, sizeof(reg_val)); + if (err) + { + goto out; + } + } + + /* Set NRPT config options */ + reg_val = dnssec ? 0x0000000A : 0x00000008; + err = RegSetValueExA(rule_key, "ConfigOptions", 0, REG_DWORD, (const PBYTE)®_val, sizeof(reg_val)); + if (err) + { + goto out; + } + + /* Mandatory NRPT version */ + reg_val = 2; + err = RegSetValueExA(rule_key, "Version", 0, REG_DWORD, (const PBYTE)®_val, sizeof(reg_val)); + if (err) + { + goto out; + } + +out: + if (err) + { + RegDeleteKeyW(nrpt_key, subkey); + } + RegCloseKey(rule_key); + return err; +} + +/** + * Set NRPT exclude rules to accompany a catch all rule. This is done so that + * local resolution of names is not interfered with in case the VPN resolves + * all names. + * + * @param nrpt_key the registry key to set the rules under + * @param ovpn_pid the PID of the openvpn process + */ +static void +SetNrptExcludeRules(HKEY nrpt_key, DWORD ovpn_pid) +{ + nrpt_exclude_data_t data[8]; /* data from up to 8 interfaces */ + memset(data, 0, sizeof(data)); + GetNrptExcludeData(data, _countof(data)); + + unsigned n = 0; + for (int i = 0; i < _countof(data); ++i) + { + DWORD err; + WCHAR subkey[48]; + swprintf(subkey, _countof(subkey), L"OpenVPNDNSRoutingX-%02x-%lu", ++n, ovpn_pid); + + nrpt_exclude_data_t *d = &data[i]; + err = SetNrptRule(nrpt_key, subkey, d->addresses, d->domains, d->domains_size, FALSE); + if (err) + { + MsgToEventLog(M_ERR, TEXT("SetNrptExcludeRules: " + "failed to set rule %s (%lu)"), subkey, err); + } + } +} + +/** + * Set NRPT rules for a openvpn process + * + * @param nrpt_key the registry key to set the rules under + * @param addresses name server addresses + * @param domains optional list of split routing domains + * @param dnssec boolean whether DNSSEC is to be used + * @param ovpn_pid the PID of the openvpn process + * + * @return NO_ERROR on success, or a Windows error code + */ +static DWORD +SetNrptRules(HKEY nrpt_key, const nrpt_address_t *addresses, + const char *domains, BOOL dnssec, DWORD ovpn_pid) +{ + DWORD err = NO_ERROR; + PWSTR wide_domains = L".\0"; /* DNS route everything by default */ + DWORD dom_size = 6; + + /* Prepare DNS routing domains / split DNS */ + if (domains[0]) + { + size_t domains_len = strlen(domains); + dom_size = domains_len + 2; /* len + the trailing NULs */ + + wide_domains = utf8to16_size(domains, dom_size); + dom_size *= sizeof(*wide_domains); + if (!wide_domains) + { + return ERROR_OUTOFMEMORY; + } + /* Make a MULTI_SZ from a comma separated list */ + for (size_t i = 0; i < domains_len; ++i) + { + if (wide_domains[i] == ',') + { + wide_domains[i] = 0; + } + } + } + else + { + SetNrptExcludeRules(nrpt_key, ovpn_pid); + } + + /* Create address string list */ + CHAR addr_list[NRPT_ADDR_NUM * NRPT_ADDR_SIZE]; + PSTR pos = addr_list; + for (int i = 0; i < NRPT_ADDR_NUM && addresses[i][0]; ++i) + { + if (i != 0) + { + *pos++ = ';'; + } + strcpy(pos, addresses[i]); + pos += strlen(pos); + } + + WCHAR subkey[MAX_PATH]; + swprintf(subkey, _countof(subkey), L"OpenVPNDNSRouting-%lu", ovpn_pid); + err = SetNrptRule(nrpt_key, subkey, addr_list, wide_domains, dom_size, dnssec); + if (err) + { + MsgToEventLog(M_ERR, TEXT("SetNrptRules: " + "failed to set rule %s (%lu)"), subkey, err); + } + + if (domains[0]) + { + free(wide_domains); + } + return err; +} + +/** + * Return the registry key where NRPT rules are stored + * + * @param key pointer to the HKEY it is returned in + * @param gpol pointer to BOOL the use of GPOL hive is returned in + * + * @return NO_ERROR on success, or a Windows error code + */ +static LSTATUS +OpenNrptBaseKey(PHKEY key, PBOOL gpol) +{ + /* + * Registry keys Name Service Policy Table (NRPT) rules can be stored at. + * When the group policy key exists, NRPT rules must be placed there. + * It is created when NRPT rules are pushed via group policy and it + * remains in the registry even if the last GP-NRPT rule is deleted. + */ + static PCSTR gpol_key = "SOFTWARE\\Policies\\Microsoft\\Windows NT\\DNSClient\\DnsPolicyConfig"; + static PCSTR sys_key = "SYSTEM\\CurrentControlSet\\Services\\Dnscache\\Parameters\\DnsPolicyConfig"; + + HKEY nrpt; + *gpol = TRUE; + LSTATUS err = RegOpenKeyExA(HKEY_LOCAL_MACHINE, gpol_key, 0, KEY_ALL_ACCESS, &nrpt); + if (err == ERROR_FILE_NOT_FOUND) + { + *gpol = FALSE; + err = RegOpenKeyExA(HKEY_LOCAL_MACHINE, sys_key, 0, KEY_ALL_ACCESS, &nrpt); + if (err) + { + nrpt = INVALID_HANDLE_VALUE; + } + } + *key = nrpt; + return err; +} + +/** + * Delete OpenVPN NRPT rules from the registry + * + * If the pid parameter is 0 all NRPT rules added by OpenVPN are deleted. + * In all other cases only rules matching the pid are deleted. + * + * @param pid PID of the process to delete the rules for or 0 + * @param gpol + * + * @return BOOL to indicate if rules were deleted + */ +static BOOL +DeleteNrptRules(DWORD pid, PBOOL gpol) +{ + HKEY key; + LSTATUS err = OpenNrptBaseKey(&key, gpol); + if (err) + { + MsgToEventLog(M_SYSERR, TEXT("DeleteNrptRules: " + "could not open NRPT base key (%lu)"), err); + return FALSE; + } + + /* PID suffix string to compare against later */ + WCHAR pid_str[16]; + size_t pidlen = 0; + if (pid) + { + swprintf(pid_str, _countof(pid_str), L"-%lu", pid); + pidlen = wcslen(pid_str); + } + + int deleted = 0; + DWORD enum_index = 0; + while (TRUE) + { + WCHAR name[MAX_PATH]; + DWORD namelen = _countof(name); + err = RegEnumKeyExW(key, enum_index++, name, &namelen, NULL, NULL, NULL, NULL); + if (err) + { + if (err != ERROR_NO_MORE_ITEMS) + { + MsgToEventLog(M_SYSERR, TEXT("DeleteNrptRules: " + "could not enumerate NRPT rules (%lu)"), err); + } + break; + } + + /* Keep rule if name doesn't match */ + if (wcsncmp(name, L"OpenVPNDNSRouting", 17) != 0 + || (pid && wcsncmp(name + namelen - pidlen, pid_str, pidlen) != 0)) + { + continue; + } + + if (RegDeleteKeyW(key, name) == NO_ERROR) + { + enum_index--; + deleted++; + } + } + + RegCloseKey(key); + return deleted ? TRUE : FALSE; +} + +/** + * Delete a process' NRPT rules and apply the reduced set of rules + * + * @param ovpn_pid OpenVPN process id to delete rules for + */ +static void +UndoNrptRules(DWORD ovpn_pid) +{ + BOOL gpol; + if (DeleteNrptRules(ovpn_pid, &gpol)) + { + ApplyDnsSettings(gpol); + } +} + +/** + * Add Name Resolution Policy Table (NRPT) rules as documented in + * https://msdn.microsoft.com/en-us/library/ff957356.aspx for DNS name + * resolution, as well as DNS search domain(s), if given. + * + * @param msg config messages sent by the openvpn process + * @param ovpn_pid process id of the sending openvpn process + * @param lists undo lists for this process + * + * @return NO_ERROR on success, or a Windows error code + */ +static DWORD +HandleDNSConfigNrptMessage(const nrpt_dns_cfg_message_t *msg, + DWORD ovpn_pid, undo_lists_t *lists) +{ + /* + * Use a non-const reference with limited scope to + * enforce null-termination of strings from client + */ + { + nrpt_dns_cfg_message_t *msgptr = (nrpt_dns_cfg_message_t *) msg; + msgptr->iface.name[_countof(msg->iface.name) - 1] = '\0'; + msgptr->search_domains[_countof(msg->search_domains) - 1] = '\0'; + msgptr->resolve_domains[_countof(msg->resolve_domains) - 1] = '\0'; + for (size_t i = 0; i < NRPT_ADDR_NUM; ++i) + { + msgptr->addresses[i][_countof(msg->addresses[0]) - 1] = '\0'; + } + } + + /* Make sure we have the VPN interface name */ + if (msg->iface.name[0] == 0) + { + return ERROR_MESSAGE_DATA; + } + + /* Some sanity checks on the add message data */ + if (msg->header.type == msg_add_nrpt_cfg) + { + /* At least one name server address is set */ + if (msg->addresses[0][0] == 0) + { + return ERROR_MESSAGE_DATA; + } + /* Resolve domains are double zero terminated (MULTI_SZ) */ + const char *rdom = msg->resolve_domains; + size_t rdom_size = sizeof(msg->resolve_domains); + size_t rdom_len = strlen(rdom); + if (rdom_len && (rdom_len + 1 >= rdom_size || rdom[rdom_len + 2] != 0)) + { + return ERROR_MESSAGE_DATA; + } + } + + BOOL gpol_nrpt = FALSE; + BOOL gpol_list = FALSE; + + WCHAR iid[64]; + DWORD iid_err = InterfaceIdString(msg->iface.name, iid, _countof(iid)); + if (iid_err) + { + return iid_err; + } + + /* Delete previously set values for this instance first, if any */ + PDWORD undo_pid = RemoveListItem(&(*lists)[undo_nrpt], CmpAny, NULL); + if (undo_pid) + { + if (*undo_pid != ovpn_pid) + { + MsgToEventLog(M_INFO, TEXT("HandleDNSConfigNrptMessage: " + "PID stored for undo doesn't match: %lu vs %lu. " + "This is likely an error. Cleaning up anyway."), + *undo_pid, ovpn_pid); + } + DeleteNrptRules(*undo_pid, &gpol_nrpt); + free(undo_pid); + + ResetNameServers(iid, AF_INET); + ResetNameServers(iid, AF_INET6); + } + SetDnsSearchDomains(msg->iface.name, NULL, &gpol_list, lists); + + if (msg->header.type == msg_del_nrpt_cfg) + { + ApplyDnsSettings(gpol_nrpt || gpol_list); + return NO_ERROR; /* Done dealing with del message */ + } + + HKEY key; + LSTATUS err = OpenNrptBaseKey(&key, &gpol_nrpt); + if (err) + { + goto out; + } + + /* Add undo information first in case there's no heap left */ + PDWORD pid = malloc(sizeof(ovpn_pid)); + if (!pid) + { + err = ERROR_OUTOFMEMORY; + goto out; + } + *pid = ovpn_pid; + if (AddListItem(&(*lists)[undo_nrpt], pid)) + { + err = ERROR_OUTOFMEMORY; + free(pid); + goto out; + } + + /* Set NRPT rules */ + BOOL dnssec = (msg->flags & nrpt_dnssec) != 0; + err = SetNrptRules(key, msg->addresses, msg->resolve_domains, dnssec, ovpn_pid); + if (err) + { + goto out; + } + + /* Set name servers */ + err = SetNameServerAddresses(iid, msg->addresses); + if (err) + { + goto out; + } + + /* Set search domains, if any */ + if (msg->search_domains[0]) + { + err = SetDnsSearchDomains(msg->iface.name, msg->search_domains, &gpol_list, lists); + } + + ApplyDnsSettings(gpol_nrpt || gpol_list); + +out: + return err; +} + static DWORD HandleWINSConfigMessage(const wins_cfg_message_t *msg, undo_lists_t *lists) { @@ -2199,7 +3108,7 @@ } static VOID -HandleMessage(HANDLE pipe, HANDLE ovpn_proc, +HandleMessage(HANDLE pipe, PPROCESS_INFORMATION proc_info, DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists) { pipe_message_t msg; @@ -2262,6 +3171,14 @@ ack.error_number = HandleDNSConfigMessage(&msg.dns, lists); break; + case msg_add_nrpt_cfg: + case msg_del_nrpt_cfg: + { + DWORD ovpn_pid = proc_info->dwProcessId; + ack.error_number = HandleDNSConfigNrptMessage(&msg.nrpt_dns, ovpn_pid, lists); + } + break; + case msg_add_wins_cfg: case msg_del_wins_cfg: ack.error_number = HandleWINSConfigMessage(&msg.wins, lists); @@ -2277,7 +3194,8 @@ case msg_register_ring_buffers: if (msg.header.size == sizeof(msg.rrb)) { - ack.error_number = HandleRegisterRingBuffers(&msg.rrb, ovpn_proc, lists); + HANDLE ovpn_hnd = proc_info->hProcess; + ack.error_number = HandleRegisterRingBuffers(&msg.rrb, ovpn_hnd, lists); } break; @@ -2328,6 +3246,10 @@ ResetNameServers(item->data, AF_INET6); break; + case undo_nrpt: + UndoNrptRules(*(PDWORD)item->data); + break; + case undo_domains: UndoDnsSearchDomains(item->data); break; @@ -2649,7 +3571,7 @@ break; } - HandleMessage(ovpn_pipe, proc_info.hProcess, bytes, 1, &exit_event, &undo_lists); + HandleMessage(ovpn_pipe, &proc_info, bytes, 1, &exit_event, &undo_lists); } WaitForSingleObject(proc_info.hProcess, IO_TIMEOUT); @@ -2845,24 +3767,28 @@ static void CleanupRegistry(void) { - HKEY key; - DWORD changed = 0; + BOOL changed = FALSE; + + /* Clean up leftover NRPT rules */ + BOOL gpol_nrpt; + changed = DeleteNrptRules(0, &gpol_nrpt); /* Clean up leftover DNS search list fragments */ + HKEY key; BOOL gpol_list; GetDnsSearchListKey(NULL, &gpol_list, &key); if (key != INVALID_HANDLE_VALUE) { if (ResetDnsSearchDomains(key)) { - changed++; + changed = TRUE; } RegCloseKey(key); } if (changed) { - ApplyDnsSettings(gpol_list); + ApplyDnsSettings(gpol_nrpt || gpol_list); } } -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/837?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I576e74f3276362606e9cbd50bb5adbebaaf209cc Gerrit-Change-Number: 837 Gerrit-PatchSet: 14 Gerrit-Owner: d12fk <he...@op...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-MessageType: newpatchset |
| From: d12fk (C. Review) <ge...@op...> - 2025-03-19 23:22:10 |
Attention is currently required from: cron2, flichtenheld, plaisthos. Hello cron2, flichtenheld, plaisthos, I'd like you to reexamine a change. Please visit http://gerrit.openvpn.net/c/openvpn/+/838?usp=email to look at the new patch set (#16). The following approvals got outdated and were removed: Code-Review-1 by cron2 Change subject: dns: apply settings via script on unixoid systems ...................................................................... dns: apply settings via script on unixoid systems This introduces a new script hook, the dns-updown, and implements such a command script for a few popular systems (and a default for the not so popular ones). Like the name suggests this hook is soleley for dealing with modifying how names are resolved when the VPN pushes some --dns settings. The default dns updown command is part of the distribution and is installed with openvpn. You can change the path the command is located at as a compile time option, defaults to libexecdir. You can disable the dns-updown hook at compile time by passing --disable-dns-updown to configure or ccmake ENABLE_DNS_UPDOWN to OFF. There's also a new runtime option --dns-updown, which can run a custom command or disable execution of it altogether. Change-Id: Ifbe4ffb44d3bfcaa50adb38cacb3436fcdc71b10 Signed-off-by: Heiko Hund <he...@is...> --- M .gitignore M CMakeLists.txt M config.h.cmake.in M configure.ac M distro/Makefile.am A distro/dns-scripts/Makefile.am A distro/dns-scripts/haikuos_file-dns-updown.sh A distro/dns-scripts/openresolv-dns-updown.sh A distro/dns-scripts/resolvconf_file-dns-updown.sh A distro/dns-scripts/systemd-dns-updown.sh M doc/man-sections/script-options.rst M src/openvpn/Makefile.am M src/openvpn/dns.c M src/openvpn/dns.h M src/openvpn/options.c 15 files changed, 647 insertions(+), 9 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/38/838/16 diff --git a/.gitignore b/.gitignore index db8bb73..04523af 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,7 @@ /doc/doxygen/latex/ /doc/doxygen/openvpn.doxyfile distro/systemd/*.service +distro/dns-scripts/dns-updown sample/sample-keys/sample-ca/ vendor/cmocka_build vendor/dist diff --git a/CMakeLists.txt b/CMakeLists.txt index b04adce..adf6e26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,10 @@ option(USE_WERROR "Treat compiler warnings as errors (-Werror)" ON) option(FAKE_ANDROID "Target Android but do not use actual cross compile/Android cmake to build for simple compile checks on Linux") -set(PLUGIN_DIR /usr/local/lib/openvpn/plugins CACHE FILEPATH "Location of the plugin directory") +option(ENABLE_DNS_UPDOWN "BUILD with --dns-updown support" ON) +set(DNS_UPDOWN_PATH "${CMAKE_INSTALL_PREFIX}/libexec/openvpn/dns-updown" CACHE STRING "Default location for the DNS up/down script") + +set(PLUGIN_DIR "${CMAKE_INSTALL_PREFIX}/lib/openvpn/plugins" CACHE FILEPATH "Location of the plugin directory") # Create machine readable compile commands option(ENABLE_COMPILE_COMMANDS "Generate compile_commands.json and a symlink for clangd to find it" OFF) @@ -577,6 +580,8 @@ add_library_deps(openvpn) +target_compile_options(openvpn PRIVATE -DDNS_UPDOWN_PATH=\"${DNS_UPDOWN_PATH}\") + if(MINGW) target_compile_options(openvpn PRIVATE -municode -UUNICODE) target_link_options(openvpn PRIVATE -municode) diff --git a/config.h.cmake.in b/config.h.cmake.in index 2f7b43d..5164ce3 100644 --- a/config.h.cmake.in +++ b/config.h.cmake.in @@ -35,6 +35,9 @@ /* Enable LZO compression library */ #cmakedefine ENABLE_LZO +/* Enable dns-updown script hook */ +#cmakedefine ENABLE_DNS_UPDOWN + /* Enable NTLMv2 proxy support */ #define ENABLE_NTLM 1 diff --git a/configure.ac b/configure.ac index 9777e36..17565ea 100644 --- a/configure.ac +++ b/configure.ac @@ -96,6 +96,13 @@ ) AC_ARG_ENABLE( + [dns-updown], + [AS_HELP_STRING([--disable-dns-updown], [disable the --dns-updown hook @<:@default=no@:>@])], + , + [enable_dns_updown="yes"] +) + +AC_ARG_ENABLE( [ntlm], [AS_HELP_STRING([--disable-ntlm], [disable NTLMv2 proxy support @<:@default=yes@:>@])], , @@ -315,37 +322,50 @@ plugindir="\${libdir}/openvpn/plugins" fi +AC_ARG_VAR([SCRIPTDIR], [Path of script directory @<:@default=PKGLIBEXECDIR@:>@]) +if test -n "${SCRIPTDIR}"; then + scriptdir="${SCRIPTDIR}" +else + scriptdir="\${pkglibexecdir}" +fi + AC_DEFINE_UNQUOTED([TARGET_ALIAS], ["${host}"], [A string representing our host]) -AM_CONDITIONAL([TARGET_LINUX], [false]) +AM_CONDITIONAL([ENABLE_DNS_UPDOWN],[true]) case "$host" in *-*-linux*) AC_DEFINE([TARGET_LINUX], [1], [Are we running on Linux?]) - AM_CONDITIONAL([TARGET_LINUX], [true]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["L"], [Target prefix]) + AC_SUBST([DNS_UPDOWN_TYPE], ["systemd"]) have_sitnl="yes" pkg_config_required="yes" ;; *-*-solaris*) AC_DEFINE([TARGET_SOLARIS], [1], [Are we running on Solaris?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["S"], [Target prefix]) + AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"]) CPPFLAGS="$CPPFLAGS -D_XPG4_2" test -x /bin/bash && SHELL="/bin/bash" ;; *-*-openbsd*) AC_DEFINE([TARGET_OPENBSD], [1], [Are we running on OpenBSD?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["O"], [Target prefix]) + AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"]) ;; *-*-freebsd*) AC_DEFINE([TARGET_FREEBSD], [1], [Are we running on FreeBSD?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["F"], [Target prefix]) + AC_SUBST([DNS_UPDOWN_TYPE], ["openresolv"]) ;; *-*-netbsd*) AC_DEFINE([TARGET_NETBSD], [1], [Are we running NetBSD?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["N"], [Target prefix]) + AC_SUBST([DNS_UPDOWN_TYPE], ["openresolv"]) ;; *-*-darwin*) AC_DEFINE([TARGET_DARWIN], [1], [Are we running on Mac OS X?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["M"], [Target prefix]) + AM_CONDITIONAL([ENABLE_DNS_UPDOWN], [false]) + AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"]) have_tap_header="yes" ac_cv_type_struct_in_pktinfo=no ;; @@ -353,6 +373,8 @@ AC_DEFINE([TARGET_WIN32], [1], [Are we running WIN32?]) AC_DEFINE([ENABLE_DCO], [1], [DCO is always enabled on Windows]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["W"], [Target prefix]) + AM_CONDITIONAL([ENABLE_DNS_UPDOWN], [false]) + AC_SUBST([DNS_UPDOWN_TYPE], ["windows"]) CPPFLAGS="${CPPFLAGS} -DWIN32_LEAN_AND_MEAN" CPPFLAGS="${CPPFLAGS} -DNTDDI_VERSION=NTDDI_VISTA -D_WIN32_WINNT=_WIN32_WINNT_VISTA" WIN32=yes @@ -360,10 +382,12 @@ *-*-dragonfly*) AC_DEFINE([TARGET_DRAGONFLY], [1], [Are we running on DragonFlyBSD?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["D"], [Target prefix]) + AC_SUBST([DNS_UPDOWN_TYPE], ["openresolv"]) ;; *-aix*) AC_DEFINE([TARGET_AIX], [1], [Are we running AIX?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["A"], [Target prefix]) + AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"]) ROUTE="/usr/sbin/route" have_tap_header="yes" ac_cv_header_net_if_h="no" # exists, but breaks things @@ -371,10 +395,12 @@ *-*-haiku*) AC_DEFINE([TARGET_HAIKU], [1], [Are we running Haiku?]) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["H"], [Target prefix]) + AC_SUBST([DNS_UPDOWN_TYPE], ["haikuos_file"]) LIBS="${LIBS} -lnetwork" ;; *) AC_DEFINE_UNQUOTED([TARGET_PREFIX], ["X"], [Target prefix]) + AC_SUBST([DNS_UPDOWN_TYPE], ["resolvconf_file"]) have_tap_header="yes" ;; esac @@ -1318,6 +1344,12 @@ test "${enable_fragment}" = "yes" && AC_DEFINE([ENABLE_FRAGMENT], [1], [Enable internal fragmentation support]) test "${enable_port_share}" = "yes" && AC_DEFINE([ENABLE_PORT_SHARE], [1], [Enable TCP Server port sharing]) +if test "${enable_dns_updown}" = "yes"; then + AC_DEFINE([ENABLE_DNS_UPDOWN], [1], [Enable dns-updown hook]) +else + AM_CONDITIONAL([ENABLE_DNS_UPDOWN], [false]) +fi + test "${enable_ntlm}" = "yes" && AC_DEFINE([ENABLE_NTLM], [1], [Enable NTLMv2 proxy support]) test "${enable_crypto_ofb_cfb}" = "yes" && AC_DEFINE([ENABLE_OFB_CFB_MODE], [1], [Enable OFB and CFB cipher modes]) if test "${have_export_keying_material}" = "yes"; then @@ -1505,6 +1537,7 @@ sampledir="\$(docdir)/sample" AC_SUBST([plugindir]) +AC_SUBST([scriptdir]) AC_SUBST([sampledir]) AC_SUBST([systemdunitdir]) @@ -1541,6 +1574,7 @@ Makefile distro/Makefile distro/systemd/Makefile + distro/dns-scripts/Makefile doc/Makefile doc/doxygen/Makefile doc/doxygen/openvpn.doxyfile diff --git a/distro/Makefile.am b/distro/Makefile.am index 7a588da..26f577b 100644 --- a/distro/Makefile.am +++ b/distro/Makefile.am @@ -13,3 +13,7 @@ $(srcdir)/Makefile.in SUBDIRS = systemd + +if ENABLE_DNS_UPDOWN +SUBDIRS += dns-scripts +endif diff --git a/distro/dns-scripts/Makefile.am b/distro/dns-scripts/Makefile.am new file mode 100644 index 0000000..ec7bfde --- /dev/null +++ b/distro/dns-scripts/Makefile.am @@ -0,0 +1,28 @@ +# +# OpenVPN -- An application to securely tunnel IP networks +# over a single UDP port, with support for SSL/TLS-based +# session authentication and key exchange, +# packet encryption, packet authentication, and +# packet compression. +# +# Copyright (C) 2002-2024 OpenVPN Inc <sa...@op...> +# + +MAINTAINERCLEANFILES = \ + $(srcdir)/Makefile.in + +EXTRA_DIST = \ + systemd-dns-updown.sh \ + openresolv-dns-updown.sh \ + haikuos_file-dns-updown.sh \ + resolvconf_file-dns-updown.sh + +script_SCRIPTS = \ + dns-updown + +CLEANFILES = $(script_SCRIPTS) + +dns-updown: @DNS...@-d... + cp ${srcdir}/@DNS...@-d... $@ + +all: $(script_SCRIPTS) diff --git a/distro/dns-scripts/haikuos_file-dns-updown.sh b/distro/dns-scripts/haikuos_file-dns-updown.sh new file mode 100644 index 0000000..1b03e9c --- /dev/null +++ b/distro/dns-scripts/haikuos_file-dns-updown.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# +# Simple OpenVPN up/down script for modifying Haiku OS resolv.conf +# (C) Copyright 2024 OpenVPN Inc <sa...@op...> +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Example env from openvpn (most are not applied): +# +# dev tun0 +# script-type dns-up +# dns_search_domain_1 mycorp.in +# dns_search_domain_2 eu.mycorp.com +# dns_server_1_address_1 192.168.99.254 +# dns_server_1_address_2 fd00::99:53 +# dns_server_1_port_1 53 +# dns_server_1_port_2 53 +# dns_server_1_resolve_domain_1 mycorp.in +# dns_server_1_resolve_domain_2 eu.mycorp.com +# dns_server_1_dnssec true +# dns_server_1_transport DoH +# dns_server_1_sni dns.mycorp.in +# + +set -e +u + +conly_standard_server_ports() { + i=1 + while true; do + eval addr=\"\$dns_server_${n}_address_${i}\" + [ -n "$addr" ] || return 0 + + eval port=\"\$dns_server_${n}_port_${i}\" + [ -z "$port" -o "$port" = "53" ] || return 1 + + i=$(expr $i + 1) + done +} + +onf=/boot/system/settings/network/resolv.conf +test -e "$conf" || exit 1 +case "${script_type}" in +dns-up) + n=1 + while :; do + eval addr=\"\$dns_server_${n}_address_1\" + [ -n "$addr" ] || { + echo "setting DNS failed, no compatible server profile" + exit 1 + } + + # Skip server profiles which require DNSSEC, + # secure transport or use a custom port + eval dnssec=\"\$dns_server_${n}_dnssec\" + eval transport=\"\$dns_server_${n}_transport\" + [ -z "$transport" -o "$transport" = "plain" ] \ + && [ -z "$dnssec" -o "$dnssec" = "no" ] \ + && only_standard_server_ports && break + + n=$(expr $n + 1) + done + + eval addr1=\"\$dns_server_${n}_address_1\" + eval addr2=\"\$dns_server_${n}_address_2\" + eval addr3=\"\$dns_server_${n}_address_3\" + text="### openvpn ${dev} begin ###\n" + text="${text}nameserver $addr1\n" + test -z "$addr2" || text="${text}nameserver $addr2\n" + test -z "$addr3" || text="${text}nameserver $addr3\n" + + test -z "$dns_search_domain_1" || { + for i in $(seq 1 6); do + eval domains=\"$domains\$dns_search_domain_${i} \" || break + done + text="${text}search $domains\n" + } + text="${text}### openvpn ${dev} end ###" + + sed -i "1i${text}" "$conf" + ;; +dns-down) + sed -i "/### openvpn ${dev} begin ###/,/### openvpn ${dev} end ###/d" "$conf" + ;; +esac diff --git a/distro/dns-scripts/openresolv-dns-updown.sh b/distro/dns-scripts/openresolv-dns-updown.sh new file mode 100644 index 0000000..1b218f5 --- /dev/null +++ b/distro/dns-scripts/openresolv-dns-updown.sh @@ -0,0 +1,89 @@ +#!/bin/sh +# +# Simple OpenVPN up/down script for openresolv integration +# (C) Copyright 2016 Baptiste Daroussin +# 2024 OpenVPN Inc <sa...@op...> +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Example env from openvpn (most are not applied): +# +# dev tun0 +# script-type dns-up +# dns_search_domain_1 mycorp.in +# dns_search_domain_2 eu.mycorp.com +# dns_server_1_address_1 192.168.99.254 +# dns_server_1_address_2 fd00::99:53 +# dns_server_1_port_1 53 +# dns_server_1_port_2 53 +# dns_server_1_resolve_domain_1 mycorp.in +# dns_server_1_resolve_domain_2 eu.mycorp.com +# dns_server_1_dnssec true +# dns_server_1_transport DoH +# dns_server_1_sni dns.mycorp.in +# + +set -e +u + +only_standard_server_ports() { + i=1 + while true; do + eval addr=\"\$dns_server_${n}_address_${i}\" + [ -n "$addr" ] || return 0 + + eval port=\"\$dns_server_${n}_port_${i}\" + [ -z "$port" -o "$port" = "53" ] || return 1 + + i=$(expr $i + 1) + done +} + +: ${script_type:=dns-down} +case "${script_type}" in +dns-up) + n=1 + while :; do + eval addr=\"\$dns_server_${n}_address_1\" + [ -n "$addr" ] || { + echo "setting DNS failed, no compatible server profile" + exit 1 + } + + # Skip server profiles which require DNSSEC, + # secure transport or use a custom port + eval dnssec=\"\$dns_server_${n}_dnssec\" + eval transport=\"\$dns_server_${n}_transport\" + [ -z "$transport" -o "$transport" = "plain" ] \ + && [ -z "$dnssec" -o "$dnssec" = "no" ] \ + && only_standard_server_ports && break + + n=$(expr $n + 1) + done + + { + i=1 + maxns=3 + while :; do + maxns=$((maxns - 1)) + [ $maxns -gt 0 ] || break + eval option=\"\$dns_server_${n}_address_${i}\" || break + [ "${option}" ] || break + i=$((i + 1)) + echo "nameserver ${option}" + done + i=1 + maxdom=6 + while :; do + maxdom=$((maxdom - 1)) + [ $maxdom -gt 0 ] || break + eval option=\"\$dns_search_domain_${i}\" || break + [ "${option}" ] || break + i=$((i + 1)) + echo "search ${option}" + done + } | /sbin/resolvconf -a "${dev}" + ;; +dns-down) + /sbin/resolvconf -d "${dev}" -f + ;; +esac diff --git a/distro/dns-scripts/resolvconf_file-dns-updown.sh b/distro/dns-scripts/resolvconf_file-dns-updown.sh new file mode 100644 index 0000000..c469490 --- /dev/null +++ b/distro/dns-scripts/resolvconf_file-dns-updown.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# +# Simple OpenVPN up/down script for modifying /etc/resolv.conf +# (C) Copyright 2024 OpenVPN Inc <sa...@op...> +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Example env from openvpn (most are not applied): +# +# dev tun0 +# script-type dns-up +# dns_search_domain_1 mycorp.in +# dns_search_domain_2 eu.mycorp.com +# dns_server_1_address_1 192.168.99.254 +# dns_server_1_address_2 fd00::99:53 +# dns_server_1_port_1 53 +# dns_server_1_port_2 53 +# dns_server_1_resolve_domain_1 mycorp.in +# dns_server_1_resolve_domain_2 eu.mycorp.com +# dns_server_1_dnssec true +# dns_server_1_transport DoH +# dns_server_1_sni dns.mycorp.in +# + +set -e +u + +only_standard_server_ports() { + i=1 + while true; do + eval addr=\"\$dns_server_${n}_address_${i}\" + [ -n "$addr" ] || return 0 + + eval port=\"\$dns_server_${n}_port_${i}\" + [ -z "$port" -o "$port" = "53" ] || return 1 + + i=$(expr $i + 1) + done +} + +conf=/etc/resolv.conf +test -e "$conf" || exit 1 +case "${script_type}" in +dns-up) + n=1 + while :; do + eval addr=\"\$dns_server_${n}_address_1\" + [ -n "$addr" ] || { + echo "setting DNS failed, no compatible server profile" + exit 1 + } + + # Skip server profiles which require DNSSEC, + # secure transport or use a custom port + eval dnssec=\"\$dns_server_${n}_dnssec\" + eval transport=\"\$dns_server_${n}_transport\" + [ -z "$transport" -o "$transport" = "plain" ] \ + && [ -z "$dnssec" -o "$dnssec" = "no" ] \ + && only_standard_server_ports && break + + n=$(expr $n + 1) + done + + eval addr1=\"\$dns_server_${n}_address_1\" + eval addr2=\"\$dns_server_${n}_address_2\" + eval addr3=\"\$dns_server_${n}_address_3\" + text="### openvpn ${dev} begin ###\n" + text="${text}nameserver $addr1\n" + test -z "$addr2" || text="${text}nameserver $addr2\n" + test -z "$addr3" || text="${text}nameserver $addr3\n" + + test -z "$dns_search_domain_1" || { + for i in $(seq 1 6); do + eval domains=\"$domains\$dns_search_domain_${i} \" || break + done + text="${text}search $domains\n" + } + text="${text}### openvpn ${dev} end ###" + + sed -i "1i${text}" "$conf" + ;; +dns-down) + sed -i "/### openvpn ${dev} begin ###/,/### openvpn ${dev} end ###/d" "$conf" + ;; +esac diff --git a/distro/dns-scripts/systemd-dns-updown.sh b/distro/dns-scripts/systemd-dns-updown.sh new file mode 100644 index 0000000..69bbebf --- /dev/null +++ b/distro/dns-scripts/systemd-dns-updown.sh @@ -0,0 +1,194 @@ +#!/bin/bash +# +# dns-updown - add/remove openvpn provided DNS information +# +# Copyright (C) 2024 OpenVPN Inc <sa...@op...> +# +# SPDX-License-Identifier: GPL-2.0 +# +# Add/remove openvpn DNS settings from the env into/from +# the system. Supported backends in this order: +# +# * systemd-resolved +# * resolvconf +# +# Example env from openvpn (not all are always applied): +# +# dev tun0 +# script-type dns-up +# dns_search_domain_1 mycorp.in +# dns_search_domain_2 eu.mycorp.com +# dns_server_1_address_1 192.168.99.254 +# dns_server_1_address_2 fd00::99:53 +# dns_server_1_port_1 53 +# dns_server_1_port_2 53 +# dns_server_1_resolve_domain_1 mycorp.in +# dns_server_1_resolve_domain_2 eu.mycorp.com +# dns_server_1_dnssec true +# dns_server_1_transport DoH +# dns_server_1_sni dns.mycorp.in +# + +function do_resolved_servers { + local sni="" + local transport_var=dns_server_${n}_transport + local sni_var=dns_server_${n}_sni + [ "${!transport_var}" = "DoT" ] && sni="#${!sni_var}" + + local i=1 + local addrs="" + while :; do + local addr_var=dns_server_${n}_address_${i} + local addr="${!addr_var}" + [ -n "$addr" ] || break + + local port_var=dns_server_${n}_port_${i} + if [ -n "${!port_var}" ]; then + if [[ "$addr" =~ : ]]; then + addr="[$addr]" + fi + addrs+="${addr}:${!port_var}${sni} " + else + addrs+="${addr}${sni} " + fi + i=$((i+1)) + done + + resolvectl dns "$dev" $addrs +} + +function do_resolved_domains { + local list="" + for domain_var in ${!dns_search_domain_*}; do + list+="${!domain_var} " + done + local domain_var=dns_server_${n}_resolve_domain_1 + if [ -z "${!domain_var}" ]; then + resolvectl default-route "$dev" true + list+="~." + else + resolvectl default-route "$dev" false + local i=1 + while :; do + domain_var=dns_server_${n}_resolve_domain_${i} + [ -n "${!domain_var}" ] || break + # Add as split domain (~ prefix), if it doesn't already exist + [[ "$list" =~ (^| )"${!domain_var}"( |$) ]] \ + || list+="~${!domain_var} " + i=$((i+1)) + done + fi + + resolvectl domain "$dev" $list +} + +function do_resolved_dnssec { + local dnssec_var=dns_server_${n}_dnssec + if [ "${!dnssec_var}" = "optional" ]; then + resolvectl dnssec "$dev" allow-downgrade + elif [ "${!dnssec_var}" = "yes" ]; then + resolvectl dnssec "$dev" true + else + resolvectl dnssec "$dev" false + fi +} + +function do_resolved_dnsovertls { + local transport_var=dns_server_${n}_transport + if [ "${!transport_var}" = "DoT" ]; then + resolvectl dnsovertls "$dev" true + else + resolvectl dnsovertls "$dev" false + fi +} + +function do_resolved { + [[ "$(readlink /etc/resolv.conf)" =~ systemd ]] || return 1 + + n=1 + while :; do + local addr_var=dns_server_${n}_address_1 + [ -n "${!addr_var}" ] || { + echo "setting DNS failed, no compatible server profile" + return 1 + } + + # Skip server profiles which require DNS-over-HTTPS + local transport_var=dns_server_${n}_transport + [ -n "${!transport_var}" -a "${!transport_var}" = "DoH" ] || break + + n=$((n+1)) + done + + if [ "$script_type" = "dns-up" ]; then + echo "setting DNS using resolvectl" + do_resolved_servers + do_resolved_domains + do_resolved_dnssec + do_resolved_dnsovertls + else + echo "unsetting DNS using resolvectl" + resolvectl revert "$dev" + fi + + return 0 +} + +function only_standard_server_ports { + local i=1 + while :; do + local addr_var=dns_server_${n}_address_${i} + [ -n "${!addr_var}" ] || return 0 + + local port_var=dns_server_${n}_port_${i} + [ -z "${!port_var}" -o "${!port_var}" = "53" ] || return 1 + + i=$((i+1)) + done +} + +function do_resolvconf { + [ -x /sbin/resolvconf ] || return 1 + + n=1 + while :; do + local server_addr_var=dns_server_${n}_address_1 + [ -n "${!server_addr_var}" ] || { + echo "setting DNS failed, no compatible server profile" + return 1 + } + + # Skip server profiles which require DNSSEC, + # secure transport or use a custom port + local dnssec_var=dns_server_${n}_dnssec + local transport_var=dns_server_${n}_transport + [ -z "${!transport_var}" -o "${!transport_var}" = "plain" ] \ + && [ -z "${!dnssec_var}" -o "${!dnssec_var}" = "no" ] \ + && only_standard_server_ports && break + + n=$((n+1)) + done + + if [ "$script_type" = "dns-up" ]; then + echo "setting DNS using resolvconf" + local domains="" + for domain_var in ${!dns_search_domain_*}; do + domains+="${!domain_var} " + done + { + local maxns=3 + for addr_var in ${!dns_server_1_address_*}; do + [ $((maxns--)) -gt 0 ] || break + echo "nameserver ${!addr_var}" + done + [ -z "$domains" ] || echo "search $domains" + } | /sbin/resolvconf -a "$dev" + else + echo "unsetting DNS using resolvconf" + /sbin/resolvconf -d "$dev" + fi + + return 0 +} + +do_resolved || do_resolvconf diff --git a/doc/man-sections/script-options.rst b/doc/man-sections/script-options.rst index 0d1f9ae..8285122 100644 --- a/doc/man-sections/script-options.rst +++ b/doc/man-sections/script-options.rst @@ -8,9 +8,13 @@ Script Order of Execution ------------------------- +#. ``--dns-updown`` + + Executed after TCP/UDP socket bind and TUN/TAP open, before ``--up``. + #. ``--up`` - Executed after TCP/UDP socket bind and TUN/TAP open. + Executed after TCP/UDP socket bind and TUN/TAP open, after ``--dns-updown``. #. ``--tls-verify`` @@ -38,9 +42,13 @@ Executed in ``--mode server`` mode on client instance shutdown. +#. ``--dns-updown`` + + Executed before TCP/UDP and TUN/TAP close, before ``--down``. + #. ``--down`` - Executed after TCP/UDP and TUN/TAP close. + Executed after TCP/UDP and TUN/TAP close, after ``--dns-updown``. #. ``--learn-address`` @@ -173,7 +181,7 @@ client-crresponse cmd OpenVPN will write the response of the client into a temporary file. - The filename will be passed as an argument to ``cmd``, and the file will be + The filename will be passed as an argument to ``cmd``, and the file will automatically deleted by OpenVPN after the script returns. The response is passed as is from the client. The script needs to check @@ -235,6 +243,25 @@ The ``--client-disconnect`` command is not passed any extra arguments (only those arguments specified in cmd, if any). +--dns-updown cmd + Run command ``cmd``, instead of the default DNS command that comes with + openvpn. If ``cmd`` is ``disable`` no command is executed to set ``--dns`` + options. If you write your own command, please make sure to ignore ``--dns`` + server profiles that cannot be applied. Port, DNSSEC and secure transport + settings need to be adhered to. If split DNS is not possible a full redirect + can be used as a fallback. If not all of the server addresses or search domains + can be configured, apply them in the order they are listed in. + + Note that ``--dns-updown`` is not supported on Windows. DNS will + always be set by the service there. + + Note that DNS-related ``--dhcp-option``\ s will not be handled by this hook. + If any ``--dns server`` option is present, DNS-related ``--dhcp-option``\ s will + be ignored. If an ``--up`` script is defined, foreign_option env vars will be + generated from ``--dns`` options and passed to the script. The ``--dns-updown`` + command is not run if a ``--up`` script is defined. Both is done for backward + compatibility. + --down cmd Run command ``cmd`` after TUN/TAP device close (post ``--user`` UID change and/or ``--chroot`` ). ``cmd`` consists of a path to script (or @@ -661,7 +688,7 @@ names). Set prior to ``--up`` or ``--down`` script execution. :code:`dns_*` - The ``--dns`` configuration options will be made available to script + The ``--dns`` configuration options will be made available to ``--dns-updown`` execution through this set of environment variables. Variables appear only if the corresponding option has a value assigned. For the semantics of each individual variable, please refer to the documentation for ``--dns``. diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index 37af683..6664aae 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -30,7 +30,8 @@ $(OPTIONAL_LZ4_CFLAGS) \ $(OPTIONAL_PKCS11_HELPER_CFLAGS) \ $(OPTIONAL_INOTIFY_CFLAGS) \ - -DPLUGIN_LIBDIR=\"${plugindir}\" + -DPLUGIN_LIBDIR=\"${plugindir}\" \ + -DDNS_UPDOWN_PATH=\"${scriptdir}/dns-updown\" if WIN32 # we want unicode entry point but not the macro diff --git a/src/openvpn/dns.c b/src/openvpn/dns.c index b6e524f..d3b9274 100644 --- a/src/openvpn/dns.c +++ b/src/openvpn/dns.c @@ -30,6 +30,7 @@ #include "dns.h" #include "socket.h" #include "options.h" +#include "run_command.h" #ifdef _WIN32 #include "win32.h" @@ -262,6 +263,8 @@ clone.search_domains = clone_dns_domains(o->search_domains, gc); clone.servers = clone_dns_servers(o->servers, gc); clone.servers_prepull = clone_dns_servers(o->servers_prepull, gc); + clone.updown = o->updown; + clone.user_defined_updown = o->user_defined_updown; return clone; } @@ -548,6 +551,54 @@ send_msg_iservice(o->msg_channel, &nrpt, sizeof(nrpt), &ack, "DNS"); } +#else /* ifdef _WIN32 */ + +static void +updown_env_set(bool up, const struct dns_options *o, const struct tuntap *tt, struct env_set *es) +{ + setenv_str(es, "dev", tt->actual_name); + setenv_str(es, "script_type", up ? "dns-up" : "dns-down"); + setenv_dns_options(o, es); +} + +static int +do_run_up_down_command(bool up, const struct dns_options *o, const struct tuntap *tt) +{ + struct gc_arena gc = gc_new(); + struct argv argv = argv_new(); + struct env_set *es = env_set_create(&gc); + + updown_env_set(up, o, tt, es); + + argv_printf(&argv, "%s", o->updown); + argv_msg(M_INFO, &argv); + int res; + if (o->user_defined_updown) + { + res = openvpn_run_script(&argv, es, S_EXITCODE, "dns updown"); + } + else + { + res = openvpn_execve_check(&argv, es, S_EXITCODE, "WARNING: Failed running dns updown"); + } + argv_free(&argv); + gc_free(&gc); + return res; +} + +static void +run_up_down_command(bool up, struct options *o, const struct tuntap *tt) +{ + if (!o->dns_options.updown) + { + return; + } + + int status; + status = do_run_up_down_command(up, &o->dns_options, tt); + msg(M_INFO, "dns %s command exited with status %d", up ? "up" : "down", status); +} + #endif /* _WIN32 */ void @@ -666,5 +717,7 @@ #ifdef _WIN32 run_up_down_service(up, o, tt); +#else + run_up_down_command(up, o, tt); #endif /* ifdef _WIN32 */ } diff --git a/src/openvpn/dns.h b/src/openvpn/dns.h index f24e30b..e34e07d 100644 --- a/src/openvpn/dns.h +++ b/src/openvpn/dns.h @@ -73,6 +73,8 @@ struct dns_server *servers_prepull; struct dns_server *servers; struct gc_arena gc; + const char *updown; + bool user_defined_updown; }; /** diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 67ef55b..e8ec6570 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -526,10 +526,11 @@ " address <addr[:port]> [addr[:port] ...] : server addresses 4/6\n" " resolve-domains <domain> [domain ...] : split domains\n" " dnssec <yes|no|optional> : option to use DNSSEC\n" - " type <DoH|DoT> : query server over HTTPS / TLS\n" + " transport <DoH|DoT> : query server over HTTPS / TLS\n" " sni <domain> : DNS server name indication\n" "--dns search-domains <domain> [domain ...]:\n" " Add domains to DNS domain search list\n" + "--dns-updown cmd|disable : Run cmd as user defined dns config command or disable it\n" "--auth-retry t : How to handle auth failures. Set t to\n" " none (default), interact, or nointeract.\n" "--static-challenge t e [<scrv1|concat>]: Enable static challenge/response protocol using\n" @@ -921,6 +922,10 @@ #ifndef ENABLE_DCO o->disable_dco = true; #endif /* ENABLE_DCO */ + +#ifdef ENABLE_DNS_UPDOWN + o->dns_options.updown = DNS_UPDOWN_PATH; +#endif /* ENABLE_DNS_UPDOWN */ } void @@ -8082,6 +8087,30 @@ to->ip_win32_defined = true; } #endif /* ifdef _WIN32 */ + else if (streq(p[0], "dns-updown") && p[1]) + { + VERIFY_PERMISSION(OPT_P_SCRIPT); + if (!no_more_than_n_args(msglevel, p, 2, NM_QUOTE_HINT)) + { + goto err; + } +#ifdef ENABLE_DNS_UPDOWN + if (streq(p[1], "disable")) + { + options->dns_options.updown = NULL; + } + else + { + if (options->dns_options.user_defined_updown == false) + { + /* Unset the default command to prevent warnings */ + options->dns_options.updown = NULL; + } + set_user_script(options, &options->dns_options.updown, p[1], p[0], false); + options->dns_options.user_defined_updown = true; + } +#endif /* ENABLE_DNS_UPDOWN */ + } else if (streq(p[0], "dns") && p[1]) { VERIFY_PERMISSION(OPT_P_DHCPDNS); -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/838?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: Ifbe4ffb44d3bfcaa50adb38cacb3436fcdc71b10 Gerrit-Change-Number: 838 Gerrit-PatchSet: 16 Gerrit-Owner: d12fk <he...@op...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: cron2 <ge...@gr...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-MessageType: newpatchset |
| From: d12fk (C. Review) <ge...@op...> - 2025-03-19 22:46:06 |
Attention is currently required from: plaisthos, stipa. d12fk has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/837?usp=email ) Change subject: win: implement --dns option support with NRPT ...................................................................... Patch Set 13: (2 comments) File src/openvpnserv/interactive.c: http://gerrit.openvpn.net/c/openvpn/+/837/comment/b96c8df4_7beb686c : PS13, Line 2602: free(wide_domains); > If domains is not set, we're freeing stack-allocated wide_domains (PWSTR wide_domains = L".\0";). Done http://gerrit.openvpn.net/c/openvpn/+/837/comment/8eed4464_e3ea759f : PS13, Line 2782: DWORD iid_err = InterfaceIdString(msg->iface.name, iid, sizeof(iid)); > We pass sizeof(iid) as count to wcsncpy and it should be count of wide chars, not the buffer size. […] Done -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/837?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I576e74f3276362606e9cbd50bb5adbebaaf209cc Gerrit-Change-Number: 837 Gerrit-PatchSet: 13 Gerrit-Owner: d12fk <he...@op...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Wed, 19 Mar 2025 22:45:41 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: stipa <lst...@gm...> Gerrit-MessageType: comment |
| From: d12fk (C. Review) <ge...@op...> - 2025-03-19 22:45:45 |
Attention is currently required from: cron2, flichtenheld, plaisthos. d12fk has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/838?usp=email ) Change subject: dns: apply settings via script on unixoid systems ...................................................................... Patch Set 15: (3 comments) File CMakeLists.txt: http://gerrit.openvpn.net/c/openvpn/+/838/comment/46a4965c_d67b6a1d : PS15, Line 582: > does this need some sort of magic to enable `-DENABLE_DNS_UPDOWN`? Now you can disable the feature with ccmake or `-DENABLE_DNS_UPDOWN=ON`, just like the others. File src/openvpn/options.c: http://gerrit.openvpn.net/c/openvpn/+/838/comment/929d0d87_38955934 : PS15, Line 926: #ifdef ENABLE_DNS_SCRIPT > should that be ENABLE_DNS_UPDOWN? Done http://gerrit.openvpn.net/c/openvpn/+/838/comment/b0363c3c_449e72d0 : PS15, Line 8227: #ifdef ENABLE_DNS_SCRIPT > same here Done -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/838?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: Ifbe4ffb44d3bfcaa50adb38cacb3436fcdc71b10 Gerrit-Change-Number: 838 Gerrit-PatchSet: 15 Gerrit-Owner: d12fk <he...@op...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: cron2 <ge...@gr...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Comment-Date: Wed, 19 Mar 2025 22:45:28 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: cron2 <ge...@gr...> Gerrit-MessageType: comment |
| From: cron2 (C. Review) <ge...@op...> - 2025-03-19 17:48:31 |
cron2 has submitted this change. ( http://gerrit.openvpn.net/c/openvpn/+/854?usp=email ) Change subject: Post tchar.h removal cleanup ...................................................................... Post tchar.h removal cleanup Remove some unused defines. Change-Id: Ib3a166ead912beb2a591105c84d96d342664c05f Signed-off-by: Frank Lichtenheld <fr...@li...> Acked-by: Gert Doering <ge...@gr...> Message-Id: <202...@gr...> URL: https://www.mail-archive.com/ope...@li.../msg31172.html Signed-off-by: Gert Doering <ge...@gr...> --- M src/openvpnserv/service.h M src/tapctl/basic.h 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/openvpnserv/service.h b/src/openvpnserv/service.h index b2b706b..7112f26 100644 --- a/src/openvpnserv/service.h +++ b/src/openvpnserv/service.h @@ -24,11 +24,6 @@ #ifndef _SERVICE_H #define _SERVICE_H -/* We do not support non-unicode builds */ -#ifndef UNICODE -#define UNICODE -#endif - #ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/src/tapctl/basic.h b/src/tapctl/basic.h index ca5c6d4..49a3cf6 100644 --- a/src/tapctl/basic.h +++ b/src/tapctl/basic.h @@ -22,13 +22,11 @@ #ifndef BASIC_H #define BASIC_H -#ifdef _UNICODE -#define PRIsLPWSTR "ls" -#define PRIsLPOLESTR "ls" -#else -#define PRIsLPWSTR "s" -#define PRIsLPOLESTR "ls" +/* We do not support non-unicode builds */ +#ifndef UNICODE +#define UNICODE #endif + #define PRIXGUID "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}" #define PRIGUID_PARAM(g) \ (g).Data1, (g).Data2, (g).Data3, (g).Data4[0], (g).Data4[1], (g).Data4[2], (g).Data4[3], (g).Data4[4], (g).Data4[5], (g).Data4[6], (g).Data4[7] -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/854?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: Ib3a166ead912beb2a591105c84d96d342664c05f Gerrit-Change-Number: 854 Gerrit-PatchSet: 5 Gerrit-Owner: flichtenheld <fr...@li...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-MessageType: merged |
| From: cron2 (C. Review) <ge...@op...> - 2025-03-19 17:48:30 |
cron2 has uploaded a new patch set (#5) to the change originally created by flichtenheld. ( http://gerrit.openvpn.net/c/openvpn/+/854?usp=email ) The following approvals got outdated and were removed: Code-Review+2 by cron2 Change subject: Post tchar.h removal cleanup ...................................................................... Post tchar.h removal cleanup Remove some unused defines. Change-Id: Ib3a166ead912beb2a591105c84d96d342664c05f Signed-off-by: Frank Lichtenheld <fr...@li...> Acked-by: Gert Doering <ge...@gr...> Message-Id: <202...@gr...> URL: https://www.mail-archive.com/ope...@li.../msg31172.html Signed-off-by: Gert Doering <ge...@gr...> --- M src/openvpnserv/service.h M src/tapctl/basic.h 2 files changed, 4 insertions(+), 11 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/54/854/5 diff --git a/src/openvpnserv/service.h b/src/openvpnserv/service.h index b2b706b..7112f26 100644 --- a/src/openvpnserv/service.h +++ b/src/openvpnserv/service.h @@ -24,11 +24,6 @@ #ifndef _SERVICE_H #define _SERVICE_H -/* We do not support non-unicode builds */ -#ifndef UNICODE -#define UNICODE -#endif - #ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/src/tapctl/basic.h b/src/tapctl/basic.h index ca5c6d4..49a3cf6 100644 --- a/src/tapctl/basic.h +++ b/src/tapctl/basic.h @@ -22,13 +22,11 @@ #ifndef BASIC_H #define BASIC_H -#ifdef _UNICODE -#define PRIsLPWSTR "ls" -#define PRIsLPOLESTR "ls" -#else -#define PRIsLPWSTR "s" -#define PRIsLPOLESTR "ls" +/* We do not support non-unicode builds */ +#ifndef UNICODE +#define UNICODE #endif + #define PRIXGUID "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}" #define PRIGUID_PARAM(g) \ (g).Data1, (g).Data2, (g).Data3, (g).Data4[0], (g).Data4[1], (g).Data4[2], (g).Data4[3], (g).Data4[4], (g).Data4[5], (g).Data4[6], (g).Data4[7] -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/854?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: Ib3a166ead912beb2a591105c84d96d342664c05f Gerrit-Change-Number: 854 Gerrit-PatchSet: 5 Gerrit-Owner: flichtenheld <fr...@li...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-MessageType: newpatchset |
| From: Gert D. <ge...@gr...> - 2025-03-19 17:48:15 |
"Clean up the rest" - it looks a bit confusing at first, why the UNICODE stuff is removed from service.h - but that's just because "everything!" includes ../tapctl/basic.h, including service.h Your patch has been applied to the master branch. commit 6bb20fa8bebc29d8b3103662ffba4904d03e852d Author: Frank Lichtenheld Date: Wed Mar 19 15:22:24 2025 +0100 Post tchar.h removal cleanup Signed-off-by: Frank Lichtenheld <fr...@li...> Acked-by: Gert Doering <ge...@gr...> Message-Id: <202...@gr...> URL: https://www.mail-archive.com/ope...@li.../msg31172.html Signed-off-by: Gert Doering <ge...@gr...> -- kind regards, Gert Doering |
| From: flichtenheld (C. Review) <ge...@op...> - 2025-03-19 16:48:05 |
Attention is currently required from: plaisthos, stipa. Hello plaisthos, stipa, I'd like you to reexamine a change. Please visit http://gerrit.openvpn.net/c/openvpn/+/854?usp=email to look at the new patch set (#4). The following approvals got outdated and were removed: Code-Review+2 by stipa The change is no longer submittable: Code-Review and checks~ChecksSubmitRule are unsatisfied now. Change subject: Post tchar.h removal cleanup ...................................................................... Post tchar.h removal cleanup Remove some unused defines. Change-Id: Ib3a166ead912beb2a591105c84d96d342664c05f Signed-off-by: Frank Lichtenheld <fr...@li...> --- M src/openvpnserv/service.h M src/tapctl/basic.h 2 files changed, 4 insertions(+), 11 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/54/854/4 diff --git a/src/openvpnserv/service.h b/src/openvpnserv/service.h index b2b706b..7112f26 100644 --- a/src/openvpnserv/service.h +++ b/src/openvpnserv/service.h @@ -24,11 +24,6 @@ #ifndef _SERVICE_H #define _SERVICE_H -/* We do not support non-unicode builds */ -#ifndef UNICODE -#define UNICODE -#endif - #ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/src/tapctl/basic.h b/src/tapctl/basic.h index ca5c6d4..49a3cf6 100644 --- a/src/tapctl/basic.h +++ b/src/tapctl/basic.h @@ -22,13 +22,11 @@ #ifndef BASIC_H #define BASIC_H -#ifdef _UNICODE -#define PRIsLPWSTR "ls" -#define PRIsLPOLESTR "ls" -#else -#define PRIsLPWSTR "s" -#define PRIsLPOLESTR "ls" +/* We do not support non-unicode builds */ +#ifndef UNICODE +#define UNICODE #endif + #define PRIXGUID "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}" #define PRIGUID_PARAM(g) \ (g).Data1, (g).Data2, (g).Data3, (g).Data4[0], (g).Data4[1], (g).Data4[2], (g).Data4[3], (g).Data4[4], (g).Data4[5], (g).Data4[6], (g).Data4[7] -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/854?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: Ib3a166ead912beb2a591105c84d96d342664c05f Gerrit-Change-Number: 854 Gerrit-PatchSet: 4 Gerrit-Owner: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-MessageType: newpatchset |
| From: flichtenheld (C. Review) <ge...@op...> - 2025-03-19 16:15:37 |
Attention is currently required from: plaisthos. flichtenheld has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/830?usp=email ) Change subject: Remove uncrustify config and scripts, switch GHA ...................................................................... Set Ready For Review -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/830?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I15d4946800cbfaead67a73450ff3b12193814e54 Gerrit-Change-Number: 830 Gerrit-PatchSet: 3 Gerrit-Owner: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Comment-Date: Wed, 19 Mar 2025 14:31:40 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: No Gerrit-MessageType: comment |
| From: flichtenheld (C. Review) <ge...@op...> - 2025-03-19 16:07:20 |
flichtenheld has abandoned this change. ( http://gerrit.openvpn.net/c/openvpn/+/852?usp=email ) Change subject: dev-tools/text-removal.sh: Script to remove usage of tchar.h ...................................................................... Abandoned Not actually required to commit script to remove it immediately afterwards. It will remain documented in Gerrit and on the list. -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/852?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I4879f983ed6cc035cd6ad8d571e00eb14f9ffdc1 Gerrit-Change-Number: 852 Gerrit-PatchSet: 2 Gerrit-Owner: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-MessageType: abandon |
| From: stipa (C. Review) <ge...@op...> - 2025-03-19 15:40:14 |
Attention is currently required from: d12fk, plaisthos. stipa has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/837?usp=email ) Change subject: win: implement --dns option support with NRPT ...................................................................... Patch Set 13: Code-Review-2 (2 comments) File src/openvpnserv/interactive.c: http://gerrit.openvpn.net/c/openvpn/+/837/comment/527430f0_4471f7d6 : PS13, Line 2602: free(wide_domains); If domains is not set, we're freeing stack-allocated wide_domains (PWSTR wide_domains = L".\0";). http://gerrit.openvpn.net/c/openvpn/+/837/comment/828a5a05_4a81dca3 : PS13, Line 2782: DWORD iid_err = InterfaceIdString(msg->iface.name, iid, sizeof(iid)); We pass sizeof(iid) as count to wcsncpy and it should be count of wide chars, not the buffer size. This causes crash. -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/837?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I576e74f3276362606e9cbd50bb5adbebaaf209cc Gerrit-Change-Number: 837 Gerrit-PatchSet: 13 Gerrit-Owner: d12fk <he...@op...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: d12fk <he...@op...> Gerrit-Comment-Date: Wed, 19 Mar 2025 13:58:01 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: Yes Gerrit-MessageType: comment |
| From: flichtenheld (C. Review) <ge...@op...> - 2025-03-19 15:32:49 |
Attention is currently required from: plaisthos. Hello plaisthos, I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/829?usp=email to review the following change. Change subject: Disable clang-format for some code parts ...................................................................... Disable clang-format for some code parts These do not come out better with clang-format, so leave them be. Change-Id: I4dd0c44982955f16ec4a3f167d4e6f3e9b4dbc11 Signed-off-by: Frank Lichtenheld <fr...@li...> --- M src/openvpn/ssl_common.h M src/tapctl/main.c 2 files changed, 4 insertions(+), 1 deletion(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/29/829/3 diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 4e54001..97c5041 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -75,6 +75,7 @@ * * @{ */ +/* clang-format off */ #define S_ERROR (-2) /**< Error state. */ #define S_ERROR_PRE (-1) /**< Error state but try to send out alerts * before killing the keystore and moving @@ -102,7 +103,7 @@ #define S_GENERATED_KEYS 7 /**< The data channel keys have been generated * The TLS session is fully authenticated * when reaching this state. */ - +/* clang-format on */ /* Note that earlier versions also had a S_OP_NORMAL state that was * virtually identical with S_ACTIVE and the code still assumes everything * >= S_ACTIVE to be fully operational */ diff --git a/src/tapctl/main.c b/src/tapctl/main.c index 551a8e6..d27da6b 100644 --- a/src/tapctl/main.c +++ b/src/tapctl/main.c @@ -37,6 +37,7 @@ #endif +/* clang-format off */ const WCHAR title_string[] = _L(PACKAGE_NAME) L" " _L(PACKAGE_VERSION) ; @@ -111,6 +112,7 @@ L"\n" L"tapctl delete <adapter GUID | adapter name>\n" ; +/* clang-format on */ /** -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/829?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I4dd0c44982955f16ec4a3f167d4e6f3e9b4dbc11 Gerrit-Change-Number: 829 Gerrit-PatchSet: 3 Gerrit-Owner: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-MessageType: newchange |
| From: flichtenheld (C. Review) <ge...@op...> - 2025-03-19 15:28:16 |
Attention is currently required from: plaisthos. Hello plaisthos, I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/790?usp=email to review the following change. Change subject: Define a .clang-format file for the project ...................................................................... Define a .clang-format file for the project Each of these statements has been reviewed but not all of them are obvious. Also add a pre-commit config to easily check the formatting. Change-Id: I40f6af10c5ee2f5aed4185d783fc622a2e3c19ff Signed-off-by: Frank Lichtenheld <fr...@li...> --- A .clang-format A .pre-commit-config.yaml 2 files changed, 54 insertions(+), 0 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/90/790/9 diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..0960fe7 --- /dev/null +++ b/.clang-format @@ -0,0 +1,46 @@ +--- +BasedOnStyle: Mozilla +AccessModifierOffset: '-4' +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: false + AcrossComments: true +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: + Kind: Always + OverEmptyLines: 1 +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Allman +BreakBeforeTernaryOperators: true +BreakStringLiterals: false +ColumnLimit: '100' +ContinuationIndentWidth: '4' +DerivePointerAlignment: false +IndentCaseLabels: true +IndentGotoLabels: false +IndentWidth: '4' +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +Language: Cpp +MaxEmptyLinesToKeep: '2' +PointerAlignment: Right +ReflowComments: true +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpacesBeforeTrailingComments: '2' +SpacesInParens: Never +TabWidth: '4' +TypeNames: [DWORD] +UseTab: Never +WhitespaceSensitiveMacros: [_STRINGIFY] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0f09a06 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,8 @@ +repos: + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: 'v19.1.4' + hooks: + - id: clang-format + files: \.[ch]$ + # preserve upstream formatting + exclude: ^(src/compat/compat-lz4\.[ch]|src/openvpn/ovpn_dco_(linux|win)\.h)$ -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/790?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I40f6af10c5ee2f5aed4185d783fc622a2e3c19ff Gerrit-Change-Number: 790 Gerrit-PatchSet: 9 Gerrit-Owner: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-MessageType: newchange |
| From: Gert D. <ge...@gr...> - 2025-03-19 15:25:51 |
From: Frank Lichtenheld <fr...@li...> Remove some unused defines. Change-Id: Ib3a166ead912beb2a591105c84d96d342664c05f Signed-off-by: Frank Lichtenheld <fr...@li...> Acked-by: Gert Doering <ge...@gr...> --- This change was reviewed on Gerrit and approved by at least one developer. I request to merge it to master. Gerrit URL: https://gerrit.openvpn.net/c/openvpn/+/854 This mail reflects revision 4 of this Change. Acked-by according to Gerrit (reflected above): Gert Doering <ge...@gr...> diff --git a/src/openvpnserv/service.h b/src/openvpnserv/service.h index b2b706b..7112f26 100644 --- a/src/openvpnserv/service.h +++ b/src/openvpnserv/service.h @@ -24,11 +24,6 @@ #ifndef _SERVICE_H #define _SERVICE_H -/* We do not support non-unicode builds */ -#ifndef UNICODE -#define UNICODE -#endif - #ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/src/tapctl/basic.h b/src/tapctl/basic.h index ca5c6d4..49a3cf6 100644 --- a/src/tapctl/basic.h +++ b/src/tapctl/basic.h @@ -22,13 +22,11 @@ #ifndef BASIC_H #define BASIC_H -#ifdef _UNICODE -#define PRIsLPWSTR "ls" -#define PRIsLPOLESTR "ls" -#else -#define PRIsLPWSTR "s" -#define PRIsLPOLESTR "ls" +/* We do not support non-unicode builds */ +#ifndef UNICODE +#define UNICODE #endif + #define PRIXGUID "{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}" #define PRIGUID_PARAM(g) \ (g).Data1, (g).Data2, (g).Data3, (g).Data4[0], (g).Data4[1], (g).Data4[2], (g).Data4[3], (g).Data4[4], (g).Data4[5], (g).Data4[6], (g).Data4[7] |
| From: cron2 (C. Review) <ge...@op...> - 2025-03-19 15:21:24 |
Attention is currently required from: flichtenheld, plaisthos, stipa. cron2 has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/854?usp=email ) Change subject: Post tchar.h removal cleanup ...................................................................... Patch Set 4: Code-Review+2 -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/854?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: Ib3a166ead912beb2a591105c84d96d342664c05f Gerrit-Change-Number: 854 Gerrit-PatchSet: 4 Gerrit-Owner: flichtenheld <fr...@li...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-Reviewer: stipa <lst...@gm...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: stipa <lst...@gm...> Gerrit-Comment-Date: Wed, 19 Mar 2025 14:22:11 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment |
| From: flichtenheld (C. Review) <ge...@op...> - 2025-03-19 15:19:44 |
Attention is currently required from: plaisthos. Hello plaisthos, I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/792?usp=email to review the following change. Change subject: Manually reformat some long trailing comments ...................................................................... Manually reformat some long trailing comments When trying to reformat the code with a formatter that actually checks line-lengths, these never come out nice otherwise. Change-Id: I7f0ba2261b61f6eed511cbd8bb2e880d774d1365 Signed-off-by: Frank Lichtenheld <fr...@li...> --- M sample/sample-plugins/simple/base64.c M src/openvpn/comp.h M src/openvpn/errlevel.h M src/openvpn/fragment.h M src/openvpn/init.c M src/openvpn/manage.c M src/openvpn/misc.h M src/openvpn/options.c M src/openvpn/ssl_common.h 9 files changed, 152 insertions(+), 134 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/92/792/12 diff --git a/sample/sample-plugins/simple/base64.c b/sample/sample-plugins/simple/base64.c index 291f9e1..3a09eb5 100644 --- a/sample/sample-plugins/simple/base64.c +++ b/sample/sample-plugins/simple/base64.c @@ -31,10 +31,14 @@ #define PLUGIN_NAME "base64.c" /* Exported plug-in v3 API functions */ -plugin_log_t ovpn_log = NULL; /**< Pointer to the OpenVPN log function. See plugin_log() */ -plugin_vlog_t ovpn_vlog = NULL; /**< Pointer to the OpenVPN vlog function. See plugin_vlog() */ -plugin_base64_encode_t ovpn_base64_encode = NULL; /**< Pointer to the openvpn_base64_encode () function */ -plugin_base64_decode_t ovpn_base64_decode = NULL; /**< Pointer to the openvpn_base64_decode () function */ +/** Pointer to the OpenVPN log function. See plugin_log() */ +plugin_log_t ovpn_log = NULL; +/** Pointer to the OpenVPN vlog function. See plugin_vlog() */ +plugin_vlog_t ovpn_vlog = NULL; +/** Pointer to the openvpn_base64_encode () function */ +plugin_base64_encode_t ovpn_base64_encode = NULL; +/** Pointer to the openvpn_base64_decode () function */ +plugin_base64_decode_t ovpn_base64_decode = NULL; /** * Search the environment pointer for a specific env var name diff --git a/src/openvpn/comp.h b/src/openvpn/comp.h index 7eed331..f9f9598 100644 --- a/src/openvpn/comp.h +++ b/src/openvpn/comp.h @@ -36,20 +36,27 @@ #define COMP_F_ADAPTIVE (1<<0) / * COMP_ALG_LZO only * / #define COMP_F_ALLOW_COMPRESS (1<<1) / * not only incoming is compressed but also outgoing * / */ -#define COMP_F_SWAP (1<<2) /* initial command byte is swapped with last byte in buffer to preserve payload alignment */ -#define COMP_F_ADVERTISE_STUBS_ONLY (1<<3) /* tell server that we only support compression stubs */ -#define COMP_F_ALLOW_STUB_ONLY (1<<4) /* Only accept stub compression, even with COMP_F_ADVERTISE_STUBS_ONLY - * we still accept other compressions to be pushed */ -#define COMP_F_MIGRATE (1<<5) /* push stub-v2 or comp-lzo no when we see a client with comp-lzo in occ */ -#define COMP_F_ALLOW_ASYM (1<<6) /* Compression was explicitly set to allow asymetric compression */ -#define COMP_F_ALLOW_NOCOMP_ONLY (1<<7) /* Do not allow compression framing (breaks DCO) */ +/** initial command byte is swapped with last byte in buffer to preserve payload alignment */ +#define COMP_F_SWAP (1<<2) +/** tell server that we only support compression stubs */ +#define COMP_F_ADVERTISE_STUBS_ONLY (1<<3) +/** Only accept stub compression, even with COMP_F_ADVERTISE_STUBS_ONLY + * we still accept other compressions to be pushed */ +#define COMP_F_ALLOW_STUB_ONLY (1<<4) +/** push stub-v2 or comp-lzo no when we see a client with comp-lzo in occ */ +#define COMP_F_MIGRATE (1<<5) +/** Compression was explicitly set to allow asymetric compression */ +#define COMP_F_ALLOW_ASYM (1<<6) +/** Do not allow compression framing (breaks DCO) */ +#define COMP_F_ALLOW_NOCOMP_ONLY (1<<7) /* algorithms */ #define COMP_ALG_UNDEF 0 -#define COMP_ALG_STUB 1 /* support compression command byte and framing without actual compression */ -#define COMP_ALG_LZO 2 /* LZO algorithm */ -#define COMP_ALG_SNAPPY 3 /* Snappy algorithm (no longer supported) */ -#define COMP_ALG_LZ4 4 /* LZ4 algorithm */ +/** support compression command byte and framing without actual compression */ +#define COMP_ALG_STUB 1 +#define COMP_ALG_LZO 2 /**< LZO algorithm */ +#define COMP_ALG_SNAPPY 3 /**< Snappy algorithm (no longer supported) */ +#define COMP_ALG_LZ4 4 /**< LZ4 algorithm */ /* algorithm v2 */ @@ -106,7 +113,8 @@ #define LZO_COMPRESS_BYTE 0x66 #define LZ4_COMPRESS_BYTE 0x69 #define NO_COMPRESS_BYTE 0xFA -#define NO_COMPRESS_BYTE_SWAP 0xFB /* to maintain payload alignment, replace this byte with last byte of packet */ +/** to maintain payload alignment, replace this byte with last byte of packet */ +#define NO_COMPRESS_BYTE_SWAP 0xFB /* V2 on wire code */ #define COMP_ALGV2_INDICATOR_BYTE 0x50 diff --git a/src/openvpn/errlevel.h b/src/openvpn/errlevel.h index bf2e54e..1f54ed8 100644 --- a/src/openvpn/errlevel.h +++ b/src/openvpn/errlevel.h @@ -143,7 +143,7 @@ #define D_PACKET_TRUNC_DEBUG LOGLEV(7, 70, M_DEBUG) /* PACKET_TRUNCATION_CHECK verbose */ #define D_PING LOGLEV(7, 70, M_DEBUG) /* PING send/receive messages */ #define D_PS_PROXY_DEBUG LOGLEV(7, 70, M_DEBUG) /* port share proxy debug */ -#define D_TLS_KEYSELECT LOGLEV(7, 70, M_DEBUG) /* show information on key selection for data channel */ +#define D_TLS_KEYSELECT LOGLEV(7, 70, M_DEBUG) /* show key selection for data channel */ #define D_ARGV_PARSE_CMD LOGLEV(7, 70, M_DEBUG) /* show parse_line() errors in argv_parse_cmd */ #define D_CRYPTO_DEBUG LOGLEV(7, 70, M_DEBUG) /* show detailed info from crypto.c routines */ #define D_PID_DEBUG LOGLEV(7, 70, M_DEBUG) /* show packet-id debugging info */ @@ -153,7 +153,7 @@ #define D_VLAN_DEBUG LOGLEV(7, 74, M_DEBUG) /* show VLAN tagging/untagging debug info */ -#define D_HANDSHAKE_VERBOSE LOGLEV(8, 70, M_DEBUG) /* show detailed description of each handshake */ +#define D_HANDSHAKE_VERBOSE LOGLEV(8, 70, M_DEBUG) /* show detailed description of handshake */ #define D_TLS_DEBUG_MED LOGLEV(8, 70, M_DEBUG) /* limited info from tls_session routines */ #define D_INTERVAL LOGLEV(8, 70, M_DEBUG) /* show interval.h debugging info */ #define D_SCHEDULER LOGLEV(8, 70, M_DEBUG) /* show scheduler debugging info */ @@ -168,7 +168,7 @@ #define D_PACKET_CONTENT LOGLEV(9, 70, M_DEBUG) /* show before/after encryption packet content */ #define D_TLS_NO_SEND_KEY LOGLEV(9, 70, M_DEBUG) /* show when no data channel send-key exists */ #define D_PID_PERSIST_DEBUG LOGLEV(9, 70, M_DEBUG) /* show packet-id persist debugging info */ -#define D_LINK_RW_VERBOSE LOGLEV(9, 70, M_DEBUG) /* show link reads/writes with greater verbosity */ +#define D_LINK_RW_VERBOSE LOGLEV(9, 70, M_DEBUG) /* increase link reads/writes verbosity */ #define D_STREAM_DEBUG LOGLEV(9, 70, M_DEBUG) /* show TCP stream debug info */ #define D_WIN32_IO LOGLEV(9, 70, M_DEBUG) /* win32 I/O debugging info */ #define D_PKCS11_DEBUG LOGLEV(9, 70, M_DEBUG) /* show PKCS#11 debugging */ diff --git a/src/openvpn/fragment.h b/src/openvpn/fragment.h index 3cd0ee7..88f6053 100644 --- a/src/openvpn/fragment.h +++ b/src/openvpn/fragment.h @@ -92,25 +92,28 @@ * List of fragment structures for reassembling multiple incoming packets * concurrently. */ -struct fragment_list { - int seq_id; /**< Highest fragmentation sequence ID of - * the packets currently being - * reassembled. */ - int index; /**< Index of the packet being reassembled - * with the highest fragmentation - * sequence ID into the \c - * fragment_list.fragments array. */ +struct fragment_list +{ + /** Highest fragmentation sequence ID of + * the packets currently being + * reassembled. */ + int seq_id; + /** Index of the packet being reassembled + * with the highest fragmentation + * sequence ID into the \c + * fragment_list.fragments array. */ + int index; -/** Array of reassembly structures, each can contain one whole packet. - * - * The fragmentation sequence IDs of the packets being reassembled in - * this array are linearly increasing. \c - * fragment_list.fragments[fragment_list.index] has an ID of \c - * fragment_list.seq_id. This means that one of these \c fragment_list - * structures can at any one time contain at most packets with the - * fragmentation sequence IDs in the range \c fragment_list.seq_id \c - - * \c N_FRAG_BUF \c + \c 1 to \c fragment_list.seq_id, inclusive. - */ + /** Array of reassembly structures, each can contain one whole packet. + * + * The fragmentation sequence IDs of the packets being reassembled in + * this array are linearly increasing. \c + * fragment_list.fragments[fragment_list.index] has an ID of \c + * fragment_list.seq_id. This means that one of these \c fragment_list + * structures can at any one time contain at most packets with the + * fragmentation sequence IDs in the range \c fragment_list.seq_id \c - + * \c N_FRAG_BUF \c + \c 1 to \c fragment_list.seq_id, inclusive. + */ struct fragment fragments[N_FRAG_BUF]; }; @@ -149,9 +152,7 @@ * the remote OpenVPN peer can determine * which parts belong to which original * packet. */ -#define MAX_FRAG_PKT_SIZE 65536 - /**< (Not used) Maximum packet size before - * fragmenting. */ +#define MAX_FRAG_PKT_SIZE 65536 /**< (Not used) Maximum packet size before fragmenting. */ int outgoing_frag_size; /**< Size in bytes of each part to be * sent, except for the last part which * may be smaller. @@ -183,45 +184,37 @@ /**************************************************************************/ /** @name Fragment header * @todo Add description of %fragment header format. - *//** @{ *//*************************************/ + */ +/** @{ */ /*************************************/ typedef uint32_t fragment_header_type; -/**< Fragmentation information is stored in - * a 32-bit packet header. */ +/**< Fragmentation information is stored in a 32-bit packet header. */ #define hton_fragment_header_type(x) htonl(x) -/**< Convert a fragment_header_type from - * host to network order. */ +/**< Convert a fragment_header_type from host to network order. */ #define ntoh_fragment_header_type(x) ntohl(x) -/**< Convert a \c fragment_header_type - * from network to host order. */ +/**< Convert a \c fragment_header_type from network to host order. */ -#define FRAG_TYPE_MASK 0x00000003 -/**< Bit mask for %fragment type info. */ -#define FRAG_TYPE_SHIFT 0 /**< Bit shift for %fragment type info. */ +#define FRAG_TYPE_MASK 0x00000003 /**< Bit mask for %fragment type info. */ +#define FRAG_TYPE_SHIFT 0 /**< Bit shift for %fragment type info. */ -#define FRAG_WHOLE 0 /**< Fragment type indicating packet is - * whole. */ -#define FRAG_YES_NOTLAST 1 /**< Fragment type indicating packet is - * part of a fragmented packet, but not - * the last part in the sequence. */ -#define FRAG_YES_LAST 2 /**< Fragment type indicating packet is - * the last part in the sequence of - * parts. */ -#define FRAG_TEST 3 /**< Fragment type not implemented yet. - * In the future might be used as a - * control packet for establishing MTU - * size. */ +#define FRAG_WHOLE 0 /**< Fragment type indicating packet is whole. */ +#define FRAG_YES_NOTLAST 1 +/**< Fragment type indicating packet is part of a fragmented packet, but not + * the last part in the sequence. */ +#define FRAG_YES_LAST 2 +/**< Fragment type indicating packet is the last part in the sequence of parts. */ +#define FRAG_TEST 3 +/**< Fragment type not implemented yet. + * In the future might be used as a control packet for establishing MTU size. */ -#define FRAG_SEQ_ID_MASK 0x000000ff -/**< Bit mask for %fragment sequence ID. */ -#define FRAG_SEQ_ID_SHIFT 2 /**< Bit shift for %fragment sequence ID. */ +#define FRAG_SEQ_ID_MASK 0x000000ff /**< Bit mask for %fragment sequence ID. */ +#define FRAG_SEQ_ID_SHIFT 2 /**< Bit shift for %fragment sequence ID. */ -#define FRAG_ID_MASK 0x0000001f -/**< Bit mask for %fragment ID. */ -#define FRAG_ID_SHIFT 10 -/**< Bit shift for %fragment ID. */ +#define FRAG_ID_MASK 0x0000001f /**< Bit mask for %fragment ID. */ +#define FRAG_ID_SHIFT 10 /**< Bit shift for %fragment ID. */ + /* * FRAG_SIZE 14 bits @@ -232,12 +225,10 @@ * max_frag_size is only sent over the wire if FRAG_LAST is set. Otherwise it is assumed * to be the actual %fragment size received. */ -#define FRAG_SIZE_MASK 0x00003fff -/**< Bit mask for %fragment size. */ -#define FRAG_SIZE_SHIFT 15 -/**< Bit shift for %fragment size. */ -#define FRAG_SIZE_ROUND_SHIFT 2 /**< Bit shift for %fragment size rounding. */ -#define FRAG_SIZE_ROUND_MASK ((1 << FRAG_SIZE_ROUND_SHIFT) - 1) +#define FRAG_SIZE_MASK 0x00003fff /**< Bit mask for %fragment size. */ +#define FRAG_SIZE_SHIFT 15 /**< Bit shift for %fragment size. */ +#define FRAG_SIZE_ROUND_SHIFT 2 /**< Bit shift for %fragment size rounding. */ +#define FRAG_SIZE_ROUND_MASK ((1 << FRAG_SIZE_ROUND_SHIFT) - 1) /**< Bit mask for %fragment size rounding. */ /* @@ -245,10 +236,8 @@ * * IF FRAG_WHOLE or FRAG_YES_NOTLAST, these 16 bits are available (not currently used) */ -#define FRAG_EXTRA_MASK 0x0000ffff -/**< Bit mask for extra bits. */ -#define FRAG_EXTRA_SHIFT 15 -/**< Bit shift for extra bits. */ +#define FRAG_EXTRA_MASK 0x0000ffff /**< Bit mask for extra bits. */ +#define FRAG_EXTRA_SHIFT 15 /**< Bit shift for extra bits. */ /** @} name Fragment header *//********************************************/ diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 1be205b..bbaf63f 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -983,7 +983,8 @@ { if (!options->dev && options->dev_node) { - char *dev_node = string_alloc(options->dev_node, NULL); /* POSIX basename() implementations may modify its arguments */ + /* POSIX basename() implementations may modify its arguments */ + char *dev_node = string_alloc(options->dev_node, NULL); options->dev = basename(dev_node); } } @@ -2566,12 +2567,14 @@ } else { - initialization_sequence_completed(c, error_flags); /* client/p2p --route-delay undefined */ + /* client/p2p --route-delay undefined */ + initialization_sequence_completed(c, error_flags); } } else if (c->options.mode == MODE_POINT_TO_POINT) { - initialization_sequence_completed(c, error_flags); /* client/p2p restart with --persist-tun */ + /* client/p2p restart with --persist-tun */ + initialization_sequence_completed(c, error_flags); } tls_print_deferred_options_results(c); diff --git a/src/openvpn/manage.c b/src/openvpn/manage.c index 0e73942..567b6ea 100644 --- a/src/openvpn/manage.c +++ b/src/openvpn/manage.c @@ -3447,7 +3447,8 @@ const bool standalone_disabled_save = man->persist.standalone_disabled; time_t expire = 0; - man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */ + /* This is so M_CLIENT messages will be correctly passed through msg() */ + man->persist.standalone_disabled = false; /* set expire time */ update_time(); @@ -3510,7 +3511,8 @@ unsigned int up_query_mode = 0; const char *sc = NULL; ret = true; - man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */ + /* This is so M_CLIENT messages will be correctly passed through msg() */ + man->persist.standalone_disabled = false; man->persist.special_state_msg = NULL; CLEAR(man->connection.up_query); @@ -3634,7 +3636,8 @@ if (man_standalone_ok(man)) { - man->persist.standalone_disabled = false; /* This is so M_CLIENT messages will be correctly passed through msg() */ + /* This is so M_CLIENT messages will be correctly passed through msg() */ + man->persist.standalone_disabled = false; man->persist.special_state_msg = NULL; *state = EKS_SOLICIT; diff --git a/src/openvpn/misc.h b/src/openvpn/misc.h index 3c46c02..5f55a060 100644 --- a/src/openvpn/misc.h +++ b/src/openvpn/misc.h @@ -114,12 +114,14 @@ #define GET_USER_PASS_NEED_STR (1<<5) #define GET_USER_PASS_PREVIOUS_CREDS_FAILED (1<<6) -#define GET_USER_PASS_DYNAMIC_CHALLENGE (1<<7) /* CRV1 protocol -- dynamic challenge */ -#define GET_USER_PASS_STATIC_CHALLENGE (1<<8) /* SCRV1 protocol -- static challenge */ -#define GET_USER_PASS_STATIC_CHALLENGE_ECHO (1<<9) /* SCRV1 protocol -- echo response */ +#define GET_USER_PASS_DYNAMIC_CHALLENGE (1<<7) /**< CRV1 protocol -- dynamic challenge */ +#define GET_USER_PASS_STATIC_CHALLENGE (1<<8) /**< SCRV1 protocol -- static challenge */ +#define GET_USER_PASS_STATIC_CHALLENGE_ECHO (1<<9) /**< SCRV1 protocol -- echo response */ -#define GET_USER_PASS_INLINE_CREDS (1<<10) /* indicates that auth_file is actually inline creds */ -#define GET_USER_PASS_STATIC_CHALLENGE_CONCAT (1<<11) /* indicates password and response should be concatenated */ +/** indicates that auth_file is actually inline creds */ +#define GET_USER_PASS_INLINE_CREDS (1<<10) +/** indicates password and response should be concatenated */ +#define GET_USER_PASS_STATIC_CHALLENGE_CONCAT (1<<11) /** * Retrieves the user credentials from various sources depending on the flags. diff --git a/src/openvpn/options.c b/src/openvpn/options.c index 67ef55b..aa672ca 100644 --- a/src/openvpn/options.c +++ b/src/openvpn/options.c @@ -853,7 +853,8 @@ o->tuntap_options.ip_win32_type = IPW32_SET_DHCP_MASQ; #endif o->tuntap_options.dhcp_lease_time = 31536000; /* one year */ - o->tuntap_options.dhcp_masq_offset = 0; /* use network address as internal DHCP server address */ + /* use network address as internal DHCP server address */ + o->tuntap_options.dhcp_masq_offset = 0; o->route_method = ROUTE_METHOD_ADAPTIVE; o->block_outside_dns = false; o->windows_driver = WINDOWS_DRIVER_UNSPECIFIED; diff --git a/src/openvpn/ssl_common.h b/src/openvpn/ssl_common.h index 68a6ce6..4e54001 100644 --- a/src/openvpn/ssl_common.h +++ b/src/openvpn/ssl_common.h @@ -75,10 +75,10 @@ * * @{ */ -#define S_ERROR (-2) /**< Error state. */ -#define S_ERROR_PRE (-1) /**< Error state but try to send out alerts - * before killing the keystore and moving - * it to S_ERROR */ +#define S_ERROR (-2) /**< Error state. */ +#define S_ERROR_PRE (-1) /**< Error state but try to send out alerts + * before killing the keystore and moving + * it to S_ERROR */ #define S_UNDEF 0 /**< Undefined state, used after a \c * key_state is cleaned up. */ #define S_INITIAL 1 /**< Initial \c key_state state after @@ -564,18 +564,22 @@ * tls_session reaches S_ACTIVE, this state machine moves to CAS_PENDING (server) * or CAS_CONNECT_DONE (client/p2p) as clients skip the stages associated with * connect scripts/plugins */ -enum multi_status { +enum multi_status +{ CAS_NOT_CONNECTED, - CAS_WAITING_AUTH, /**< Initial TLS connection established but deferred auth is not yet finished */ - CAS_PENDING, /**< Options import (Connect script/plugin, ccd,...) */ - CAS_PENDING_DEFERRED, /**< Waiting on an async option import handler */ - CAS_PENDING_DEFERRED_PARTIAL, /**< at least handler succeeded but another is still pending */ - CAS_FAILED, /**< Option import failed or explicitly denied the client */ - CAS_WAITING_OPTIONS_IMPORT, /**< client with pull or p2p waiting for first time options import */ - CAS_RECONNECT_PENDING, /**< session has already successful established (CAS_CONNECT_DONE) - * but has a reconnect and needs to redo some initialisation, this state is - * similar CAS_WAITING_OPTIONS_IMPORT but skips a few things. The normal connection - * skips this step. */ + CAS_WAITING_AUTH, /**< Initial TLS connection established but deferred auth is not yet finished + */ + CAS_PENDING, /**< Options import (Connect script/plugin, ccd,...) */ + CAS_PENDING_DEFERRED, /**< Waiting on an async option import handler */ + CAS_PENDING_DEFERRED_PARTIAL, /**< at least handler succeeded but another is still pending */ + CAS_FAILED, /**< Option import failed or explicitly denied the client */ + CAS_WAITING_OPTIONS_IMPORT, /**< client with pull or p2p waiting for first time options import + */ + /** session has already successful established (CAS_CONNECT_DONE) but has a + * reconnect and needs to redo some initialisation, this state is similar + * CAS_WAITING_OPTIONS_IMPORT but skips a few things. The normal connection + * skips this step. */ + CAS_RECONNECT_PENDING, CAS_CONNECT_DONE, }; @@ -623,8 +627,9 @@ int n_hard_errors; /* errors due to TLS negotiation failure */ int n_soft_errors; /* errors due to unrecognized or failed-to-authenticate incoming packets */ - /* - * Our locked common name, username, and cert hashes (cannot change during the life of this tls_multi object) + /** + * Our locked common name, username, and cert hashes + * (cannot change during the life of this tls_multi object) */ char *locked_cn; @@ -639,43 +644,46 @@ struct cert_hash_set *locked_cert_hash_set; - /** Time of last when we updated the cached state of + /** + * Time of last when we updated the cached state of * tls_authentication_status deferred files */ time_t tas_cache_last_update; /** The number of times we updated the cache */ unsigned int tas_cache_num_updates; - /* - * An error message to send to client on AUTH_FAILED - */ + /** An error message to send to client on AUTH_FAILED */ char *client_reason; - /* + /** * A multi-line string of general-purpose info received from peer * over control channel. */ char *peer_info; - char *auth_token; /**< If server sends a generated auth-token, - * this is the token to use for future - * user/pass authentications in this session. - */ - char *auth_token_initial; - /**< The first auth-token we sent to a client. We use this to remember + /** + * If server sends a generated auth-token, + * this is the token to use for future + * user/pass authentications in this session. + */ + char *auth_token; + /** + * The first auth-token we sent to a client. We use this to remember * the session ID and initial timestamp when generating new auth-token. */ -#define AUTH_TOKEN_HMAC_OK (1<<0) - /**< Auth-token sent from client has valid hmac */ -#define AUTH_TOKEN_EXPIRED (1<<1) - /**< Auth-token sent from client has expired */ -#define AUTH_TOKEN_VALID_EMPTYUSER (1<<2) - /**< - * Auth-token is only valid for an empty username - * and not the username actually supplied from the client - * - * OpenVPN 3 clients sometimes wipes or replaces the username with a - * username hint from their config. - */ + char *auth_token_initial; + +/** Auth-token sent from client has valid hmac */ +#define AUTH_TOKEN_HMAC_OK (1 << 0) +/** Auth-token sent from client has expired */ +#define AUTH_TOKEN_EXPIRED (1 << 1) +/** + * Auth-token is only valid for an empty username + * and not the username actually supplied from the client + * + * OpenVPN 3 clients sometimes wipes or replaces the username with a + * username hint from their config. + */ +#define AUTH_TOKEN_VALID_EMPTYUSER (1 << 2) /* For P_DATA_V2 */ uint32_t peer_id; @@ -687,10 +695,10 @@ /* * Our session objects. */ + /** Array of \c tls_session objects + * representing control channel + * sessions with the remote peer. */ struct tls_session session[TM_SIZE]; - /**< Array of \c tls_session objects - * representing control channel - * sessions with the remote peer. */ /* Only used when DCO is used to remember how many keys we installed * for this session */ -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/792?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I7f0ba2261b61f6eed511cbd8bb2e880d774d1365 Gerrit-Change-Number: 792 Gerrit-PatchSet: 12 Gerrit-Owner: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-MessageType: newchange |
| From: cron2 (C. Review) <ge...@op...> - 2025-03-19 15:09:20 |
Attention is currently required from: d12fk, flichtenheld, plaisthos. cron2 has posted comments on this change. ( http://gerrit.openvpn.net/c/openvpn/+/838?usp=email ) Change subject: dns: apply settings via script on unixoid systems ...................................................................... Patch Set 15: Code-Review-1 (4 comments) Patchset: PS15: Overall it looks good, but I'm afraid the change from ENABLE_DNS_SCRIPT to ENABLE_DNS_UPDOWN broke options.c File CMakeLists.txt: http://gerrit.openvpn.net/c/openvpn/+/838/comment/4b69602a_38fa67d4 : PS15, Line 582: does this need some sort of magic to enable `-DENABLE_DNS_UPDOWN`? File src/openvpn/options.c: http://gerrit.openvpn.net/c/openvpn/+/838/comment/f473ebac_d6d18ad0 : PS15, Line 926: #ifdef ENABLE_DNS_SCRIPT should that be ENABLE_DNS_UPDOWN? http://gerrit.openvpn.net/c/openvpn/+/838/comment/de0f1212_6e2780f2 : PS15, Line 8227: #ifdef ENABLE_DNS_SCRIPT same here -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/838?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: Ifbe4ffb44d3bfcaa50adb38cacb3436fcdc71b10 Gerrit-Change-Number: 838 Gerrit-PatchSet: 15 Gerrit-Owner: d12fk <he...@op...> Gerrit-Reviewer: cron2 <ge...@gr...> Gerrit-Reviewer: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-Attention: flichtenheld <fr...@li...> Gerrit-Attention: d12fk <he...@op...> Gerrit-Comment-Date: Wed, 19 Mar 2025 14:41:16 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: Yes Gerrit-MessageType: comment |
| From: flichtenheld (C. Review) <ge...@op...> - 2025-03-19 15:03:28 |
Attention is currently required from: plaisthos. Hello plaisthos, I'd like you to do a code review. Please visit http://gerrit.openvpn.net/c/openvpn/+/830?usp=email to review the following change. Change subject: Remove uncrustify config and scripts, switch GHA ...................................................................... Remove uncrustify config and scripts, switch GHA Replaced with clang-format and pre-commit. Change-Id: I15d4946800cbfaead67a73450ff3b12193814e54 Signed-off-by: Frank Lichtenheld <fr...@li...> --- M .github/workflows/build.yaml D dev-tools/git-pre-commit-uncrustify.sh D dev-tools/reformat-all.sh D dev-tools/special-files.lst D dev-tools/uncrustify.conf 5 files changed, 12 insertions(+), 402 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/30/830/3 diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index b1af7ec..b33e0ce 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -5,35 +5,26 @@ pull_request: jobs: - checkuncrustify: - name: "Check code style with Uncrustify" - # Ubuntu 22.04 has uncrustify 0.72_f - runs-on: ubuntu-22.04 + clang-format: + name: Check code style with clang-format + runs-on: ubuntu-24.04 steps: - name: Install dependencies - run: sudo apt update && sudo apt install -y uncrustify + run: | + sudo apt update && sudo apt install -y python3-pip + pip3 install pre-commit - name: Checkout OpenVPN uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - path: openvpn - - name: Show uncrustify version - run: uncrustify --version - - name: Run uncrustify - run: ./dev-tools/reformat-all.sh - working-directory: openvpn + - name: Run clang-format + run: pre-commit run -a --show-diff-on-failure || true - name: Check for changes - run: git diff --output=uncrustify-changes.patch - working-directory: openvpn - - name: Show changes on standard output - run: git diff - working-directory: openvpn + run: git diff --output=format-changes.patch - uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: - name: uncrustify-changes.patch - path: 'openvpn/uncrustify-changes.patch' + name: format-changes.patch + path: format-changes.patch - name: Set job status - run: test ! -s uncrustify-changes.patch - working-directory: openvpn + run: test ! -s format-changes.patch android: strategy: diff --git a/dev-tools/git-pre-commit-uncrustify.sh b/dev-tools/git-pre-commit-uncrustify.sh deleted file mode 100755 index 9851c21..0000000 --- a/dev-tools/git-pre-commit-uncrustify.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2015, David Martin -# 2022, Heiko Hund -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -# git pre-commit hook that runs an Uncrustify stylecheck. -# Features: -# - abort commit when commit does not comply with the style guidelines -# - create a patch of the proposed style changes -# -# More info on Uncrustify: http://uncrustify.sourceforge.net/ - -# This file was taken from a set of unofficial pre-commit hooks available -# at https://github.com/ddddavidmartin/Pre-commit-hooks and modified to -# fit the openvpn project's needs - -# exit on error -set -e - - -# If called so, install this script as pre-commit hook -if [ "$1" = "install" ] ; then - TARGET="$(git rev-parse --git-path hooks)/pre-commit" - - if [ -e "$TARGET" ] ; then - printf "$TARGET file exists. Won't overwrite.\n" - printf "Aborting installation.\n" - exit 1 - fi - - read -p "Install as $TARGET? [y/N] " INPUT - [ "$INPUT" = "y" ] || exit 0 - cp "$0" "$TARGET" - chmod +x $TARGET - exit 0 -fi - -# check whether the given file matches any of the set extensions -matches_extension() { - local filename="$(basename -- "$1")" - local extension=".${filename##*.}" - local ext - - for ext in .c .h ; do [ "$ext" = "$extension" ] && return 0; done - - return 1 -} - -# necessary check for initial commit -if git rev-parse --verify HEAD >/dev/null 2>&1 ; then - against=HEAD -else - # Initial commit: diff against an empty tree object - against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 -fi - -UNCRUSTIFY=$(command -v uncrustify) -UNCRUST_CONFIG="$(git rev-parse --show-toplevel)/dev-tools/uncrustify.conf" - -# make sure the config file and executable are correctly set -if [ ! -f "$UNCRUST_CONFIG" ] ; then - printf "Error: uncrustify config file not found.\n" - printf "Expected to find it at $UNCRUST_CONFIG.\n" - printf "Aborting commit.\n" - exit 1 -fi - -if [ -z "$UNCRUSTIFY" ] ; then - printf "Error: uncrustify executable not found.\n" - printf "Is it installed and in your \$PATH?\n" - printf "Aborting commit.\n" - exit 1 -fi - -# create a filename to store our generated patch -patch=$(mktemp /tmp/ovpn-fmt-XXXXXX) -tmpout=$(mktemp /tmp/uncrustify-XXXXXX) - -# create one patch containing all changes to the files -# sed to remove quotes around the filename, if inserted by the system -# (done sometimes, if the filename contains special characters, like the quote itself) -git diff-index --cached --diff-filter=ACMR --name-only $against -- | \ -sed -e 's/^"\(.*\)"$/\1/' | \ -while read file -do - # ignore file if we do check for file extensions and the file - # does not match the extensions .c or .h - if ! matches_extension "$file"; then - continue; - fi - - # escape special characters in the target filename: - # phase 1 (characters escaped in the output diff): - # - '\': backslash needs to be escaped in the output diff - # - '"': quote needs to be escaped in the output diff if present inside - # of the filename, as it used to bracket the entire filename part - # phase 2 (characters escaped in the match replacement): - # - '\': backslash needs to be escaped again for sed itself - # (i.e. double escaping after phase 1) - # - '&': would expand to matched string - # - '|': used as sed split char instead of '/' - # printf %s particularly important if the filename contains the % character - file_escaped_target=$(printf "%s" "$file" | sed -e 's/[\"]/\\&/g' -e 's/[\&|]/\\&/g') - - # uncrustify our sourcefile, create a patch with diff and append it to our $patch - # The sed call is necessary to transform the patch from - # --- - timestamp - # +++ $tmpout timestamp - # to both lines working on the same file and having a a/ and b/ prefix. - # Else it can not be applied with 'git apply'. - git show ":$file" | "$UNCRUSTIFY" -q -l C -c "$UNCRUST_CONFIG" -o "$tmpout" - git show ":$file" | diff -u -- - "$tmpout" | \ - sed -e "1s|--- -|--- \"b/$file_escaped_target\"|" -e "2s|+++ $tmpout|+++ \"a/$file_escaped_target\"|" >> "$patch" -done - -rm -f "$tmpout" - -# if no patch has been generated all is ok, clean up the file stub and exit -if [ ! -s "$patch" ] ; then - rm -f "$patch" - exit 0 -fi - -# a patch has been created, notify the user and exit -printf "Formatting of some code does not follow the project guidelines.\n" - -if [ $(wc -l < $patch) -gt 80 ] ; then - printf "The file $patch contains the necessary fixes.\n" -else - printf "Here's the patch that fixes the formatting:\n\n" - cat $patch -fi - -printf "\nYou can apply these changes with:\n git apply $patch\n" -printf "(from the root directory of the repository) and then commit again.\n" -printf "\nAborting commit.\n" - -exit 1 diff --git a/dev-tools/reformat-all.sh b/dev-tools/reformat-all.sh deleted file mode 100755 index 42d7368..0000000 --- a/dev-tools/reformat-all.sh +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/sh -# reformat-all.sh - Reformat all git files in the checked out -# git branch using uncrustify. -# -# Copyright (C) 2016-2024 - David Sommerseth <da...@op...> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# - -tstamp="$(date +%Y%m%d-%H%M%S)" -files="$(pwd)/reformat-all_files-$tstamp.lst" -log="$(pwd)/reformat-all_log-$tstamp.txt" - -srcroot="$(git rev-parse --show-toplevel)" -cfg="$srcroot/dev-tools/uncrustify.conf" -specialfiles="$srcroot/dev-tools/special-files.lst" - -export gitfiles=0 -export procfiles=0 - -# Go to the root of the source tree -cd "$srcroot" - -{ - echo -n "** Starting $0: " - date - - # Find all C source/header files - git ls-files | grep -E ".*\.[ch](\.in$|$)" > "${files}.git" - - # Manage files which needs special treatment - awk -F\# '{gsub("\n| ", "", $1); print $1}' "$specialfiles" > "${files}.sp" - while read srcfile - do - res=$(grep "$srcfile" "${files}.sp" 2>/dev/null) - if [ $? -ne 0 ]; then - # If grep didn't find the file among special files, - # process it normally - echo "$srcfile" >> "$files" - else - mode=$(echo "$res" | cut -d: -f1) - case "$mode" in - E) - echo "** INFO ** Excluding '$srcfile'" - ;; - P) - echo "** INFO ** Pre-patching '$srcfile'" - patchfile="${srcroot}"/dev-tools/reformat-patches/before_$(echo "$srcfile" | tr "/" "_").patch - if [ -r "$patchfile" ]; then - git apply "$patchfile" - if [ $? -ne 0 ]; then - echo "** ERROR ** Failed to apply pre-patch file: $patchfile" - exit 2 - fi - else - echo "** WARN ** Pre-patch file for $srcfile is missing: $patchfile" - fi - echo "$srcfile" >> "${files}.postpatch" - echo "$srcfile" >> "$files" - ;; - *) - echo "** WARN ** Unknown mode '$mode' for file '$srcfile'" - ;; - esac - fi - done < "${files}.git" - rm -f "${files}.git" "${files}.sp" - - # Kick off uncrustify - echo - echo "** INFO ** Running: uncrustify -c $cfg --no-backup -l C -F $files" - uncrustify -c "$cfg" --no-backup -l C -F "$files" 2>&1 - res=$? - echo "** INFO ** Uncrustify completed (exit code $res)" -} | tee "${log}-1" # Log needs to be closed here, to be processed in next block - -{ - # Check the results - gitfiles=$(wc -l "$files" | cut -d\ -f1) - procfiles=$(grep "Parsing: " "${log}-1" | wc -l) - echo - echo "C source/header files checked into git: $gitfiles" - echo "Files processed by uncrustify: $procfiles" - echo - - # Post-Patch files modified after we uncrustify have adjusted them - if [ -r "${files}.postpatch" ]; then - while read srcfile; - do - patchfile="${srcroot}"/dev-tools/reformat-patches/after_$(echo "$srcfile" | tr "/" "_").patch - if [ -r "$patchfile" ]; then - echo "** INFO ** Post-patching '$srcfile'" - git apply "$patchfile" - if [ $? -ne 0 ]; then - echo "** WARN ** Failed to apply $patchfile" - fi - else - echo "** WARN ** Post-patch file for $srcfile is missing: $patchfile" - fi - done < "${files}.postpatch" - rm -f "${files}.postpatch" - fi -} | tee "${log}-2" # Log needs to be closed here, to be processed in next block - -cat "${log}-1" "${log}-2" > "$log" - -{ - ec=1 - echo - if [ "$gitfiles" -eq "$procfiles" ]; then - echo "Reformatting completed successfully" - ec=0 - else - last=$(tail -n1 "${log}-1") - echo "** ERROR ** Reformating failed to process all files." - echo " uncrustify exit code: $res" - echo " Last log line: $last" - echo - fi - rm -f "${log}-1" "${log}-2" -} | tee -a "$log" -rm -f "${files}" - -exit $ec diff --git a/dev-tools/special-files.lst b/dev-tools/special-files.lst deleted file mode 100644 index e5f2fc2..0000000 --- a/dev-tools/special-files.lst +++ /dev/null @@ -1,5 +0,0 @@ -E:doc/doxygen/doc_key_generation.h # @verbatim section gets mistreated, exclude it -E:src/compat/compat-lz4.c # Preserve LZ4 upstream formatting -E:src/compat/compat-lz4.h # Preserve LZ4 upstream formatting -E:src/openvpn/ovpn_dco_linux.h # Preserve ovpn-dco upstream formatting -E:src/openvpn/ovpn_dco_win.h # Preserve ovpn-dco-win upstream formatting diff --git a/dev-tools/uncrustify.conf b/dev-tools/uncrustify.conf deleted file mode 100644 index 325f310..0000000 --- a/dev-tools/uncrustify.conf +++ /dev/null @@ -1,79 +0,0 @@ -# Use Allman-style -indent_columns=4 -indent_braces=false -indent_else_if=false -indent_switch_case=4 -indent_label=1 -nl_if_brace=add -nl_brace_else=add -nl_elseif_brace=add -nl_else_brace=add -nl_else_if=remove -nl_for_brace=add -nl_while_brace=add -nl_switch_brace=add -nl_fdef_brace=add -nl_do_brace=add -sp_func_proto_paren=Remove -sp_func_def_paren=Remove -sp_func_call_paren=Remove -sp_sizeof_paren=Remove - -# No tabs, spaces only -indent_with_tabs=0 -align_with_tabs=false -cmt_convert_tab_to_spaces=true - -# Do not put spaces between the # and preprocessor statements -pp_space=remove - -# Various whitespace fiddling -sp_assign=add -sp_before_sparen=add -sp_inside_sparen=remove -sp_cond_colon=add -sp_cond_question=add -sp_bool=add -sp_else_brace=add -sp_brace_else=add -sp_after_comma=add -pos_arith=Lead -pos_bool=Lead -nl_func_type_name=add -nl_before_case=true -nl_assign_leave_one_liners=true -nl_enum_leave_one_liners=true -nl_brace_fparen=add -nl_max=4 -nl_after_func_proto=2 -nl_end_of_file_min=1 -nl_end_of_file=force - -# Always use scoping braces for conditionals -mod_full_brace_if=add -mod_full_brace_if_chain=false -mod_full_brace_while=add -mod_full_brace_for=add -mod_full_brace_do=add - -# Annotate #else and #endif statements -mod_add_long_ifdef_endif_comment=20 -mod_add_long_ifdef_else_comment=5 - -# Misc cleanup -mod_remove_extra_semicolon=true - -# leave blank at end of empty for() statements -sp_after_semi_for_empty=Add - -# Use C-style comments (/* .. */) -cmt_c_nl_end=true -cmt_star_cont=true -cmt_cpp_to_c=true - -# Use "char **a"-style pointer stars/dereferences -sp_before_ptr_star=Add -sp_between_ptr_star=Remove -sp_after_ptr_star=Remove -sp_before_byref=Add -sp_after_byref=Remove -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/830?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I15d4946800cbfaead67a73450ff3b12193814e54 Gerrit-Change-Number: 830 Gerrit-PatchSet: 3 Gerrit-Owner: flichtenheld <fr...@li...> Gerrit-Reviewer: plaisthos <arn...@rf...> Gerrit-CC: openvpn-devel <ope...@li...> Gerrit-Attention: plaisthos <arn...@rf...> Gerrit-MessageType: newchange |