mirror of
https://github.com/OpenVPN/openvpn.git
synced 2026-02-03 20:39:40 -05:00
The Great Reformatting - first phase
This is the first commit of the big reformatting task. This is performed by running the ./dev-tools/reformat-all.sh script. This is based upon the v3 reformat-all.sh/uncrustify.conf version which is now applied to git master. Signed-off-by: David Sommerseth <davids@openvpn.net>
This commit is contained in:
parent
2417d55c49
commit
81d882d530
204 changed files with 63438 additions and 55477 deletions
|
|
@ -118,20 +118,20 @@
|
|||
#define SIGUSR2 12
|
||||
#define SIGTERM 15
|
||||
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int8 int8_t;
|
||||
|
||||
#ifdef HAVE_CONFIG_MSVC_LOCAL_H
|
||||
#include <config-msvc-local.h>
|
||||
#endif
|
||||
|
||||
// Vista and above has implementation of inet_ntop / inet_pton
|
||||
/* Vista and above has implementation of inet_ntop / inet_pton */
|
||||
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
|
||||
#define HAVE_INET_NTOP
|
||||
#define HAVE_INET_PTON
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -30,17 +30,22 @@
|
|||
|
||||
typedef struct _CertData
|
||||
{
|
||||
CFArrayRef subject;
|
||||
CFArrayRef issuer;
|
||||
CFStringRef serial;
|
||||
CFStringRef md5, sha1;
|
||||
CFArrayRef subject;
|
||||
CFArrayRef issuer;
|
||||
CFStringRef serial;
|
||||
CFStringRef md5, sha1;
|
||||
} CertData, *CertDataRef;
|
||||
|
||||
CertDataRef createCertDataFromCertificate(SecCertificateRef certificate);
|
||||
|
||||
CertDataRef createCertDataFromString(const char *description);
|
||||
|
||||
void destroyCertData(CertDataRef pCertData);
|
||||
|
||||
bool certDataMatchesTemplate(CertDataRef pCertData, CertDataRef pTemplate);
|
||||
|
||||
void printCertData(CertDataRef pCertData);
|
||||
|
||||
SecIdentityRef findIdentity(CertDataRef pCertDataTemplate);
|
||||
|
||||
#endif
|
||||
#endif /* ifndef __cert_data_h__ */
|
||||
|
|
|
|||
|
|
@ -24,71 +24,78 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
#include "config.h"
|
||||
#include "syshead.h"
|
||||
#include "common.h"
|
||||
#include "buffer.h"
|
||||
#include "error.h"
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "syshead.h"
|
||||
#include "common.h"
|
||||
#include "buffer.h"
|
||||
#include "error.h"
|
||||
*/
|
||||
|
||||
#include "common_osx.h"
|
||||
#include <err.h>
|
||||
|
||||
void printCFString(CFStringRef str)
|
||||
void
|
||||
printCFString(CFStringRef str)
|
||||
{
|
||||
CFIndex bufferLength = CFStringGetLength(str) + 1;
|
||||
char *pBuffer = (char*)malloc(sizeof(char) * bufferLength);
|
||||
CFStringGetCString(str, pBuffer, bufferLength, kCFStringEncodingUTF8);
|
||||
warnx("%s\n", pBuffer);
|
||||
free(pBuffer);
|
||||
CFIndex bufferLength = CFStringGetLength(str) + 1;
|
||||
char *pBuffer = (char *)malloc(sizeof(char) * bufferLength);
|
||||
CFStringGetCString(str, pBuffer, bufferLength, kCFStringEncodingUTF8);
|
||||
warnx("%s\n", pBuffer);
|
||||
free(pBuffer);
|
||||
}
|
||||
|
||||
char* cfstringToCstr(CFStringRef str)
|
||||
char *
|
||||
cfstringToCstr(CFStringRef str)
|
||||
{
|
||||
CFIndex bufferLength = CFStringGetLength(str) + 1;
|
||||
char *pBuffer = (char*)malloc(sizeof(char) * bufferLength);
|
||||
CFStringGetCString(str, pBuffer, bufferLength, kCFStringEncodingUTF8);
|
||||
return pBuffer;
|
||||
CFIndex bufferLength = CFStringGetLength(str) + 1;
|
||||
char *pBuffer = (char *)malloc(sizeof(char) * bufferLength);
|
||||
CFStringGetCString(str, pBuffer, bufferLength, kCFStringEncodingUTF8);
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
void appendHexChar(CFMutableStringRef str, unsigned char halfByte)
|
||||
void
|
||||
appendHexChar(CFMutableStringRef str, unsigned char halfByte)
|
||||
{
|
||||
if (halfByte < 10)
|
||||
if (halfByte < 10)
|
||||
{
|
||||
CFStringAppendFormat (str, NULL, CFSTR("%d"), halfByte);
|
||||
CFStringAppendFormat(str, NULL, CFSTR("%d"), halfByte);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
char tmp[2] = {'A'+halfByte-10, 0};
|
||||
CFStringAppendCString(str, tmp, kCFStringEncodingUTF8);
|
||||
char tmp[2] = {'A'+halfByte-10, 0};
|
||||
CFStringAppendCString(str, tmp, kCFStringEncodingUTF8);
|
||||
}
|
||||
}
|
||||
|
||||
CFStringRef createHexString(unsigned char *pData, int length)
|
||||
CFStringRef
|
||||
createHexString(unsigned char *pData, int length)
|
||||
{
|
||||
unsigned char byte, low, high;
|
||||
int i;
|
||||
CFMutableStringRef str = CFStringCreateMutable(NULL, 0);
|
||||
unsigned char byte, low, high;
|
||||
int i;
|
||||
CFMutableStringRef str = CFStringCreateMutable(NULL, 0);
|
||||
|
||||
for(i = 0;i < length;i++)
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
byte = pData[i];
|
||||
low = byte & 0x0F;
|
||||
high = (byte >> 4);
|
||||
byte = pData[i];
|
||||
low = byte & 0x0F;
|
||||
high = (byte >> 4);
|
||||
|
||||
appendHexChar(str, high);
|
||||
appendHexChar(str, low);
|
||||
appendHexChar(str, high);
|
||||
appendHexChar(str, low);
|
||||
|
||||
if (i != (length - 1))
|
||||
CFStringAppendCString(str, " ", kCFStringEncodingUTF8);
|
||||
if (i != (length - 1))
|
||||
{
|
||||
CFStringAppendCString(str, " ", kCFStringEncodingUTF8);
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
return str;
|
||||
}
|
||||
|
||||
void printHex(unsigned char *pData, int length)
|
||||
void
|
||||
printHex(unsigned char *pData, int length)
|
||||
{
|
||||
CFStringRef hexStr = createHexString(pData, length);
|
||||
printCFString(hexStr);
|
||||
CFRelease(hexStr);
|
||||
CFStringRef hexStr = createHexString(pData, length);
|
||||
printCFString(hexStr);
|
||||
CFRelease(hexStr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,8 +29,11 @@
|
|||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
void printCFString(CFStringRef str);
|
||||
char* cfstringToCstr(CFStringRef str);
|
||||
|
||||
char *cfstringToCstr(CFStringRef str);
|
||||
|
||||
CFStringRef createHexString(unsigned char *pData, int length);
|
||||
|
||||
void printHex(unsigned char *pData, int length);
|
||||
|
||||
#endif //__Common_osx_h__
|
||||
#endif /*__Common_osx_h__ */
|
||||
|
|
|
|||
|
|
@ -31,45 +31,50 @@
|
|||
#include "crypto_osx.h"
|
||||
#include <err.h>
|
||||
|
||||
void printErrorMsg(const char *func, CFErrorRef error)
|
||||
void
|
||||
printErrorMsg(const char *func, CFErrorRef error)
|
||||
{
|
||||
CFStringRef desc = CFErrorCopyDescription(error);
|
||||
warnx("%s failed: %s", func, CFStringGetCStringPtr(desc, kCFStringEncodingUTF8));
|
||||
CFRelease(desc);
|
||||
CFStringRef desc = CFErrorCopyDescription(error);
|
||||
warnx("%s failed: %s", func, CFStringGetCStringPtr(desc, kCFStringEncodingUTF8));
|
||||
CFRelease(desc);
|
||||
}
|
||||
|
||||
void printErrorStatusMsg(const char *func, OSStatus status)
|
||||
void
|
||||
printErrorStatusMsg(const char *func, OSStatus status)
|
||||
{
|
||||
CFStringRef error;
|
||||
error = SecCopyErrorMessageString(status, NULL);
|
||||
if (error)
|
||||
CFStringRef error;
|
||||
error = SecCopyErrorMessageString(status, NULL);
|
||||
if (error)
|
||||
{
|
||||
warnx("%s failed: %s", func, CFStringGetCStringPtr(error, kCFStringEncodingUTF8));
|
||||
CFRelease(error);
|
||||
warnx("%s failed: %s", func, CFStringGetCStringPtr(error, kCFStringEncodingUTF8));
|
||||
CFRelease(error);
|
||||
}
|
||||
else
|
||||
{
|
||||
warnx("%s failed: %X", func, (int)status);
|
||||
}
|
||||
else
|
||||
warnx("%s failed: %X", func, (int)status);
|
||||
}
|
||||
|
||||
void signData(SecIdentityRef identity, const uint8_t *from, int flen, uint8_t *to, size_t *tlen)
|
||||
void
|
||||
signData(SecIdentityRef identity, const uint8_t *from, int flen, uint8_t *to, size_t *tlen)
|
||||
{
|
||||
SecKeyRef privateKey = NULL;
|
||||
OSStatus status;
|
||||
SecKeyRef privateKey = NULL;
|
||||
OSStatus status;
|
||||
|
||||
status = SecIdentityCopyPrivateKey(identity, &privateKey);
|
||||
if (status != noErr)
|
||||
status = SecIdentityCopyPrivateKey(identity, &privateKey);
|
||||
if (status != noErr)
|
||||
{
|
||||
printErrorStatusMsg("signData: SecIdentityCopyPrivateKey", status);
|
||||
*tlen = 0;
|
||||
return;
|
||||
printErrorStatusMsg("signData: SecIdentityCopyPrivateKey", status);
|
||||
*tlen = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
status = SecKeyRawSign(privateKey, kSecPaddingPKCS1, from, flen, to, tlen);
|
||||
CFRelease(privateKey);
|
||||
if (status != noErr)
|
||||
status = SecKeyRawSign(privateKey, kSecPaddingPKCS1, from, flen, to, tlen);
|
||||
CFRelease(privateKey);
|
||||
if (status != noErr)
|
||||
{
|
||||
printErrorStatusMsg("signData: SecKeyRawSign", status);
|
||||
*tlen = 0;
|
||||
return;
|
||||
printErrorStatusMsg("signData: SecKeyRawSign", status);
|
||||
*tlen = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,16 +29,17 @@
|
|||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
|
||||
extern OSStatus SecKeyRawSign (
|
||||
SecKeyRef key,
|
||||
SecPadding padding,
|
||||
const uint8_t *dataToSign,
|
||||
size_t dataToSignLen,
|
||||
uint8_t *sig,
|
||||
size_t *sigLen
|
||||
);
|
||||
extern OSStatus SecKeyRawSign(
|
||||
SecKeyRef key,
|
||||
SecPadding padding,
|
||||
const uint8_t *dataToSign,
|
||||
size_t dataToSignLen,
|
||||
uint8_t *sig,
|
||||
size_t *sigLen
|
||||
);
|
||||
|
||||
void signData(SecIdentityRef identity, const uint8_t *from, int flen, uint8_t *to, size_t *tlen);
|
||||
|
||||
void printErrorMsg(const char *func, CFErrorRef error);
|
||||
|
||||
#endif //__crypto_osx_h__
|
||||
#endif /*__crypto_osx_h__ */
|
||||
|
|
|
|||
|
|
@ -38,36 +38,44 @@
|
|||
#include "../../src/openvpn/base64.h"
|
||||
|
||||
|
||||
SecIdentityRef template_to_identity(const char *template)
|
||||
SecIdentityRef
|
||||
template_to_identity(const char *template)
|
||||
{
|
||||
SecIdentityRef identity;
|
||||
CertDataRef pCertDataTemplate = createCertDataFromString(template);
|
||||
if (pCertDataTemplate == NULL)
|
||||
{
|
||||
errx(1, "Bad certificate template");
|
||||
}
|
||||
identity = findIdentity(pCertDataTemplate);
|
||||
if (identity == NULL)
|
||||
{
|
||||
errx(1, "No such identify");
|
||||
}
|
||||
fprintf(stderr, "Identity found\n");
|
||||
destroyCertData(pCertDataTemplate);
|
||||
return identity;
|
||||
}
|
||||
|
||||
int connect_to_management_server(const char *ip, const char *port)
|
||||
int
|
||||
connect_to_management_server(const char *ip, const char *port)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_un addr_un;
|
||||
struct sockaddr *addr;
|
||||
size_t addr_len;
|
||||
|
||||
if (strcmp(port, "unix") == 0) {
|
||||
addr = (struct sockaddr*)&addr_un;
|
||||
if (strcmp(port, "unix") == 0)
|
||||
{
|
||||
addr = (struct sockaddr *)&addr_un;
|
||||
addr_len = sizeof(addr_un);
|
||||
|
||||
addr_un.sun_family = AF_UNIX;
|
||||
strncpy(addr_un.sun_path, ip, sizeof(addr_un.sun_path));
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
int rv;
|
||||
struct addrinfo *result;
|
||||
struct addrinfo hints;
|
||||
|
|
@ -78,9 +86,13 @@ int connect_to_management_server(const char *ip, const char *port)
|
|||
|
||||
rv = getaddrinfo(ip, port, &hints, &result);
|
||||
if (rv < 0)
|
||||
{
|
||||
errx(1, "getaddrinfo: %s", gai_strerror(rv));
|
||||
}
|
||||
if (result == NULL)
|
||||
{
|
||||
errx(1, "getaddrinfo returned 0 addressed");
|
||||
}
|
||||
|
||||
/* Use the first found address */
|
||||
fd = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||
|
|
@ -88,20 +100,26 @@ int connect_to_management_server(const char *ip, const char *port)
|
|||
addr_len = result->ai_addrlen;
|
||||
}
|
||||
if (fd < 0)
|
||||
{
|
||||
err(1, "socket");
|
||||
}
|
||||
|
||||
if (connect(fd, addr, addr_len) < 0)
|
||||
{
|
||||
err(1, "connect");
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int is_prefix(const char *s, const char *prefix)
|
||||
int
|
||||
is_prefix(const char *s, const char *prefix)
|
||||
{
|
||||
return strncmp(s, prefix, strlen(prefix)) == 0;
|
||||
}
|
||||
|
||||
void handle_rsasign(FILE *man_file, SecIdentityRef identity, const char *input)
|
||||
void
|
||||
handle_rsasign(FILE *man_file, SecIdentityRef identity, const char *input)
|
||||
{
|
||||
const char *input_b64 = strchr(input, ':') + 1;
|
||||
char *input_binary;
|
||||
|
|
@ -114,13 +132,17 @@ void handle_rsasign(FILE *man_file, SecIdentityRef identity, const char *input)
|
|||
input_binary = malloc(input_len);
|
||||
input_len = openvpn_base64_decode(input_b64, input_binary, input_len);
|
||||
if (input_len < 0)
|
||||
{
|
||||
errx(1, "openvpn_base64_decode: overflow");
|
||||
}
|
||||
|
||||
output_len = 1024;
|
||||
output_binary = malloc(output_len);
|
||||
signData(identity, (const uint8_t *)input_binary, input_len, (uint8_t *)output_binary, &output_len);
|
||||
if (output_len == 0)
|
||||
{
|
||||
errx(1, "handle_rsasign: failed to sign data");
|
||||
}
|
||||
|
||||
openvpn_base64_encode(output_binary, output_len, &output_b64);
|
||||
fprintf(man_file, "rsa-sig\n%s\nEND\n", output_b64);
|
||||
|
|
@ -131,7 +153,8 @@ void handle_rsasign(FILE *man_file, SecIdentityRef identity, const char *input)
|
|||
fprintf(stderr, "Handled RSA_SIGN command\n");
|
||||
}
|
||||
|
||||
void handle_needcertificate(FILE *man_file, SecIdentityRef identity)
|
||||
void
|
||||
handle_needcertificate(FILE *man_file, SecIdentityRef identity)
|
||||
{
|
||||
OSStatus status;
|
||||
SecCertificateRef certificate = NULL;
|
||||
|
|
@ -141,14 +164,17 @@ void handle_needcertificate(FILE *man_file, SecIdentityRef identity)
|
|||
char *result_b64, *tmp_b64;
|
||||
|
||||
status = SecIdentityCopyCertificate(identity, &certificate);
|
||||
if (status != noErr) {
|
||||
if (status != noErr)
|
||||
{
|
||||
const char *msg = GetMacOSStatusErrorString(status);
|
||||
err(1, "SecIdentityCopyCertificate() failed: %s", msg);
|
||||
}
|
||||
|
||||
data = SecCertificateCopyData(certificate);
|
||||
if (data == NULL)
|
||||
{
|
||||
err(1, "SecCertificateCopyData() returned NULL");
|
||||
}
|
||||
|
||||
cert = CFDataGetBytePtr(data);
|
||||
cert_len = CFDataGetLength(data);
|
||||
|
|
@ -162,11 +188,13 @@ void handle_needcertificate(FILE *man_file, SecIdentityRef identity)
|
|||
fprintf(man_file, "-----BEGIN CERTIFICATE-----\n");
|
||||
tmp_b64 = result_b64;
|
||||
while (strlen(tmp_b64) > 64) {
|
||||
fprintf(man_file, "%.64s\n", tmp_b64);
|
||||
tmp_b64 += 64;
|
||||
fprintf(man_file, "%.64s\n", tmp_b64);
|
||||
tmp_b64 += 64;
|
||||
}
|
||||
if (*tmp_b64)
|
||||
fprintf(man_file, "%s\n", tmp_b64);
|
||||
{
|
||||
fprintf(man_file, "%s\n", tmp_b64);
|
||||
}
|
||||
fprintf(man_file, "-----END CERTIFICATE-----\n");
|
||||
fprintf(man_file, "END\n");
|
||||
|
||||
|
|
@ -177,62 +205,87 @@ void handle_needcertificate(FILE *man_file, SecIdentityRef identity)
|
|||
fprintf(stderr, "Handled NEED 'cert' command\n");
|
||||
}
|
||||
|
||||
void management_loop(SecIdentityRef identity, int man_fd, const char *password)
|
||||
void
|
||||
management_loop(SecIdentityRef identity, int man_fd, const char *password)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
size_t buffer_len = 0;
|
||||
FILE *man = fdopen(man_fd, "w+");
|
||||
if (man == 0)
|
||||
{
|
||||
err(1, "fdopen");
|
||||
}
|
||||
|
||||
if (password)
|
||||
{
|
||||
fprintf(man, "%s\n", password);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (getline(&buffer, &buffer_len, man) < 0)
|
||||
{
|
||||
err(1, "getline");
|
||||
}
|
||||
#if 0
|
||||
fprintf(stderr, "M: %s", buffer);
|
||||
#endif
|
||||
|
||||
if (is_prefix(buffer, ">RSA_SIGN:"))
|
||||
{
|
||||
handle_rsasign(man, identity, buffer);
|
||||
if (is_prefix(buffer, ">NEED-CERTIFICATE")) {
|
||||
if (!identity) {
|
||||
}
|
||||
if (is_prefix(buffer, ">NEED-CERTIFICATE"))
|
||||
{
|
||||
if (!identity)
|
||||
{
|
||||
const char prefix[] = ">NEED-CERTIFICATE:macosx-keychain:";
|
||||
if (!is_prefix(buffer, prefix))
|
||||
errx(1, "No identity template is passed via command line and " \
|
||||
"NEED-CERTIFICATE management interface command " \
|
||||
"misses 'macosx-keychain' prefix.");
|
||||
{
|
||||
errx(1, "No identity template is passed via command line and " \
|
||||
"NEED-CERTIFICATE management interface command " \
|
||||
"misses 'macosx-keychain' prefix.");
|
||||
}
|
||||
identity = template_to_identity(buffer+strlen(prefix));
|
||||
}
|
||||
handle_needcertificate(man, identity);
|
||||
}
|
||||
if (is_prefix(buffer, ">FATAL"))
|
||||
{
|
||||
fprintf(stderr, "Fatal message from OpenVPN: %s\n", buffer+7);
|
||||
}
|
||||
if (is_prefix(buffer, ">INFO"))
|
||||
{
|
||||
fprintf(stderr, "INFO message from OpenVPN: %s\n", buffer+6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *read_password(const char *fname)
|
||||
char *
|
||||
read_password(const char *fname)
|
||||
{
|
||||
char *password = NULL;
|
||||
FILE *pwf = fopen(fname, "r");
|
||||
size_t n = 0;
|
||||
|
||||
if (pwf == NULL)
|
||||
{
|
||||
errx(1, "fopen(%s) failed", fname);
|
||||
}
|
||||
if (getline(&password, &n, pwf) < 0)
|
||||
{
|
||||
err(1, "getline");
|
||||
}
|
||||
fclose(pwf);
|
||||
return password;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (argc < 4)
|
||||
{
|
||||
err(1, "usage: %s <identity_template> <management_ip> <management_port> [<pw-file>]", argv[0]);
|
||||
}
|
||||
|
||||
char *identity_template = argv[1];
|
||||
char *s_ip = argv[2];
|
||||
|
|
@ -240,14 +293,17 @@ int main(int argc, char* argv[])
|
|||
char *password = NULL;
|
||||
int man_fd;
|
||||
|
||||
if (argc > 4) {
|
||||
if (argc > 4)
|
||||
{
|
||||
char *s_pw_file = argv[4];
|
||||
password = read_password(s_pw_file);
|
||||
}
|
||||
|
||||
SecIdentityRef identity = NULL;
|
||||
if (strcmp(identity_template, "auto"))
|
||||
{
|
||||
identity = template_to_identity(identity_template);
|
||||
}
|
||||
man_fd = connect_to_management_server(s_ip, s_port);
|
||||
fprintf(stderr, "Successfully connected to openvpn\n");
|
||||
|
||||
|
|
|
|||
|
|
@ -26,90 +26,90 @@
|
|||
#define OPENVPN_MSG_H_
|
||||
|
||||
typedef enum {
|
||||
msg_acknowledgement,
|
||||
msg_add_address,
|
||||
msg_del_address,
|
||||
msg_add_route,
|
||||
msg_del_route,
|
||||
msg_add_dns_cfg,
|
||||
msg_del_dns_cfg,
|
||||
msg_add_nbt_cfg,
|
||||
msg_del_nbt_cfg,
|
||||
msg_flush_neighbors,
|
||||
msg_add_block_dns,
|
||||
msg_del_block_dns,
|
||||
msg_register_dns
|
||||
msg_acknowledgement,
|
||||
msg_add_address,
|
||||
msg_del_address,
|
||||
msg_add_route,
|
||||
msg_del_route,
|
||||
msg_add_dns_cfg,
|
||||
msg_del_dns_cfg,
|
||||
msg_add_nbt_cfg,
|
||||
msg_del_nbt_cfg,
|
||||
msg_flush_neighbors,
|
||||
msg_add_block_dns,
|
||||
msg_del_block_dns,
|
||||
msg_register_dns
|
||||
} message_type_t;
|
||||
|
||||
typedef struct {
|
||||
message_type_t type;
|
||||
size_t size;
|
||||
int message_id;
|
||||
message_type_t type;
|
||||
size_t size;
|
||||
int message_id;
|
||||
} message_header_t;
|
||||
|
||||
typedef union {
|
||||
struct in_addr ipv4;
|
||||
struct in6_addr ipv6;
|
||||
struct in_addr ipv4;
|
||||
struct in6_addr ipv6;
|
||||
} inet_address_t;
|
||||
|
||||
typedef struct {
|
||||
int index;
|
||||
char name[256];
|
||||
int index;
|
||||
char name[256];
|
||||
} interface_t;
|
||||
|
||||
typedef struct {
|
||||
message_header_t header;
|
||||
short family;
|
||||
inet_address_t address;
|
||||
int prefix_len;
|
||||
interface_t iface;
|
||||
message_header_t header;
|
||||
short family;
|
||||
inet_address_t address;
|
||||
int prefix_len;
|
||||
interface_t iface;
|
||||
} address_message_t;
|
||||
|
||||
typedef struct {
|
||||
message_header_t header;
|
||||
short family;
|
||||
inet_address_t prefix;
|
||||
int prefix_len;
|
||||
inet_address_t gateway;
|
||||
interface_t iface;
|
||||
int metric;
|
||||
message_header_t header;
|
||||
short family;
|
||||
inet_address_t prefix;
|
||||
int prefix_len;
|
||||
inet_address_t gateway;
|
||||
interface_t iface;
|
||||
int metric;
|
||||
} route_message_t;
|
||||
|
||||
typedef struct {
|
||||
message_header_t header;
|
||||
interface_t iface;
|
||||
char domains[512];
|
||||
short family;
|
||||
int addr_len;
|
||||
inet_address_t addr[4]; /* support up to 4 dns addresses */
|
||||
message_header_t header;
|
||||
interface_t iface;
|
||||
char domains[512];
|
||||
short family;
|
||||
int addr_len;
|
||||
inet_address_t addr[4]; /* support up to 4 dns addresses */
|
||||
} dns_cfg_message_t;
|
||||
|
||||
typedef struct {
|
||||
message_header_t header;
|
||||
interface_t iface;
|
||||
int disable_nbt;
|
||||
int nbt_type;
|
||||
char scope_id[256];
|
||||
struct in_addr primary_nbns;
|
||||
struct in_addr secondary_nbns;
|
||||
message_header_t header;
|
||||
interface_t iface;
|
||||
int disable_nbt;
|
||||
int nbt_type;
|
||||
char scope_id[256];
|
||||
struct in_addr primary_nbns;
|
||||
struct in_addr secondary_nbns;
|
||||
} nbt_cfg_message_t;
|
||||
|
||||
// TODO: NTP
|
||||
/* TODO: NTP */
|
||||
|
||||
typedef struct {
|
||||
message_header_t header;
|
||||
short family;
|
||||
interface_t iface;
|
||||
message_header_t header;
|
||||
short family;
|
||||
interface_t iface;
|
||||
} flush_neighbors_message_t;
|
||||
|
||||
typedef struct {
|
||||
message_header_t header;
|
||||
int error_number;
|
||||
message_header_t header;
|
||||
int error_number;
|
||||
} ack_message_t;
|
||||
|
||||
typedef struct {
|
||||
message_header_t header;
|
||||
interface_t iface;
|
||||
message_header_t header;
|
||||
interface_t iface;
|
||||
} block_dns_message_t;
|
||||
|
||||
#endif
|
||||
#endif /* ifndef OPENVPN_MSG_H_ */
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#define __OPENVPN_X509_CERT_T_DECLARED
|
||||
typedef mbedtls_x509_crt openvpn_x509_cert_t;
|
||||
#endif
|
||||
#else
|
||||
#else /* ifdef ENABLE_CRYPTO_MBEDTLS */
|
||||
#include <openssl/x509.h>
|
||||
#ifndef __OPENVPN_X509_CERT_T_DECLARED
|
||||
#define __OPENVPN_X509_CERT_T_DECLARED
|
||||
|
|
@ -85,7 +85,7 @@ extern "C" {
|
|||
*
|
||||
* FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_CLIENT_CONNECT_V2
|
||||
* FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_LEARN_ADDRESS
|
||||
*
|
||||
*
|
||||
* [Client session ensues]
|
||||
*
|
||||
* For each "TLS soft reset", according to reneg-sec option (or similar):
|
||||
|
|
@ -96,7 +96,7 @@ extern "C" {
|
|||
* in the server chain)
|
||||
* FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
|
||||
* FUNC: openvpn_plugin_func_v1 OPENVPN_PLUGIN_TLS_FINAL
|
||||
*
|
||||
*
|
||||
* [If OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY returned OPENVPN_PLUGIN_FUNC_DEFERRED,
|
||||
* we expect that authentication is verified via auth_control_file within
|
||||
* the number of seconds defined by the "hand-window" option. Data channel traffic
|
||||
|
|
@ -155,9 +155,9 @@ typedef void *openvpn_plugin_handle_t;
|
|||
* For Windows (needs to be modified for MSVC)
|
||||
*/
|
||||
#if defined(_WIN32) && !defined(OPENVPN_PLUGIN_H)
|
||||
# define OPENVPN_EXPORT __declspec(dllexport)
|
||||
#define OPENVPN_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
# define OPENVPN_EXPORT
|
||||
#define OPENVPN_EXPORT
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -172,7 +172,7 @@ typedef void *openvpn_plugin_handle_t;
|
|||
#define OPENVPN_PLUGIN_DEF typedef
|
||||
#define OPENVPN_PLUGIN_FUNC(name) (*name)
|
||||
|
||||
#else
|
||||
#else /* ifdef OPENVPN_PLUGIN_H */
|
||||
|
||||
/*
|
||||
* We are compiling plugin.
|
||||
|
|
@ -191,9 +191,9 @@ typedef void *openvpn_plugin_handle_t;
|
|||
*/
|
||||
struct openvpn_plugin_string_list
|
||||
{
|
||||
struct openvpn_plugin_string_list *next;
|
||||
char *name;
|
||||
char *value;
|
||||
struct openvpn_plugin_string_list *next;
|
||||
char *name;
|
||||
char *value;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -226,35 +226,35 @@ struct openvpn_plugin_string_list
|
|||
*/
|
||||
typedef enum
|
||||
{
|
||||
PLOG_ERR = (1 << 0), /* Error condition message */
|
||||
PLOG_WARN = (1 << 1), /* General warning message */
|
||||
PLOG_NOTE = (1 << 2), /* Informational message */
|
||||
PLOG_DEBUG = (1 << 3), /* Debug message, displayed if verb >= 7 */
|
||||
PLOG_ERR = (1 << 0),/* Error condition message */
|
||||
PLOG_WARN = (1 << 1),/* General warning message */
|
||||
PLOG_NOTE = (1 << 2),/* Informational message */
|
||||
PLOG_DEBUG = (1 << 3),/* Debug message, displayed if verb >= 7 */
|
||||
|
||||
PLOG_ERRNO = (1 << 8), /* Add error description to message */
|
||||
PLOG_NOMUTE = (1 << 9), /* Mute setting does not apply for message */
|
||||
PLOG_ERRNO = (1 << 8),/* Add error description to message */
|
||||
PLOG_NOMUTE = (1 << 9), /* Mute setting does not apply for message */
|
||||
|
||||
} openvpn_plugin_log_flags_t;
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if __USE_MINGW_ANSI_STDIO
|
||||
# define _ovpn_chk_fmt(a, b) __attribute__ ((format(gnu_printf, (a), (b))))
|
||||
#define _ovpn_chk_fmt(a, b) __attribute__ ((format(gnu_printf, (a), (b))))
|
||||
#else
|
||||
# define _ovpn_chk_fmt(a, b) __attribute__ ((format(__printf__, (a), (b))))
|
||||
#define _ovpn_chk_fmt(a, b) __attribute__ ((format(__printf__, (a), (b))))
|
||||
#endif
|
||||
#else
|
||||
# define _ovpn_chk_fmt(a, b)
|
||||
#else /* ifdef __GNUC__ */
|
||||
#define _ovpn_chk_fmt(a, b)
|
||||
#endif
|
||||
|
||||
typedef void (*plugin_log_t) (openvpn_plugin_log_flags_t flags,
|
||||
typedef void (*plugin_log_t)(openvpn_plugin_log_flags_t flags,
|
||||
const char *plugin_name,
|
||||
const char *format, ...) _ovpn_chk_fmt (3, 4);
|
||||
|
||||
typedef void (*plugin_vlog_t)(openvpn_plugin_log_flags_t flags,
|
||||
const char *plugin_name,
|
||||
const char *format, ...) _ovpn_chk_fmt(3, 4);
|
||||
|
||||
typedef void (*plugin_vlog_t) (openvpn_plugin_log_flags_t flags,
|
||||
const char *plugin_name,
|
||||
const char *format,
|
||||
va_list arglist) _ovpn_chk_fmt(3, 0);
|
||||
const char *format,
|
||||
va_list arglist) _ovpn_chk_fmt (3, 0);
|
||||
|
||||
#undef _ovpn_chk_fmt
|
||||
|
||||
|
|
@ -270,8 +270,8 @@ typedef void (*plugin_vlog_t) (openvpn_plugin_log_flags_t flags,
|
|||
*/
|
||||
struct openvpn_plugin_callbacks
|
||||
{
|
||||
plugin_log_t plugin_log;
|
||||
plugin_vlog_t plugin_vlog;
|
||||
plugin_log_t plugin_log;
|
||||
plugin_vlog_t plugin_vlog;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -281,9 +281,9 @@ struct openvpn_plugin_callbacks
|
|||
* and the plug-in against OpenSSL.
|
||||
*/
|
||||
typedef enum {
|
||||
SSLAPI_NONE,
|
||||
SSLAPI_OPENSSL,
|
||||
SSLAPI_MBEDTLS
|
||||
SSLAPI_NONE,
|
||||
SSLAPI_OPENSSL,
|
||||
SSLAPI_MBEDTLS
|
||||
} ovpnSSLAPI;
|
||||
|
||||
/**
|
||||
|
|
@ -309,15 +309,15 @@ typedef enum {
|
|||
*/
|
||||
struct openvpn_plugin_args_open_in
|
||||
{
|
||||
const int type_mask;
|
||||
const char ** const argv;
|
||||
const char ** const envp;
|
||||
struct openvpn_plugin_callbacks *callbacks;
|
||||
const ovpnSSLAPI ssl_api;
|
||||
const char *ovpn_version;
|
||||
const unsigned int ovpn_version_major;
|
||||
const unsigned int ovpn_version_minor;
|
||||
const char * const ovpn_version_patch;
|
||||
const int type_mask;
|
||||
const char **const argv;
|
||||
const char **const envp;
|
||||
struct openvpn_plugin_callbacks *callbacks;
|
||||
const ovpnSSLAPI ssl_api;
|
||||
const char *ovpn_version;
|
||||
const unsigned int ovpn_version_major;
|
||||
const unsigned int ovpn_version_minor;
|
||||
const char *const ovpn_version_patch;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -344,9 +344,9 @@ struct openvpn_plugin_args_open_in
|
|||
*/
|
||||
struct openvpn_plugin_args_open_return
|
||||
{
|
||||
int type_mask;
|
||||
openvpn_plugin_handle_t *handle;
|
||||
struct openvpn_plugin_string_list **return_list;
|
||||
int type_mask;
|
||||
openvpn_plugin_handle_t *handle;
|
||||
struct openvpn_plugin_string_list **return_list;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -379,17 +379,17 @@ struct openvpn_plugin_args_open_return
|
|||
*/
|
||||
struct openvpn_plugin_args_func_in
|
||||
{
|
||||
const int type;
|
||||
const char ** const argv;
|
||||
const char ** const envp;
|
||||
openvpn_plugin_handle_t handle;
|
||||
void *per_client_context;
|
||||
const int type;
|
||||
const char **const argv;
|
||||
const char **const envp;
|
||||
openvpn_plugin_handle_t handle;
|
||||
void *per_client_context;
|
||||
#ifdef ENABLE_CRYPTO
|
||||
int current_cert_depth;
|
||||
openvpn_x509_cert_t *current_cert;
|
||||
int current_cert_depth;
|
||||
openvpn_x509_cert_t *current_cert;
|
||||
#else
|
||||
int __current_cert_depth_disabled; /* Unused, for compatibility purposes only */
|
||||
void *__current_cert_disabled; /* Unused, for compatibility purposes only */
|
||||
int __current_cert_depth_disabled; /* Unused, for compatibility purposes only */
|
||||
void *__current_cert_disabled; /* Unused, for compatibility purposes only */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -407,7 +407,7 @@ struct openvpn_plugin_args_func_in
|
|||
*/
|
||||
struct openvpn_plugin_args_func_return
|
||||
{
|
||||
struct openvpn_plugin_string_list **return_list;
|
||||
struct openvpn_plugin_string_list **return_list;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -441,7 +441,7 @@ struct openvpn_plugin_args_func_return
|
|||
* FUNCTION: openvpn_plugin_open_v2
|
||||
*
|
||||
* REQUIRED: YES
|
||||
*
|
||||
*
|
||||
* Called on initial plug-in load. OpenVPN will preserve plug-in state
|
||||
* across SIGUSR1 restarts but not across SIGHUP restarts. A SIGHUP reset
|
||||
* will cause the plugin to be closed and reopened.
|
||||
|
|
@ -473,10 +473,10 @@ struct openvpn_plugin_args_func_return
|
|||
* An openvpn_plugin_handle_t value on success, NULL on failure
|
||||
*/
|
||||
OPENVPN_PLUGIN_DEF openvpn_plugin_handle_t OPENVPN_PLUGIN_FUNC(openvpn_plugin_open_v2)
|
||||
(unsigned int *type_mask,
|
||||
const char *argv[],
|
||||
const char *envp[],
|
||||
struct openvpn_plugin_string_list **return_list);
|
||||
(unsigned int *type_mask,
|
||||
const char *argv[],
|
||||
const char *envp[],
|
||||
struct openvpn_plugin_string_list **return_list);
|
||||
|
||||
/*
|
||||
* FUNCTION: openvpn_plugin_func_v2
|
||||
|
|
@ -484,7 +484,7 @@ OPENVPN_PLUGIN_DEF openvpn_plugin_handle_t OPENVPN_PLUGIN_FUNC(openvpn_plugin_op
|
|||
* Called to perform the work of a given script type.
|
||||
*
|
||||
* REQUIRED: YES
|
||||
*
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* handle : the openvpn_plugin_handle_t value which was returned by
|
||||
|
|
@ -569,12 +569,12 @@ OPENVPN_PLUGIN_DEF openvpn_plugin_handle_t OPENVPN_PLUGIN_FUNC(openvpn_plugin_op
|
|||
* authentication and client-specific packet filtering.
|
||||
*/
|
||||
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v2)
|
||||
(openvpn_plugin_handle_t handle,
|
||||
const int type,
|
||||
const char *argv[],
|
||||
const char *envp[],
|
||||
void *per_client_context,
|
||||
struct openvpn_plugin_string_list **return_list);
|
||||
(openvpn_plugin_handle_t handle,
|
||||
const int type,
|
||||
const char *argv[],
|
||||
const char *envp[],
|
||||
void *per_client_context,
|
||||
struct openvpn_plugin_string_list **return_list);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -589,8 +589,8 @@ OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v2)
|
|||
* ARGUMENTS
|
||||
*
|
||||
* version : fixed value, defines the API version of the OpenVPN plug-in API. The plug-in
|
||||
* should validate that this value is matching the OPENVPN_PLUGINv3_STRUCTVER
|
||||
* value.
|
||||
* should validate that this value is matching the OPENVPN_PLUGINv3_STRUCTVER
|
||||
* value.
|
||||
*
|
||||
* arguments : Structure with all arguments available to the plug-in.
|
||||
*
|
||||
|
|
@ -601,9 +601,9 @@ OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v2)
|
|||
* OPENVPN_PLUGIN_FUNC_SUCCESS on success, OPENVPN_PLUGIN_FUNC_ERROR on failure
|
||||
*/
|
||||
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_open_v3)
|
||||
(const int version,
|
||||
struct openvpn_plugin_args_open_in const *arguments,
|
||||
struct openvpn_plugin_args_open_return *retptr);
|
||||
(const int version,
|
||||
struct openvpn_plugin_args_open_in const *arguments,
|
||||
struct openvpn_plugin_args_open_return *retptr);
|
||||
|
||||
/*
|
||||
* FUNCTION: openvpn_plugin_func_v3
|
||||
|
|
@ -685,15 +685,15 @@ OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_open_v3)
|
|||
* authentication and client-specific packet filtering.
|
||||
*/
|
||||
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v3)
|
||||
(const int version,
|
||||
struct openvpn_plugin_args_func_in const *arguments,
|
||||
struct openvpn_plugin_args_func_return *retptr);
|
||||
(const int version,
|
||||
struct openvpn_plugin_args_func_in const *arguments,
|
||||
struct openvpn_plugin_args_func_return *retptr);
|
||||
|
||||
/*
|
||||
* FUNCTION: openvpn_plugin_close_v1
|
||||
*
|
||||
* REQUIRED: YES
|
||||
*
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* handle : the openvpn_plugin_handle_t value which was returned by
|
||||
|
|
@ -702,13 +702,13 @@ OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v3)
|
|||
* Called immediately prior to plug-in unload.
|
||||
*/
|
||||
OPENVPN_PLUGIN_DEF void OPENVPN_PLUGIN_FUNC(openvpn_plugin_close_v1)
|
||||
(openvpn_plugin_handle_t handle);
|
||||
(openvpn_plugin_handle_t handle);
|
||||
|
||||
/*
|
||||
* FUNCTION: openvpn_plugin_abort_v1
|
||||
*
|
||||
* REQUIRED: NO
|
||||
*
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* handle : the openvpn_plugin_handle_t value which was returned by
|
||||
|
|
@ -719,7 +719,7 @@ OPENVPN_PLUGIN_DEF void OPENVPN_PLUGIN_FUNC(openvpn_plugin_close_v1)
|
|||
* openvpn_plugin_open callback.
|
||||
*/
|
||||
OPENVPN_PLUGIN_DEF void OPENVPN_PLUGIN_FUNC(openvpn_plugin_abort_v1)
|
||||
(openvpn_plugin_handle_t handle);
|
||||
(openvpn_plugin_handle_t handle);
|
||||
|
||||
/*
|
||||
* FUNCTION: openvpn_plugin_client_constructor_v1
|
||||
|
|
@ -736,7 +736,7 @@ OPENVPN_PLUGIN_DEF void OPENVPN_PLUGIN_FUNC(openvpn_plugin_abort_v1)
|
|||
* return a void * to this memory region.
|
||||
*
|
||||
* REQUIRED: NO
|
||||
*
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* handle : the openvpn_plugin_handle_t value which was returned by
|
||||
|
|
@ -747,8 +747,8 @@ OPENVPN_PLUGIN_DEF void OPENVPN_PLUGIN_FUNC(openvpn_plugin_abort_v1)
|
|||
* void * pointer to plugin's private per-client memory region, or NULL
|
||||
* if no memory region is required.
|
||||
*/
|
||||
OPENVPN_PLUGIN_DEF void * OPENVPN_PLUGIN_FUNC(openvpn_plugin_client_constructor_v1)
|
||||
(openvpn_plugin_handle_t handle);
|
||||
OPENVPN_PLUGIN_DEF void *OPENVPN_PLUGIN_FUNC(openvpn_plugin_client_constructor_v1)
|
||||
(openvpn_plugin_handle_t handle);
|
||||
|
||||
/*
|
||||
* FUNCTION: openvpn_plugin_client_destructor_v1
|
||||
|
|
@ -756,7 +756,7 @@ OPENVPN_PLUGIN_DEF void * OPENVPN_PLUGIN_FUNC(openvpn_plugin_client_constructor_
|
|||
* This function is called on client instance object destruction.
|
||||
*
|
||||
* REQUIRED: NO
|
||||
*
|
||||
*
|
||||
* ARGUMENTS
|
||||
*
|
||||
* handle : the openvpn_plugin_handle_t value which was returned by
|
||||
|
|
@ -766,7 +766,7 @@ OPENVPN_PLUGIN_DEF void * OPENVPN_PLUGIN_FUNC(openvpn_plugin_client_constructor_
|
|||
* openvpn_plugin_client_constructor_v1, if defined.
|
||||
*/
|
||||
OPENVPN_PLUGIN_DEF void OPENVPN_PLUGIN_FUNC(openvpn_plugin_client_destructor_v1)
|
||||
(openvpn_plugin_handle_t handle, void *per_client_context);
|
||||
(openvpn_plugin_handle_t handle, void *per_client_context);
|
||||
|
||||
/*
|
||||
* FUNCTION: openvpn_plugin_select_initialization_point_v1
|
||||
|
|
@ -779,7 +779,7 @@ OPENVPN_PLUGIN_DEF void OPENVPN_PLUGIN_FUNC(openvpn_plugin_client_destructor_v1)
|
|||
* OPENVPN_PLUGIN_INIT_PRE_CONFIG_PARSE.
|
||||
*
|
||||
* REQUIRED: NO
|
||||
*
|
||||
*
|
||||
* RETURN VALUE:
|
||||
*
|
||||
* An OPENVPN_PLUGIN_INIT_x value.
|
||||
|
|
@ -790,35 +790,35 @@ OPENVPN_PLUGIN_DEF void OPENVPN_PLUGIN_FUNC(openvpn_plugin_client_destructor_v1)
|
|||
#define OPENVPN_PLUGIN_INIT_POST_UID_CHANGE 4
|
||||
|
||||
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_select_initialization_point_v1)
|
||||
(void);
|
||||
(void);
|
||||
|
||||
/*
|
||||
* FUNCTION: openvpn_plugin_min_version_required_v1
|
||||
*
|
||||
* This function is called by OpenVPN to query the minimum
|
||||
plugin interface version number required by the plugin.
|
||||
* plugin interface version number required by the plugin.
|
||||
*
|
||||
* REQUIRED: NO
|
||||
*
|
||||
*
|
||||
* RETURN VALUE
|
||||
*
|
||||
* The minimum OpenVPN plugin interface version number necessary to support
|
||||
* this plugin.
|
||||
*/
|
||||
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_min_version_required_v1)
|
||||
(void);
|
||||
(void);
|
||||
|
||||
/*
|
||||
* Deprecated functions which are still supported for backward compatibility.
|
||||
*/
|
||||
|
||||
OPENVPN_PLUGIN_DEF openvpn_plugin_handle_t OPENVPN_PLUGIN_FUNC(openvpn_plugin_open_v1)
|
||||
(unsigned int *type_mask,
|
||||
const char *argv[],
|
||||
const char *envp[]);
|
||||
(unsigned int *type_mask,
|
||||
const char *argv[],
|
||||
const char *envp[]);
|
||||
|
||||
OPENVPN_PLUGIN_DEF int OPENVPN_PLUGIN_FUNC(openvpn_plugin_func_v1)
|
||||
(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[]);
|
||||
(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
/*
|
||||
* This file implements a simple OpenVPN plugin module which
|
||||
* will test deferred authentication and packet filtering.
|
||||
*
|
||||
*
|
||||
* Will run on Windows or *nix.
|
||||
*
|
||||
* Sample usage:
|
||||
|
|
@ -68,13 +68,13 @@
|
|||
*/
|
||||
|
||||
struct plugin_context {
|
||||
int test_deferred_auth;
|
||||
int test_packet_filter;
|
||||
int test_deferred_auth;
|
||||
int test_packet_filter;
|
||||
};
|
||||
|
||||
struct plugin_per_client_context {
|
||||
int n_calls;
|
||||
bool generated_pf_file;
|
||||
int n_calls;
|
||||
bool generated_pf_file;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -83,223 +83,258 @@ struct plugin_per_client_context {
|
|||
* if found or NULL otherwise.
|
||||
*/
|
||||
static const char *
|
||||
get_env (const char *name, const char *envp[])
|
||||
get_env(const char *name, const char *envp[])
|
||||
{
|
||||
if (envp)
|
||||
if (envp)
|
||||
{
|
||||
int i;
|
||||
const int namelen = strlen (name);
|
||||
for (i = 0; envp[i]; ++i)
|
||||
{
|
||||
if (!strncmp (envp[i], name, namelen))
|
||||
{
|
||||
const char *cp = envp[i] + namelen;
|
||||
if (*cp == '=')
|
||||
return cp + 1;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
const int namelen = strlen(name);
|
||||
for (i = 0; envp[i]; ++i)
|
||||
{
|
||||
if (!strncmp(envp[i], name, namelen))
|
||||
{
|
||||
const char *cp = envp[i] + namelen;
|
||||
if (*cp == '=')
|
||||
{
|
||||
return cp + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* used for safe printf of possible NULL strings */
|
||||
static const char *
|
||||
np (const char *str)
|
||||
np(const char *str)
|
||||
{
|
||||
if (str)
|
||||
return str;
|
||||
else
|
||||
return "[NULL]";
|
||||
if (str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "[NULL]";
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
atoi_null0 (const char *str)
|
||||
atoi_null0(const char *str)
|
||||
{
|
||||
if (str)
|
||||
return atoi (str);
|
||||
else
|
||||
return 0;
|
||||
if (str)
|
||||
{
|
||||
return atoi(str);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT openvpn_plugin_handle_t
|
||||
openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
|
||||
openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[])
|
||||
{
|
||||
struct plugin_context *context;
|
||||
struct plugin_context *context;
|
||||
|
||||
printf ("FUNC: openvpn_plugin_open_v1\n");
|
||||
printf("FUNC: openvpn_plugin_open_v1\n");
|
||||
|
||||
/*
|
||||
* Allocate our context
|
||||
*/
|
||||
context = (struct plugin_context *) calloc (1, sizeof (struct plugin_context));
|
||||
/*
|
||||
* Allocate our context
|
||||
*/
|
||||
context = (struct plugin_context *) calloc(1, sizeof(struct plugin_context));
|
||||
|
||||
context->test_deferred_auth = atoi_null0 (get_env ("test_deferred_auth", envp));
|
||||
printf ("TEST_DEFERRED_AUTH %d\n", context->test_deferred_auth);
|
||||
context->test_deferred_auth = atoi_null0(get_env("test_deferred_auth", envp));
|
||||
printf("TEST_DEFERRED_AUTH %d\n", context->test_deferred_auth);
|
||||
|
||||
context->test_packet_filter = atoi_null0 (get_env ("test_packet_filter", envp));
|
||||
printf ("TEST_PACKET_FILTER %d\n", context->test_packet_filter);
|
||||
context->test_packet_filter = atoi_null0(get_env("test_packet_filter", envp));
|
||||
printf("TEST_PACKET_FILTER %d\n", context->test_packet_filter);
|
||||
|
||||
/*
|
||||
* Which callbacks to intercept.
|
||||
*/
|
||||
*type_mask =
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_ROUTE_UP) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_IPCHANGE) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_TLS_VERIFY) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_CLIENT_CONNECT_V2) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_CLIENT_DISCONNECT) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_LEARN_ADDRESS) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_TLS_FINAL) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_ENABLE_PF);
|
||||
/*
|
||||
* Which callbacks to intercept.
|
||||
*/
|
||||
*type_mask =
|
||||
OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_UP)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_DOWN)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_ROUTE_UP)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_IPCHANGE)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_VERIFY)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_CONNECT_V2)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_DISCONNECT)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_LEARN_ADDRESS)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_FINAL)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_ENABLE_PF);
|
||||
|
||||
return (openvpn_plugin_handle_t) context;
|
||||
return (openvpn_plugin_handle_t) context;
|
||||
}
|
||||
|
||||
static int
|
||||
auth_user_pass_verify (struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
|
||||
auth_user_pass_verify(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
|
||||
{
|
||||
if (context->test_deferred_auth)
|
||||
if (context->test_deferred_auth)
|
||||
{
|
||||
/* get username/password from envp string array */
|
||||
const char *username = get_env ("username", envp);
|
||||
const char *password = get_env ("password", envp);
|
||||
/* get username/password from envp string array */
|
||||
const char *username = get_env("username", envp);
|
||||
const char *password = get_env("password", envp);
|
||||
|
||||
/* get auth_control_file filename from envp string array*/
|
||||
const char *auth_control_file = get_env ("auth_control_file", envp);
|
||||
/* get auth_control_file filename from envp string array*/
|
||||
const char *auth_control_file = get_env("auth_control_file", envp);
|
||||
|
||||
printf ("DEFER u='%s' p='%s' acf='%s'\n",
|
||||
np(username),
|
||||
np(password),
|
||||
np(auth_control_file));
|
||||
printf("DEFER u='%s' p='%s' acf='%s'\n",
|
||||
np(username),
|
||||
np(password),
|
||||
np(auth_control_file));
|
||||
|
||||
/* Authenticate asynchronously in n seconds */
|
||||
if (auth_control_file)
|
||||
{
|
||||
char buf[256];
|
||||
int auth = 2;
|
||||
sscanf (username, "%d", &auth);
|
||||
snprintf (buf, sizeof(buf), "( sleep %d ; echo AUTH %s %d ; echo %d >%s ) &",
|
||||
context->test_deferred_auth,
|
||||
auth_control_file,
|
||||
auth,
|
||||
pcc->n_calls < auth,
|
||||
auth_control_file);
|
||||
printf ("%s\n", buf);
|
||||
system (buf);
|
||||
pcc->n_calls++;
|
||||
return OPENVPN_PLUGIN_FUNC_DEFERRED;
|
||||
}
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
/* Authenticate asynchronously in n seconds */
|
||||
if (auth_control_file)
|
||||
{
|
||||
char buf[256];
|
||||
int auth = 2;
|
||||
sscanf(username, "%d", &auth);
|
||||
snprintf(buf, sizeof(buf), "( sleep %d ; echo AUTH %s %d ; echo %d >%s ) &",
|
||||
context->test_deferred_auth,
|
||||
auth_control_file,
|
||||
auth,
|
||||
pcc->n_calls < auth,
|
||||
auth_control_file);
|
||||
printf("%s\n", buf);
|
||||
system(buf);
|
||||
pcc->n_calls++;
|
||||
return OPENVPN_PLUGIN_FUNC_DEFERRED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
tls_final (struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
|
||||
tls_final(struct plugin_context *context, struct plugin_per_client_context *pcc, const char *argv[], const char *envp[])
|
||||
{
|
||||
if (context->test_packet_filter)
|
||||
if (context->test_packet_filter)
|
||||
{
|
||||
if (!pcc->generated_pf_file)
|
||||
{
|
||||
const char *pff = get_env ("pf_file", envp);
|
||||
const char *cn = get_env ("username", envp);
|
||||
if (pff && cn)
|
||||
{
|
||||
char buf[256];
|
||||
snprintf (buf, sizeof(buf), "( sleep %d ; echo PF %s/%s ; cp \"%s.pf\" \"%s\" ) &",
|
||||
context->test_packet_filter, cn, pff, cn, pff);
|
||||
printf ("%s\n", buf);
|
||||
system (buf);
|
||||
pcc->generated_pf_file = true;
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
if (!pcc->generated_pf_file)
|
||||
{
|
||||
const char *pff = get_env("pf_file", envp);
|
||||
const char *cn = get_env("username", envp);
|
||||
if (pff && cn)
|
||||
{
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf), "( sleep %d ; echo PF %s/%s ; cp \"%s.pf\" \"%s\" ) &",
|
||||
context->test_packet_filter, cn, pff, cn, pff);
|
||||
printf("%s\n", buf);
|
||||
system(buf);
|
||||
pcc->generated_pf_file = true;
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT int
|
||||
openvpn_plugin_func_v2 (openvpn_plugin_handle_t handle,
|
||||
const int type,
|
||||
const char *argv[],
|
||||
const char *envp[],
|
||||
void *per_client_context,
|
||||
struct openvpn_plugin_string_list **return_list)
|
||||
openvpn_plugin_func_v2(openvpn_plugin_handle_t handle,
|
||||
const int type,
|
||||
const char *argv[],
|
||||
const char *envp[],
|
||||
void *per_client_context,
|
||||
struct openvpn_plugin_string_list **return_list)
|
||||
{
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
struct plugin_per_client_context *pcc = (struct plugin_per_client_context *) per_client_context;
|
||||
switch (type)
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
struct plugin_per_client_context *pcc = (struct plugin_per_client_context *) per_client_context;
|
||||
switch (type)
|
||||
{
|
||||
case OPENVPN_PLUGIN_UP:
|
||||
printf ("OPENVPN_PLUGIN_UP\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
case OPENVPN_PLUGIN_DOWN:
|
||||
printf ("OPENVPN_PLUGIN_DOWN\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
case OPENVPN_PLUGIN_ROUTE_UP:
|
||||
printf ("OPENVPN_PLUGIN_ROUTE_UP\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
case OPENVPN_PLUGIN_IPCHANGE:
|
||||
printf ("OPENVPN_PLUGIN_IPCHANGE\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
case OPENVPN_PLUGIN_TLS_VERIFY:
|
||||
printf ("OPENVPN_PLUGIN_TLS_VERIFY\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
|
||||
printf ("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
|
||||
return auth_user_pass_verify (context, pcc, argv, envp);
|
||||
case OPENVPN_PLUGIN_CLIENT_CONNECT_V2:
|
||||
printf ("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
case OPENVPN_PLUGIN_CLIENT_DISCONNECT:
|
||||
printf ("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
case OPENVPN_PLUGIN_LEARN_ADDRESS:
|
||||
printf ("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
case OPENVPN_PLUGIN_TLS_FINAL:
|
||||
printf ("OPENVPN_PLUGIN_TLS_FINAL\n");
|
||||
return tls_final (context, pcc, argv, envp);
|
||||
case OPENVPN_PLUGIN_ENABLE_PF:
|
||||
printf ("OPENVPN_PLUGIN_ENABLE_PF\n");
|
||||
if (context->test_packet_filter)
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
default:
|
||||
printf ("OPENVPN_PLUGIN_?\n");
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
case OPENVPN_PLUGIN_UP:
|
||||
printf("OPENVPN_PLUGIN_UP\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
|
||||
case OPENVPN_PLUGIN_DOWN:
|
||||
printf("OPENVPN_PLUGIN_DOWN\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
|
||||
case OPENVPN_PLUGIN_ROUTE_UP:
|
||||
printf("OPENVPN_PLUGIN_ROUTE_UP\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
|
||||
case OPENVPN_PLUGIN_IPCHANGE:
|
||||
printf("OPENVPN_PLUGIN_IPCHANGE\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
|
||||
case OPENVPN_PLUGIN_TLS_VERIFY:
|
||||
printf("OPENVPN_PLUGIN_TLS_VERIFY\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
|
||||
case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
|
||||
printf("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
|
||||
return auth_user_pass_verify(context, pcc, argv, envp);
|
||||
|
||||
case OPENVPN_PLUGIN_CLIENT_CONNECT_V2:
|
||||
printf("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
|
||||
case OPENVPN_PLUGIN_CLIENT_DISCONNECT:
|
||||
printf("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
|
||||
case OPENVPN_PLUGIN_LEARN_ADDRESS:
|
||||
printf("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
|
||||
case OPENVPN_PLUGIN_TLS_FINAL:
|
||||
printf("OPENVPN_PLUGIN_TLS_FINAL\n");
|
||||
return tls_final(context, pcc, argv, envp);
|
||||
|
||||
case OPENVPN_PLUGIN_ENABLE_PF:
|
||||
printf("OPENVPN_PLUGIN_ENABLE_PF\n");
|
||||
if (context->test_packet_filter)
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
|
||||
default:
|
||||
printf("OPENVPN_PLUGIN_?\n");
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT void *
|
||||
openvpn_plugin_client_constructor_v1 (openvpn_plugin_handle_t handle)
|
||||
openvpn_plugin_client_constructor_v1(openvpn_plugin_handle_t handle)
|
||||
{
|
||||
printf ("FUNC: openvpn_plugin_client_constructor_v1\n");
|
||||
return calloc (1, sizeof (struct plugin_per_client_context));
|
||||
printf("FUNC: openvpn_plugin_client_constructor_v1\n");
|
||||
return calloc(1, sizeof(struct plugin_per_client_context));
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT void
|
||||
openvpn_plugin_client_destructor_v1 (openvpn_plugin_handle_t handle, void *per_client_context)
|
||||
openvpn_plugin_client_destructor_v1(openvpn_plugin_handle_t handle, void *per_client_context)
|
||||
{
|
||||
printf ("FUNC: openvpn_plugin_client_destructor_v1\n");
|
||||
free (per_client_context);
|
||||
printf("FUNC: openvpn_plugin_client_destructor_v1\n");
|
||||
free(per_client_context);
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT void
|
||||
openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
|
||||
openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
|
||||
{
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
printf ("FUNC: openvpn_plugin_close_v1\n");
|
||||
free (context);
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
printf("FUNC: openvpn_plugin_close_v1\n");
|
||||
free(context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,23 +41,23 @@
|
|||
#endif
|
||||
|
||||
#define ovpn_err(fmt, ...) \
|
||||
plugin->log(PLOG_ERR, "SSO", fmt , ## __VA_ARGS__)
|
||||
plugin->log(PLOG_ERR, "SSO", fmt, ## __VA_ARGS__)
|
||||
#define ovpn_dbg(fmt, ...) \
|
||||
plugin->log(PLOG_DEBUG, "SSO", fmt , ## __VA_ARGS__)
|
||||
plugin->log(PLOG_DEBUG, "SSO", fmt, ## __VA_ARGS__)
|
||||
#define ovpn_note(fmt, ...) \
|
||||
plugin->log(PLOG_NOTE, "SSO", fmt , ## __VA_ARGS__)
|
||||
plugin->log(PLOG_NOTE, "SSO", fmt, ## __VA_ARGS__)
|
||||
|
||||
enum endpoint { CLIENT = 1, SERVER = 2 };
|
||||
|
||||
struct plugin {
|
||||
plugin_log_t log;
|
||||
enum endpoint type;
|
||||
int mask;
|
||||
plugin_log_t log;
|
||||
enum endpoint type;
|
||||
int mask;
|
||||
};
|
||||
|
||||
struct session {
|
||||
char user[48];
|
||||
char key [48];
|
||||
char user[48];
|
||||
char key [48];
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -69,201 +69,226 @@ struct session {
|
|||
static const char *
|
||||
get_env(const char *name, const char *envp[])
|
||||
{
|
||||
if (envp)
|
||||
if (envp)
|
||||
{
|
||||
int i;
|
||||
const int namelen = strlen (name);
|
||||
for (i = 0; envp[i]; ++i)
|
||||
{
|
||||
if (!strncmp (envp[i], name, namelen))
|
||||
{
|
||||
const char *cp = envp[i] + namelen;
|
||||
if (*cp == '=')
|
||||
return cp + 1;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
const int namelen = strlen(name);
|
||||
for (i = 0; envp[i]; ++i)
|
||||
{
|
||||
if (!strncmp(envp[i], name, namelen))
|
||||
{
|
||||
const char *cp = envp[i] + namelen;
|
||||
if (*cp == '=')
|
||||
{
|
||||
return cp + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT int
|
||||
openvpn_plugin_open_v3 (const int version,
|
||||
struct openvpn_plugin_args_open_in const *args,
|
||||
struct openvpn_plugin_args_open_return *rv)
|
||||
openvpn_plugin_open_v3(const int version,
|
||||
struct openvpn_plugin_args_open_in const *args,
|
||||
struct openvpn_plugin_args_open_return *rv)
|
||||
{
|
||||
struct plugin *plugin = calloc (1, sizeof(*plugin));
|
||||
struct plugin *plugin = calloc(1, sizeof(*plugin));
|
||||
|
||||
plugin->type = get_env ("remote_1", args->envp) ? CLIENT : SERVER;
|
||||
plugin->log = args->callbacks->plugin_log;
|
||||
plugin->type = get_env("remote_1", args->envp) ? CLIENT : SERVER;
|
||||
plugin->log = args->callbacks->plugin_log;
|
||||
|
||||
plugin->mask = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_FINAL);
|
||||
plugin->mask |= OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_VERIFY);
|
||||
plugin->mask = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_FINAL);
|
||||
plugin->mask |= OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_VERIFY);
|
||||
|
||||
ovpn_note("vpn endpoint type=%s",plugin->type == CLIENT ? "client":"server");
|
||||
ovpn_note("vpn endpoint type=%s",plugin->type == CLIENT ? "client" : "server");
|
||||
|
||||
rv->type_mask = plugin->mask;
|
||||
rv->handle = (void *)plugin;
|
||||
rv->type_mask = plugin->mask;
|
||||
rv->handle = (void *)plugin;
|
||||
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
session_user_set(struct session *sess, X509 *x509)
|
||||
{
|
||||
int fn_nid;
|
||||
ASN1_OBJECT *fn;
|
||||
ASN1_STRING *val;
|
||||
X509_NAME *x509_name;
|
||||
X509_NAME_ENTRY *ent;
|
||||
const char *objbuf;
|
||||
int fn_nid;
|
||||
ASN1_OBJECT *fn;
|
||||
ASN1_STRING *val;
|
||||
X509_NAME *x509_name;
|
||||
X509_NAME_ENTRY *ent;
|
||||
const char *objbuf;
|
||||
|
||||
x509_name = X509_get_subject_name (x509);
|
||||
int i, n = X509_NAME_entry_count (x509_name);
|
||||
for (i = 0; i < n; ++i)
|
||||
x509_name = X509_get_subject_name(x509);
|
||||
int i, n = X509_NAME_entry_count(x509_name);
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
if (!(ent = X509_NAME_get_entry (x509_name, i)))
|
||||
continue;
|
||||
if (!(fn = X509_NAME_ENTRY_get_object (ent)))
|
||||
continue;
|
||||
if (!(val = X509_NAME_ENTRY_get_data (ent)))
|
||||
continue;
|
||||
if ((fn_nid = OBJ_obj2nid (fn)) == NID_undef)
|
||||
continue;
|
||||
if (!(objbuf = OBJ_nid2sn (fn_nid)))
|
||||
continue;
|
||||
/* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
|
||||
unsigned char *buf = (unsigned char *)1;
|
||||
if (ASN1_STRING_to_UTF8 (&buf, val) <= 0)
|
||||
continue;
|
||||
if (!(ent = X509_NAME_get_entry(x509_name, i)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(fn = X509_NAME_ENTRY_get_object(ent)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(val = X509_NAME_ENTRY_get_data(ent)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ((fn_nid = OBJ_obj2nid(fn)) == NID_undef)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!(objbuf = OBJ_nid2sn(fn_nid)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
|
||||
unsigned char *buf = (unsigned char *)1;
|
||||
if (ASN1_STRING_to_UTF8(&buf, val) <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strncasecmp(objbuf, "CN", 2))
|
||||
snprintf(sess->user, sizeof(sess->user) - 1, (char *)buf);
|
||||
if (!strncasecmp(objbuf, "CN", 2))
|
||||
{
|
||||
snprintf(sess->user, sizeof(sess->user) - 1, (char *)buf);
|
||||
}
|
||||
|
||||
OPENSSL_free (buf);
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
tls_verify(struct openvpn_plugin_args_func_in const *args)
|
||||
{
|
||||
struct plugin *plugin = (struct plugin *)args->handle;
|
||||
struct session *sess = (struct session *)args->per_client_context;
|
||||
struct plugin *plugin = (struct plugin *)args->handle;
|
||||
struct session *sess = (struct session *)args->per_client_context;
|
||||
|
||||
/* we store cert subject for the server end point only */
|
||||
if (plugin->type != SERVER)
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
if (!args->current_cert)
|
||||
{
|
||||
ovpn_err("this example plugin requires client certificate");
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
|
||||
session_user_set(sess, args->current_cert);
|
||||
|
||||
/* we store cert subject for the server end point only */
|
||||
if (plugin->type != SERVER)
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
|
||||
if (!args->current_cert) {
|
||||
ovpn_err("this example plugin requires client certificate");
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
|
||||
session_user_set(sess, args->current_cert);
|
||||
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
file_store(char *file, char *content)
|
||||
{
|
||||
FILE *f;
|
||||
if (!(f = fopen(file, "w+")))
|
||||
return;
|
||||
FILE *f;
|
||||
if (!(f = fopen(file, "w+")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(f, "%s", content);
|
||||
fclose(f);
|
||||
fprintf(f, "%s", content);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static void
|
||||
server_store(struct openvpn_plugin_args_func_in const *args)
|
||||
{
|
||||
struct plugin *plugin = (struct plugin *)args->handle;
|
||||
struct session *sess = (struct session *)args->per_client_context;
|
||||
struct plugin *plugin = (struct plugin *)args->handle;
|
||||
struct session *sess = (struct session *)args->per_client_context;
|
||||
|
||||
char file[MAXPATH];
|
||||
snprintf(file, sizeof(file) - 1, "/tmp/openvpn_sso_%s", sess->key);
|
||||
ovpn_note("app session file: %s", file);
|
||||
file_store(file, sess->user);
|
||||
char file[MAXPATH];
|
||||
snprintf(file, sizeof(file) - 1, "/tmp/openvpn_sso_%s", sess->key);
|
||||
ovpn_note("app session file: %s", file);
|
||||
file_store(file, sess->user);
|
||||
}
|
||||
|
||||
static void
|
||||
client_store(struct openvpn_plugin_args_func_in const *args)
|
||||
{
|
||||
struct plugin *plugin = (struct plugin *)args->handle;
|
||||
struct session *sess = (struct session *)args->per_client_context;
|
||||
struct plugin *plugin = (struct plugin *)args->handle;
|
||||
struct session *sess = (struct session *)args->per_client_context;
|
||||
|
||||
char *file = "/tmp/openvpn_sso_user";
|
||||
ovpn_note("app session file: %s", file);
|
||||
file_store(file, sess->key);
|
||||
char *file = "/tmp/openvpn_sso_user";
|
||||
ovpn_note("app session file: %s", file);
|
||||
file_store(file, sess->key);
|
||||
}
|
||||
|
||||
static int
|
||||
tls_final(struct openvpn_plugin_args_func_in const *args,
|
||||
struct openvpn_plugin_args_func_return *rv)
|
||||
{
|
||||
struct plugin *plugin = (struct plugin *)args->handle;
|
||||
struct session *sess = (struct session *)args->per_client_context;
|
||||
struct plugin *plugin = (struct plugin *)args->handle;
|
||||
struct session *sess = (struct session *)args->per_client_context;
|
||||
|
||||
const char *key;
|
||||
if (!(key = get_env ("exported_keying_material", args->envp)))
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
const char *key;
|
||||
if (!(key = get_env("exported_keying_material", args->envp)))
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
|
||||
snprintf(sess->key, sizeof(sess->key) - 1, "%s", key);
|
||||
ovpn_note("app session key: %s", sess->key);
|
||||
snprintf(sess->key, sizeof(sess->key) - 1, "%s", key);
|
||||
ovpn_note("app session key: %s", sess->key);
|
||||
|
||||
switch (plugin->type) {
|
||||
case SERVER:
|
||||
server_store(args);
|
||||
break;
|
||||
case CLIENT:
|
||||
client_store(args);
|
||||
switch (plugin->type) {
|
||||
case SERVER:
|
||||
server_store(args);
|
||||
break;
|
||||
|
||||
case CLIENT:
|
||||
client_store(args);
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
ovpn_note("app session user: %s", sess->user);
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
ovpn_note("app session user: %s", sess->user);
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT int
|
||||
openvpn_plugin_func_v3 (const int version,
|
||||
struct openvpn_plugin_args_func_in const *args,
|
||||
struct openvpn_plugin_args_func_return *rv)
|
||||
openvpn_plugin_func_v3(const int version,
|
||||
struct openvpn_plugin_args_func_in const *args,
|
||||
struct openvpn_plugin_args_func_return *rv)
|
||||
{
|
||||
switch(args->type) {
|
||||
case OPENVPN_PLUGIN_TLS_VERIFY:
|
||||
return tls_verify(args);
|
||||
case OPENVPN_PLUGIN_TLS_FINAL:
|
||||
return tls_final(args, rv);
|
||||
}
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
switch (args->type) {
|
||||
case OPENVPN_PLUGIN_TLS_VERIFY:
|
||||
return tls_verify(args);
|
||||
|
||||
case OPENVPN_PLUGIN_TLS_FINAL:
|
||||
return tls_final(args, rv);
|
||||
}
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT void *
|
||||
openvpn_plugin_client_constructor_v1(openvpn_plugin_handle_t handle)
|
||||
{
|
||||
struct plugin *plugin = (struct plugin *)handle;
|
||||
struct session *sess = calloc (1, sizeof(*sess));
|
||||
struct plugin *plugin = (struct plugin *)handle;
|
||||
struct session *sess = calloc(1, sizeof(*sess));
|
||||
|
||||
ovpn_note("app session created");
|
||||
ovpn_note("app session created");
|
||||
|
||||
return (void *)sess;
|
||||
return (void *)sess;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT void
|
||||
openvpn_plugin_client_destructor_v1(openvpn_plugin_handle_t handle, void *ctx)
|
||||
{
|
||||
struct plugin *plugin = (struct plugin *)handle;
|
||||
struct session *sess = (struct session *)ctx;
|
||||
struct plugin *plugin = (struct plugin *)handle;
|
||||
struct session *sess = (struct session *)ctx;
|
||||
|
||||
ovpn_note("app session key: %s", sess->key);
|
||||
ovpn_note("app session destroyed");
|
||||
ovpn_note("app session key: %s", sess->key);
|
||||
ovpn_note("app session destroyed");
|
||||
|
||||
free (sess);
|
||||
free(sess);
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT void
|
||||
openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
|
||||
openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
|
||||
{
|
||||
struct plugin *plugin = (struct plugin *)handle;
|
||||
free (plugin);
|
||||
struct plugin *plugin = (struct plugin *)handle;
|
||||
free(plugin);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@
|
|||
* Our context, where we keep our state.
|
||||
*/
|
||||
struct plugin_context {
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *username;
|
||||
const char *password;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -49,136 +49,154 @@ struct plugin_context {
|
|||
* if found or NULL otherwise.
|
||||
*/
|
||||
static const char *
|
||||
get_env (const char *name, const char *envp[])
|
||||
get_env(const char *name, const char *envp[])
|
||||
{
|
||||
if (envp)
|
||||
if (envp)
|
||||
{
|
||||
int i;
|
||||
const int namelen = strlen (name);
|
||||
for (i = 0; envp[i]; ++i)
|
||||
{
|
||||
if (!strncmp (envp[i], name, namelen))
|
||||
{
|
||||
const char *cp = envp[i] + namelen;
|
||||
if (*cp == '=')
|
||||
return cp + 1;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
const int namelen = strlen(name);
|
||||
for (i = 0; envp[i]; ++i)
|
||||
{
|
||||
if (!strncmp(envp[i], name, namelen))
|
||||
{
|
||||
const char *cp = envp[i] + namelen;
|
||||
if (*cp == '=')
|
||||
{
|
||||
return cp + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT openvpn_plugin_handle_t
|
||||
openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
|
||||
openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[])
|
||||
{
|
||||
struct plugin_context *context;
|
||||
struct plugin_context *context;
|
||||
|
||||
/*
|
||||
* Allocate our context
|
||||
*/
|
||||
context = (struct plugin_context *) calloc (1, sizeof (struct plugin_context));
|
||||
/*
|
||||
* Allocate our context
|
||||
*/
|
||||
context = (struct plugin_context *) calloc(1, sizeof(struct plugin_context));
|
||||
|
||||
/*
|
||||
* Set the username/password we will require.
|
||||
*/
|
||||
context->username = "foo";
|
||||
context->password = "bar";
|
||||
/*
|
||||
* Set the username/password we will require.
|
||||
*/
|
||||
context->username = "foo";
|
||||
context->password = "bar";
|
||||
|
||||
/*
|
||||
* Which callbacks to intercept.
|
||||
*/
|
||||
*type_mask =
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_ROUTE_UP) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_IPCHANGE) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_TLS_VERIFY) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_CLIENT_CONNECT_V2) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_CLIENT_DISCONNECT) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_LEARN_ADDRESS) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_TLS_FINAL);
|
||||
/*
|
||||
* Which callbacks to intercept.
|
||||
*/
|
||||
*type_mask =
|
||||
OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_UP)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_DOWN)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_ROUTE_UP)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_IPCHANGE)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_VERIFY)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_CONNECT_V2)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_DISCONNECT)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_LEARN_ADDRESS)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_FINAL);
|
||||
|
||||
return (openvpn_plugin_handle_t) context;
|
||||
return (openvpn_plugin_handle_t) context;
|
||||
}
|
||||
|
||||
void
|
||||
show (const int type, const char *argv[], const char *envp[])
|
||||
show(const int type, const char *argv[], const char *envp[])
|
||||
{
|
||||
size_t i;
|
||||
switch (type)
|
||||
size_t i;
|
||||
switch (type)
|
||||
{
|
||||
case OPENVPN_PLUGIN_UP:
|
||||
printf ("OPENVPN_PLUGIN_UP\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_DOWN:
|
||||
printf ("OPENVPN_PLUGIN_DOWN\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_ROUTE_UP:
|
||||
printf ("OPENVPN_PLUGIN_ROUTE_UP\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_IPCHANGE:
|
||||
printf ("OPENVPN_PLUGIN_IPCHANGE\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_TLS_VERIFY:
|
||||
printf ("OPENVPN_PLUGIN_TLS_VERIFY\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
|
||||
printf ("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_CLIENT_CONNECT_V2:
|
||||
printf ("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_CLIENT_DISCONNECT:
|
||||
printf ("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_LEARN_ADDRESS:
|
||||
printf ("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_TLS_FINAL:
|
||||
printf ("OPENVPN_PLUGIN_TLS_FINAL\n");
|
||||
break;
|
||||
default:
|
||||
printf ("OPENVPN_PLUGIN_?\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_UP:
|
||||
printf("OPENVPN_PLUGIN_UP\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_DOWN:
|
||||
printf("OPENVPN_PLUGIN_DOWN\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_ROUTE_UP:
|
||||
printf("OPENVPN_PLUGIN_ROUTE_UP\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_IPCHANGE:
|
||||
printf("OPENVPN_PLUGIN_IPCHANGE\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_TLS_VERIFY:
|
||||
printf("OPENVPN_PLUGIN_TLS_VERIFY\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
|
||||
printf("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_CLIENT_CONNECT_V2:
|
||||
printf("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_CLIENT_DISCONNECT:
|
||||
printf("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_LEARN_ADDRESS:
|
||||
printf("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_TLS_FINAL:
|
||||
printf("OPENVPN_PLUGIN_TLS_FINAL\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("OPENVPN_PLUGIN_?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
printf ("ARGV\n");
|
||||
for (i = 0; argv[i] != NULL; ++i)
|
||||
printf ("%d '%s'\n", (int)i, argv[i]);
|
||||
printf("ARGV\n");
|
||||
for (i = 0; argv[i] != NULL; ++i)
|
||||
printf("%d '%s'\n", (int)i, argv[i]);
|
||||
|
||||
printf ("ENVP\n");
|
||||
for (i = 0; envp[i] != NULL; ++i)
|
||||
printf ("%d '%s'\n", (int)i, envp[i]);
|
||||
printf("ENVP\n");
|
||||
for (i = 0; envp[i] != NULL; ++i)
|
||||
printf("%d '%s'\n", (int)i, envp[i]);
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT int
|
||||
openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
|
||||
openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
|
||||
{
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
|
||||
show (type, argv, envp);
|
||||
show(type, argv, envp);
|
||||
|
||||
/* check entered username/password against what we require */
|
||||
if (type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
|
||||
/* check entered username/password against what we require */
|
||||
if (type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
|
||||
{
|
||||
/* get username/password from envp string array */
|
||||
const char *username = get_env ("username", envp);
|
||||
const char *password = get_env ("password", envp);
|
||||
/* get username/password from envp string array */
|
||||
const char *username = get_env("username", envp);
|
||||
const char *password = get_env("password", envp);
|
||||
|
||||
if (username && !strcmp (username, context->username)
|
||||
&& password && !strcmp (password, context->password))
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
if (username && !strcmp(username, context->username)
|
||||
&& password && !strcmp(password, context->password))
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT void
|
||||
openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
|
||||
openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
|
||||
{
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
free (context);
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
free(context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@
|
|||
* Our context, where we keep our state.
|
||||
*/
|
||||
struct plugin_context {
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *username;
|
||||
const char *password;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -54,205 +54,238 @@ struct plugin_context {
|
|||
* if found or NULL otherwise.
|
||||
*/
|
||||
static const char *
|
||||
get_env (const char *name, const char *envp[])
|
||||
get_env(const char *name, const char *envp[])
|
||||
{
|
||||
if (envp)
|
||||
if (envp)
|
||||
{
|
||||
int i;
|
||||
const int namelen = strlen (name);
|
||||
for (i = 0; envp[i]; ++i)
|
||||
{
|
||||
if (!strncmp (envp[i], name, namelen))
|
||||
{
|
||||
const char *cp = envp[i] + namelen;
|
||||
if (*cp == '=')
|
||||
return cp + 1;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
const int namelen = strlen(name);
|
||||
for (i = 0; envp[i]; ++i)
|
||||
{
|
||||
if (!strncmp(envp[i], name, namelen))
|
||||
{
|
||||
const char *cp = envp[i] + namelen;
|
||||
if (*cp == '=')
|
||||
{
|
||||
return cp + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT int
|
||||
openvpn_plugin_open_v3 (const int v3structver,
|
||||
struct openvpn_plugin_args_open_in const *args,
|
||||
struct openvpn_plugin_args_open_return *ret)
|
||||
openvpn_plugin_open_v3(const int v3structver,
|
||||
struct openvpn_plugin_args_open_in const *args,
|
||||
struct openvpn_plugin_args_open_return *ret)
|
||||
{
|
||||
struct plugin_context *context = NULL;
|
||||
struct plugin_context *context = NULL;
|
||||
|
||||
/* Check that we are API compatible */
|
||||
if( v3structver != OPENVPN_PLUGINv3_STRUCTVER ) {
|
||||
printf("log_v3: ** ERROR ** Incompatible plug-in interface between this plug-in and OpenVPN\n");
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
|
||||
if( args->ssl_api != SSLAPI_OPENSSL ) {
|
||||
printf("This plug-in can only be used against OpenVPN with OpenSSL\n");
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
|
||||
/* Print some version information about the OpenVPN process using this plug-in */
|
||||
printf("log_v3: OpenVPN %s (Major: %i, Minor: %i, Patch: %s)\n",
|
||||
args->ovpn_version, args->ovpn_version_major,
|
||||
args->ovpn_version_minor, args->ovpn_version_patch);
|
||||
|
||||
/* Which callbacks to intercept. */
|
||||
ret->type_mask =
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_UP) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_DOWN) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_ROUTE_UP) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_IPCHANGE) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_TLS_VERIFY) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_CLIENT_CONNECT_V2) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_CLIENT_DISCONNECT) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_LEARN_ADDRESS) |
|
||||
OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_TLS_FINAL);
|
||||
|
||||
|
||||
/* Allocate our context */
|
||||
context = (struct plugin_context *) calloc (1, sizeof (struct plugin_context));
|
||||
|
||||
/* Set the username/password we will require. */
|
||||
context->username = "foo";
|
||||
context->password = "bar";
|
||||
|
||||
/* Point the global context handle to our newly created context */
|
||||
ret->handle = (void *) context;
|
||||
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
show (const int type, const char *argv[], const char *envp[])
|
||||
{
|
||||
size_t i;
|
||||
switch (type)
|
||||
/* Check that we are API compatible */
|
||||
if (v3structver != OPENVPN_PLUGINv3_STRUCTVER)
|
||||
{
|
||||
case OPENVPN_PLUGIN_UP:
|
||||
printf ("OPENVPN_PLUGIN_UP\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_DOWN:
|
||||
printf ("OPENVPN_PLUGIN_DOWN\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_ROUTE_UP:
|
||||
printf ("OPENVPN_PLUGIN_ROUTE_UP\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_IPCHANGE:
|
||||
printf ("OPENVPN_PLUGIN_IPCHANGE\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_TLS_VERIFY:
|
||||
printf ("OPENVPN_PLUGIN_TLS_VERIFY\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
|
||||
printf ("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_CLIENT_CONNECT_V2:
|
||||
printf ("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_CLIENT_DISCONNECT:
|
||||
printf ("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_LEARN_ADDRESS:
|
||||
printf ("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
|
||||
break;
|
||||
case OPENVPN_PLUGIN_TLS_FINAL:
|
||||
printf ("OPENVPN_PLUGIN_TLS_FINAL\n");
|
||||
break;
|
||||
default:
|
||||
printf ("OPENVPN_PLUGIN_?\n");
|
||||
break;
|
||||
printf("log_v3: ** ERROR ** Incompatible plug-in interface between this plug-in and OpenVPN\n");
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
|
||||
printf ("ARGV\n");
|
||||
for (i = 0; argv[i] != NULL; ++i)
|
||||
printf ("%d '%s'\n", (int)i, argv[i]);
|
||||
|
||||
printf ("ENVP\n");
|
||||
for (i = 0; envp[i] != NULL; ++i)
|
||||
printf ("%d '%s'\n", (int)i, envp[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
x509_print_info (X509 *x509crt)
|
||||
{
|
||||
int i, n;
|
||||
int fn_nid;
|
||||
ASN1_OBJECT *fn;
|
||||
ASN1_STRING *val;
|
||||
X509_NAME *x509_name;
|
||||
X509_NAME_ENTRY *ent;
|
||||
const char *objbuf;
|
||||
unsigned char *buf;
|
||||
|
||||
x509_name = X509_get_subject_name (x509crt);
|
||||
n = X509_NAME_entry_count (x509_name);
|
||||
for (i = 0; i < n; ++i)
|
||||
if (args->ssl_api != SSLAPI_OPENSSL)
|
||||
{
|
||||
ent = X509_NAME_get_entry (x509_name, i);
|
||||
if (!ent)
|
||||
continue;
|
||||
fn = X509_NAME_ENTRY_get_object (ent);
|
||||
if (!fn)
|
||||
continue;
|
||||
val = X509_NAME_ENTRY_get_data (ent);
|
||||
if (!val)
|
||||
continue;
|
||||
fn_nid = OBJ_obj2nid (fn);
|
||||
if (fn_nid == NID_undef)
|
||||
continue;
|
||||
objbuf = OBJ_nid2sn (fn_nid);
|
||||
if (!objbuf)
|
||||
continue;
|
||||
buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
|
||||
if (ASN1_STRING_to_UTF8 (&buf, val) <= 0)
|
||||
continue;
|
||||
|
||||
printf("X509 %s: %s\n", objbuf, (char *)buf);
|
||||
OPENSSL_free (buf);
|
||||
printf("This plug-in can only be used against OpenVPN with OpenSSL\n");
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print some version information about the OpenVPN process using this plug-in */
|
||||
printf("log_v3: OpenVPN %s (Major: %i, Minor: %i, Patch: %s)\n",
|
||||
args->ovpn_version, args->ovpn_version_major,
|
||||
args->ovpn_version_minor, args->ovpn_version_patch);
|
||||
|
||||
/* Which callbacks to intercept. */
|
||||
ret->type_mask =
|
||||
OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_UP)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_DOWN)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_ROUTE_UP)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_IPCHANGE)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_VERIFY)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_CONNECT_V2)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_CLIENT_DISCONNECT)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_LEARN_ADDRESS)
|
||||
|OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_TLS_FINAL);
|
||||
|
||||
|
||||
/* Allocate our context */
|
||||
context = (struct plugin_context *) calloc(1, sizeof(struct plugin_context));
|
||||
|
||||
OPENVPN_EXPORT int
|
||||
openvpn_plugin_func_v3 (const int version,
|
||||
struct openvpn_plugin_args_func_in const *args,
|
||||
struct openvpn_plugin_args_func_return *retptr)
|
||||
{
|
||||
struct plugin_context *context = (struct plugin_context *) args->handle;
|
||||
/* Set the username/password we will require. */
|
||||
context->username = "foo";
|
||||
context->password = "bar";
|
||||
|
||||
printf("\nopenvpn_plugin_func_v3() :::::>> ");
|
||||
show (args->type, args->argv, args->envp);
|
||||
/* Point the global context handle to our newly created context */
|
||||
ret->handle = (void *) context;
|
||||
|
||||
/* Dump some X509 information if we're in the TLS_VERIFY phase */
|
||||
if ((args->type == OPENVPN_PLUGIN_TLS_VERIFY) && args->current_cert ) {
|
||||
printf("---- X509 Subject information ----\n");
|
||||
printf("Certificate depth: %i\n", args->current_cert_depth);
|
||||
x509_print_info(args->current_cert);
|
||||
printf("----------------------------------\n");
|
||||
}
|
||||
|
||||
/* check entered username/password against what we require */
|
||||
if (args->type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
|
||||
{
|
||||
/* get username/password from envp string array */
|
||||
const char *username = get_env ("username", args->envp);
|
||||
const char *password = get_env ("password", args->envp);
|
||||
|
||||
if (username && !strcmp (username, context->username)
|
||||
&& password && !strcmp (password, context->password))
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT void
|
||||
openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
|
||||
void
|
||||
show(const int type, const char *argv[], const char *envp[])
|
||||
{
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
free (context);
|
||||
size_t i;
|
||||
switch (type)
|
||||
{
|
||||
case OPENVPN_PLUGIN_UP:
|
||||
printf("OPENVPN_PLUGIN_UP\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_DOWN:
|
||||
printf("OPENVPN_PLUGIN_DOWN\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_ROUTE_UP:
|
||||
printf("OPENVPN_PLUGIN_ROUTE_UP\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_IPCHANGE:
|
||||
printf("OPENVPN_PLUGIN_IPCHANGE\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_TLS_VERIFY:
|
||||
printf("OPENVPN_PLUGIN_TLS_VERIFY\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
|
||||
printf("OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_CLIENT_CONNECT_V2:
|
||||
printf("OPENVPN_PLUGIN_CLIENT_CONNECT_V2\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_CLIENT_DISCONNECT:
|
||||
printf("OPENVPN_PLUGIN_CLIENT_DISCONNECT\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_LEARN_ADDRESS:
|
||||
printf("OPENVPN_PLUGIN_LEARN_ADDRESS\n");
|
||||
break;
|
||||
|
||||
case OPENVPN_PLUGIN_TLS_FINAL:
|
||||
printf("OPENVPN_PLUGIN_TLS_FINAL\n");
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("OPENVPN_PLUGIN_?\n");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("ARGV\n");
|
||||
for (i = 0; argv[i] != NULL; ++i)
|
||||
printf("%d '%s'\n", (int)i, argv[i]);
|
||||
|
||||
printf("ENVP\n");
|
||||
for (i = 0; envp[i] != NULL; ++i)
|
||||
printf("%d '%s'\n", (int)i, envp[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
x509_print_info(X509 *x509crt)
|
||||
{
|
||||
int i, n;
|
||||
int fn_nid;
|
||||
ASN1_OBJECT *fn;
|
||||
ASN1_STRING *val;
|
||||
X509_NAME *x509_name;
|
||||
X509_NAME_ENTRY *ent;
|
||||
const char *objbuf;
|
||||
unsigned char *buf;
|
||||
|
||||
x509_name = X509_get_subject_name(x509crt);
|
||||
n = X509_NAME_entry_count(x509_name);
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
ent = X509_NAME_get_entry(x509_name, i);
|
||||
if (!ent)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fn = X509_NAME_ENTRY_get_object(ent);
|
||||
if (!fn)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
val = X509_NAME_ENTRY_get_data(ent);
|
||||
if (!val)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fn_nid = OBJ_obj2nid(fn);
|
||||
if (fn_nid == NID_undef)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
objbuf = OBJ_nid2sn(fn_nid);
|
||||
if (!objbuf)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
buf = (unsigned char *)1; /* bug in OpenSSL 0.9.6b ASN1_STRING_to_UTF8 requires this workaround */
|
||||
if (ASN1_STRING_to_UTF8(&buf, val) <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("X509 %s: %s\n", objbuf, (char *)buf);
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
OPENVPN_EXPORT int
|
||||
openvpn_plugin_func_v3(const int version,
|
||||
struct openvpn_plugin_args_func_in const *args,
|
||||
struct openvpn_plugin_args_func_return *retptr)
|
||||
{
|
||||
struct plugin_context *context = (struct plugin_context *) args->handle;
|
||||
|
||||
printf("\nopenvpn_plugin_func_v3() :::::>> ");
|
||||
show(args->type, args->argv, args->envp);
|
||||
|
||||
/* Dump some X509 information if we're in the TLS_VERIFY phase */
|
||||
if ((args->type == OPENVPN_PLUGIN_TLS_VERIFY) && args->current_cert)
|
||||
{
|
||||
printf("---- X509 Subject information ----\n");
|
||||
printf("Certificate depth: %i\n", args->current_cert_depth);
|
||||
x509_print_info(args->current_cert);
|
||||
printf("----------------------------------\n");
|
||||
}
|
||||
|
||||
/* check entered username/password against what we require */
|
||||
if (args->type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY)
|
||||
{
|
||||
/* get username/password from envp string array */
|
||||
const char *username = get_env("username", args->envp);
|
||||
const char *password = get_env("password", args->envp);
|
||||
|
||||
if (username && !strcmp(username, context->username)
|
||||
&& password && !strcmp(password, context->password))
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT void
|
||||
openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
|
||||
{
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
free(context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@
|
|||
* Our context, where we keep our state.
|
||||
*/
|
||||
struct plugin_context {
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *username;
|
||||
const char *password;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -51,70 +51,76 @@ struct plugin_context {
|
|||
* if found or NULL otherwise.
|
||||
*/
|
||||
static const char *
|
||||
get_env (const char *name, const char *envp[])
|
||||
get_env(const char *name, const char *envp[])
|
||||
{
|
||||
if (envp)
|
||||
if (envp)
|
||||
{
|
||||
int i;
|
||||
const int namelen = strlen (name);
|
||||
for (i = 0; envp[i]; ++i)
|
||||
{
|
||||
if (!strncmp (envp[i], name, namelen))
|
||||
{
|
||||
const char *cp = envp[i] + namelen;
|
||||
if (*cp == '=')
|
||||
return cp + 1;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
const int namelen = strlen(name);
|
||||
for (i = 0; envp[i]; ++i)
|
||||
{
|
||||
if (!strncmp(envp[i], name, namelen))
|
||||
{
|
||||
const char *cp = envp[i] + namelen;
|
||||
if (*cp == '=')
|
||||
{
|
||||
return cp + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT openvpn_plugin_handle_t
|
||||
openvpn_plugin_open_v1 (unsigned int *type_mask, const char *argv[], const char *envp[])
|
||||
openvpn_plugin_open_v1(unsigned int *type_mask, const char *argv[], const char *envp[])
|
||||
{
|
||||
struct plugin_context *context;
|
||||
struct plugin_context *context;
|
||||
|
||||
/*
|
||||
* Allocate our context
|
||||
*/
|
||||
context = (struct plugin_context *) calloc (1, sizeof (struct plugin_context));
|
||||
/*
|
||||
* Allocate our context
|
||||
*/
|
||||
context = (struct plugin_context *) calloc(1, sizeof(struct plugin_context));
|
||||
|
||||
/*
|
||||
* Set the username/password we will require.
|
||||
*/
|
||||
context->username = "foo";
|
||||
context->password = "bar";
|
||||
/*
|
||||
* Set the username/password we will require.
|
||||
*/
|
||||
context->username = "foo";
|
||||
context->password = "bar";
|
||||
|
||||
/*
|
||||
* We are only interested in intercepting the
|
||||
* --auth-user-pass-verify callback.
|
||||
*/
|
||||
*type_mask = OPENVPN_PLUGIN_MASK (OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY);
|
||||
/*
|
||||
* We are only interested in intercepting the
|
||||
* --auth-user-pass-verify callback.
|
||||
*/
|
||||
*type_mask = OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY);
|
||||
|
||||
return (openvpn_plugin_handle_t) context;
|
||||
return (openvpn_plugin_handle_t) context;
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT int
|
||||
openvpn_plugin_func_v1 (openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
|
||||
openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
|
||||
{
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
|
||||
/* get username/password from envp string array */
|
||||
const char *username = get_env ("username", envp);
|
||||
const char *password = get_env ("password", envp);
|
||||
/* get username/password from envp string array */
|
||||
const char *username = get_env("username", envp);
|
||||
const char *password = get_env("password", envp);
|
||||
|
||||
/* check entered username/password against what we require */
|
||||
if (username && !strcmp (username, context->username)
|
||||
&& password && !strcmp (password, context->password))
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
else
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
/* check entered username/password against what we require */
|
||||
if (username && !strcmp(username, context->username)
|
||||
&& password && !strcmp(password, context->password))
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OPENVPN_PLUGIN_FUNC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
OPENVPN_EXPORT void
|
||||
openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
|
||||
openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
|
||||
{
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
free (context);
|
||||
struct plugin_context *context = (struct plugin_context *) handle;
|
||||
free(context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,14 +37,15 @@
|
|||
* This version is extended to handle both / and \ in path names
|
||||
*/
|
||||
char *
|
||||
basename (char *filename)
|
||||
basename(char *filename)
|
||||
{
|
||||
char *p = strrchr (filename, '/');
|
||||
if (!p) {
|
||||
/* If NULL, check for \ instead ... might be Windows a path */
|
||||
p = strrchr (filename, '\\');
|
||||
}
|
||||
return p ? p + 1 : (char *) filename;
|
||||
char *p = strrchr(filename, '/');
|
||||
if (!p)
|
||||
{
|
||||
/* If NULL, check for \ instead ... might be Windows a path */
|
||||
p = strrchr(filename, '\\');
|
||||
}
|
||||
return p ? p + 1 : (char *) filename;
|
||||
}
|
||||
|
||||
#endif /* HAVE_BASENAME */
|
||||
|
|
|
|||
|
|
@ -58,43 +58,52 @@ int
|
|||
daemon(int nochdir, int noclose)
|
||||
{
|
||||
#if defined(HAVE_FORK) && defined(HAVE_SETSID)
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
return (-1);
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
exit(0);
|
||||
}
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
return (-1);
|
||||
|
||||
if (setsid() == -1)
|
||||
return (-1);
|
||||
case 0:
|
||||
break;
|
||||
|
||||
if (!nochdir)
|
||||
chdir("/");
|
||||
default:
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!noclose) {
|
||||
if (setsid() == -1)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (!nochdir)
|
||||
{
|
||||
chdir("/");
|
||||
}
|
||||
|
||||
if (!noclose)
|
||||
{
|
||||
#if defined(HAVE_DUP) && defined(HAVE_DUP2)
|
||||
int fd;
|
||||
if ((fd = open ("/dev/null", O_RDWR, 0)) != -1) {
|
||||
dup2 (fd, 0);
|
||||
dup2 (fd, 1);
|
||||
dup2 (fd, 2);
|
||||
if (fd > 2) {
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
int fd;
|
||||
if ((fd = open("/dev/null", O_RDWR, 0)) != -1)
|
||||
{
|
||||
dup2(fd, 0);
|
||||
dup2(fd, 1);
|
||||
dup2(fd, 2);
|
||||
if (fd > 2)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
(void)nochdir;
|
||||
(void)noclose;
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
#endif
|
||||
return 0;
|
||||
#else /* if defined(HAVE_FORK) && defined(HAVE_SETSID) */
|
||||
(void)nochdir;
|
||||
(void)noclose;
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
#endif /* if defined(HAVE_FORK) && defined(HAVE_SETSID) */
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* ifndef HAVE_DAEMON */
|
||||
|
||||
|
|
|
|||
|
|
@ -41,79 +41,102 @@
|
|||
static const char *
|
||||
__memrchr(const char *str, int c, size_t n)
|
||||
{
|
||||
const char *end = str;
|
||||
const char *end = str;
|
||||
|
||||
end += n - 1; /* Go to the end of the string */
|
||||
while (end >= str) {
|
||||
if(c == *end)
|
||||
return end;
|
||||
else
|
||||
end--;
|
||||
}
|
||||
return NULL;
|
||||
end += n - 1; /* Go to the end of the string */
|
||||
while (end >= str) {
|
||||
if (c == *end)
|
||||
{
|
||||
return end;
|
||||
}
|
||||
else
|
||||
{
|
||||
end--;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Modified version based on glibc-2.14.1 by Ulrich Drepper <drepper@akkadia.org>
|
||||
* This version is extended to handle both / and \ in path names.
|
||||
*/
|
||||
char *
|
||||
dirname (char *path)
|
||||
dirname(char *path)
|
||||
{
|
||||
static const char dot[] = ".";
|
||||
char *last_slash;
|
||||
char separator = '/';
|
||||
static const char dot[] = ".";
|
||||
char *last_slash;
|
||||
char separator = '/';
|
||||
|
||||
/* Find last '/'. */
|
||||
last_slash = path != NULL ? strrchr (path, '/') : NULL;
|
||||
/* If NULL, check for \ instead ... might be Windows a path */
|
||||
if (!last_slash) {
|
||||
last_slash = path != NULL ? strrchr (path, '\\') : NULL;
|
||||
separator = last_slash ? '\\' : '/'; /* Change the separator if \ was found */
|
||||
}
|
||||
|
||||
if (last_slash != NULL && last_slash != path && last_slash[1] == '\0') {
|
||||
/* Determine whether all remaining characters are slashes. */
|
||||
char *runp;
|
||||
|
||||
for (runp = last_slash; runp != path; --runp)
|
||||
if (runp[-1] != separator)
|
||||
break;
|
||||
|
||||
/* The '/' is the last character, we have to look further. */
|
||||
if (runp != path)
|
||||
last_slash = (char *) __memrchr (path, separator, runp - path);
|
||||
/* Find last '/'. */
|
||||
last_slash = path != NULL ? strrchr(path, '/') : NULL;
|
||||
/* If NULL, check for \ instead ... might be Windows a path */
|
||||
if (!last_slash)
|
||||
{
|
||||
last_slash = path != NULL ? strrchr(path, '\\') : NULL;
|
||||
separator = last_slash ? '\\' : '/'; /* Change the separator if \ was found */
|
||||
}
|
||||
|
||||
if (last_slash != NULL) {
|
||||
/* Determine whether all remaining characters are slashes. */
|
||||
char *runp;
|
||||
if (last_slash != NULL && last_slash != path && last_slash[1] == '\0')
|
||||
{
|
||||
/* Determine whether all remaining characters are slashes. */
|
||||
char *runp;
|
||||
|
||||
for (runp = last_slash; runp != path; --runp)
|
||||
if (runp[-1] != separator)
|
||||
break;
|
||||
for (runp = last_slash; runp != path; --runp)
|
||||
if (runp[-1] != separator)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Terminate the path. */
|
||||
if (runp == path) {
|
||||
/* The last slash is the first character in the string. We have to
|
||||
return "/". As a special case we have to return "//" if there
|
||||
are exactly two slashes at the beginning of the string. See
|
||||
XBD 4.10 Path Name Resolution for more information. */
|
||||
if (last_slash == path + 1)
|
||||
++last_slash;
|
||||
else
|
||||
last_slash = path + 1;
|
||||
}
|
||||
else
|
||||
last_slash = runp;
|
||||
/* The '/' is the last character, we have to look further. */
|
||||
if (runp != path)
|
||||
{
|
||||
last_slash = (char *) __memrchr(path, separator, runp - path);
|
||||
}
|
||||
}
|
||||
|
||||
last_slash[0] = '\0';
|
||||
} else
|
||||
/* This assignment is ill-designed but the XPG specs require to
|
||||
return a string containing "." in any case no directory part is
|
||||
found and so a static and constant string is required. */
|
||||
path = (char *) dot;
|
||||
if (last_slash != NULL)
|
||||
{
|
||||
/* Determine whether all remaining characters are slashes. */
|
||||
char *runp;
|
||||
|
||||
return path;
|
||||
for (runp = last_slash; runp != path; --runp)
|
||||
if (runp[-1] != separator)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Terminate the path. */
|
||||
if (runp == path)
|
||||
{
|
||||
/* The last slash is the first character in the string. We have to
|
||||
* return "/". As a special case we have to return "//" if there
|
||||
* are exactly two slashes at the beginning of the string. See
|
||||
* XBD 4.10 Path Name Resolution for more information. */
|
||||
if (last_slash == path + 1)
|
||||
{
|
||||
++last_slash;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_slash = path + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
last_slash = runp;
|
||||
}
|
||||
|
||||
last_slash[0] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This assignment is ill-designed but the XPG specs require to
|
||||
* return a string containing "." in any case no directory part is
|
||||
* found and so a static and constant string is required. */
|
||||
path = (char *) dot;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
#endif /* HAVE_DIRNAME */
|
||||
|
|
|
|||
|
|
@ -48,12 +48,12 @@ static unsigned int last_msec = 0;
|
|||
static int bt_last = 0;
|
||||
|
||||
static void
|
||||
gettimeofday_calibrate (void)
|
||||
gettimeofday_calibrate(void)
|
||||
{
|
||||
const time_t t = time(NULL);
|
||||
const DWORD gtc = GetTickCount();
|
||||
gtc_base = t - gtc/1000;
|
||||
gtc_last = gtc;
|
||||
const time_t t = time(NULL);
|
||||
const DWORD gtc = GetTickCount();
|
||||
gtc_base = t - gtc/1000;
|
||||
gtc_last = gtc;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -62,68 +62,72 @@ gettimeofday_calibrate (void)
|
|||
* more processor cycles than GetTickCount.
|
||||
*/
|
||||
int
|
||||
gettimeofday (struct timeval *tv, void *tz)
|
||||
gettimeofday(struct timeval *tv, void *tz)
|
||||
{
|
||||
const DWORD gtc = GetTickCount();
|
||||
int bt = 0;
|
||||
time_t sec;
|
||||
unsigned int msec;
|
||||
const int backtrack_hold_seconds = 10;
|
||||
const DWORD gtc = GetTickCount();
|
||||
int bt = 0;
|
||||
time_t sec;
|
||||
unsigned int msec;
|
||||
const int backtrack_hold_seconds = 10;
|
||||
|
||||
(void)tz;
|
||||
(void)tz;
|
||||
|
||||
/* recalibrate at the dreaded 49.7 day mark */
|
||||
if (!gtc_base || gtc < gtc_last)
|
||||
gettimeofday_calibrate ();
|
||||
gtc_last = gtc;
|
||||
|
||||
sec = gtc_base + gtc / 1000;
|
||||
msec = gtc % 1000;
|
||||
|
||||
if (sec == last_sec)
|
||||
/* recalibrate at the dreaded 49.7 day mark */
|
||||
if (!gtc_base || gtc < gtc_last)
|
||||
{
|
||||
if (msec < last_msec)
|
||||
{
|
||||
msec = last_msec;
|
||||
bt = 1;
|
||||
}
|
||||
gettimeofday_calibrate();
|
||||
}
|
||||
else if (sec < last_sec)
|
||||
gtc_last = gtc;
|
||||
|
||||
sec = gtc_base + gtc / 1000;
|
||||
msec = gtc % 1000;
|
||||
|
||||
if (sec == last_sec)
|
||||
{
|
||||
/* We try to dampen out backtracks of less than backtrack_hold_seconds.
|
||||
Larger backtracks will be passed through and dealt with by the
|
||||
TIME_BACKTRACK_PROTECTION code (if enabled) */
|
||||
if (sec > last_sec - backtrack_hold_seconds)
|
||||
{
|
||||
sec = last_sec;
|
||||
msec = last_msec;
|
||||
}
|
||||
bt = 1;
|
||||
if (msec < last_msec)
|
||||
{
|
||||
msec = last_msec;
|
||||
bt = 1;
|
||||
}
|
||||
}
|
||||
else if (sec < last_sec)
|
||||
{
|
||||
/* We try to dampen out backtracks of less than backtrack_hold_seconds.
|
||||
* Larger backtracks will be passed through and dealt with by the
|
||||
* TIME_BACKTRACK_PROTECTION code (if enabled) */
|
||||
if (sec > last_sec - backtrack_hold_seconds)
|
||||
{
|
||||
sec = last_sec;
|
||||
msec = last_msec;
|
||||
}
|
||||
bt = 1;
|
||||
}
|
||||
|
||||
tv->tv_sec = (long)last_sec = (long)sec;
|
||||
tv->tv_usec = (last_msec = msec) * 1000;
|
||||
tv->tv_sec = (long)last_sec = (long)sec;
|
||||
tv->tv_usec = (last_msec = msec) * 1000;
|
||||
|
||||
if (bt && !bt_last)
|
||||
gettimeofday_calibrate ();
|
||||
bt_last = bt;
|
||||
if (bt && !bt_last)
|
||||
{
|
||||
gettimeofday_calibrate();
|
||||
}
|
||||
bt_last = bt;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* ifdef _WIN32 */
|
||||
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
gettimeofday (struct timeval *tv, void *tz)
|
||||
gettimeofday(struct timeval *tv, void *tz)
|
||||
{
|
||||
(void)tz;
|
||||
tv->tv_sec = time(NULL);
|
||||
tv->tv_usec = 0;
|
||||
return 0;
|
||||
(void)tz;
|
||||
tv->tv_sec = time(NULL);
|
||||
tv->tv_usec = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
|
|
|||
|
|
@ -46,31 +46,33 @@
|
|||
const char *
|
||||
inet_ntop(int af, const void *src, char *dst, socklen_t size)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
unsigned long s = size;
|
||||
struct sockaddr_storage ss;
|
||||
unsigned long s = size;
|
||||
|
||||
ZeroMemory(&ss, sizeof(ss));
|
||||
ss.ss_family = af;
|
||||
ZeroMemory(&ss, sizeof(ss));
|
||||
ss.ss_family = af;
|
||||
|
||||
switch(af) {
|
||||
case AF_INET:
|
||||
((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
|
||||
break;
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
/* cannot direclty use &size because of strict aliasing rules */
|
||||
return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0)?
|
||||
dst : NULL;
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src;
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src;
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
/* cannot direclty use &size because of strict aliasing rules */
|
||||
return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0) ?
|
||||
dst : NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* ifdef _WIN32 */
|
||||
|
||||
#error no emulation for inet_ntop
|
||||
|
||||
#endif
|
||||
#endif /* ifdef _WIN32 */
|
||||
|
||||
#endif
|
||||
#endif /* ifndef HAVE_INET_NTOP */
|
||||
|
|
|
|||
|
|
@ -48,32 +48,34 @@
|
|||
int
|
||||
inet_pton(int af, const char *src, void *dst)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
int size = sizeof(ss);
|
||||
char src_copy[INET6_ADDRSTRLEN+1];
|
||||
struct sockaddr_storage ss;
|
||||
int size = sizeof(ss);
|
||||
char src_copy[INET6_ADDRSTRLEN+1];
|
||||
|
||||
ZeroMemory(&ss, sizeof(ss));
|
||||
/* stupid non-const API */
|
||||
strncpy (src_copy, src, INET6_ADDRSTRLEN+1);
|
||||
src_copy[INET6_ADDRSTRLEN] = 0;
|
||||
ZeroMemory(&ss, sizeof(ss));
|
||||
/* stupid non-const API */
|
||||
strncpy(src_copy, src, INET6_ADDRSTRLEN+1);
|
||||
src_copy[INET6_ADDRSTRLEN] = 0;
|
||||
|
||||
if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0) {
|
||||
switch(af) {
|
||||
case AF_INET:
|
||||
*(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
|
||||
return 1;
|
||||
case AF_INET6:
|
||||
*(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
|
||||
return 1;
|
||||
if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) == 0)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
*(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr;
|
||||
return 1;
|
||||
|
||||
case AF_INET6:
|
||||
*(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* ifdef _WIN32 */
|
||||
|
||||
#error no emulation for inet_ntop
|
||||
|
||||
#endif
|
||||
#endif /* ifdef _WIN32 */
|
||||
|
||||
#endif
|
||||
#endif /* ifndef HAVE_INET_PTON */
|
||||
|
|
|
|||
|
|
@ -18,64 +18,77 @@
|
|||
|
||||
#define _WIN32_WINNT_WINBLUE 0x0603
|
||||
|
||||
VERSIONHELPERAPI IsWindowsVersionOrGreater(WORD major, WORD minor, WORD servpack)
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVersionOrGreater(WORD major, WORD minor, WORD servpack)
|
||||
{
|
||||
OSVERSIONINFOEXW vi = {sizeof(vi),major,minor,0,0,{0},servpack};
|
||||
return VerifyVersionInfoW(&vi, VER_MAJORVERSION|VER_MINORVERSION|VER_SERVICEPACKMAJOR,
|
||||
VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(0,
|
||||
VER_MAJORVERSION,VER_GREATER_EQUAL),
|
||||
VER_MINORVERSION,VER_GREATER_EQUAL),
|
||||
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL));
|
||||
VerSetConditionMask(VerSetConditionMask(VerSetConditionMask(0,
|
||||
VER_MAJORVERSION,VER_GREATER_EQUAL),
|
||||
VER_MINORVERSION,VER_GREATER_EQUAL),
|
||||
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL));
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindowsXPOrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPOrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 0);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindowsXPSP1OrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPSP1OrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 1);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindowsXPSP2OrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPSP2OrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 2);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindowsXPSP3OrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsXPSP3OrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINXP), LOBYTE(_WIN32_WINNT_WINXP), 3);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindowsVistaOrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVistaOrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 0);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindowsVistaSP1OrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVistaSP1OrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 1);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindowsVistaSP2OrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsVistaSP2OrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_VISTA), LOBYTE(_WIN32_WINNT_VISTA), 2);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindows7OrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindows7OrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 0);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindows7SP1OrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindows7SP1OrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN7), LOBYTE(_WIN32_WINNT_WIN7), 1);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindows8OrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindows8OrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WIN8), LOBYTE(_WIN32_WINNT_WIN8), 0);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindows8Point1OrGreater(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindows8Point1OrGreater(void) {
|
||||
return IsWindowsVersionOrGreater(HIBYTE(_WIN32_WINNT_WINBLUE), LOBYTE(_WIN32_WINNT_WINBLUE), 0);
|
||||
}
|
||||
|
||||
VERSIONHELPERAPI IsWindowsServer(void) {
|
||||
VERSIONHELPERAPI
|
||||
IsWindowsServer(void) {
|
||||
OSVERSIONINFOEXW vi = {sizeof(vi),0,0,0,0,{0},0,0,0,VER_NT_WORKSTATION};
|
||||
return !VerifyVersionInfoW(&vi, VER_PRODUCT_TYPE, VerSetConditionMask(0, VER_PRODUCT_TYPE, VER_EQUAL));
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif /* if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && !defined(__WIDL__) */
|
||||
#endif /* ifndef _INC_VERSIONHELPERS */
|
||||
|
|
|
|||
|
|
@ -42,27 +42,33 @@
|
|||
#endif
|
||||
|
||||
#ifndef HAVE_DIRNAME
|
||||
char * dirname(char *str);
|
||||
char *dirname(char *str);
|
||||
|
||||
#endif /* HAVE_DIRNAME */
|
||||
|
||||
#ifndef HAVE_BASENAME
|
||||
char * basename(char *str);
|
||||
char *basename(char *str);
|
||||
|
||||
#endif /* HAVE_BASENAME */
|
||||
|
||||
#ifndef HAVE_GETTIMEOFDAY
|
||||
int gettimeofday (struct timeval *tv, void *tz);
|
||||
int gettimeofday(struct timeval *tv, void *tz);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DAEMON
|
||||
int daemon(int nochdir, int noclose);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_INET_NTOP
|
||||
const char * inet_ntop(int af, const void *src, char *dst, socklen_t size);
|
||||
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_INET_PTON
|
||||
int inet_pton(int af, const char *src, void *dst);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* COMPAT_H */
|
||||
|
|
|
|||
|
|
@ -40,276 +40,304 @@
|
|||
#include "options.h"
|
||||
|
||||
static void
|
||||
argv_init (struct argv *a)
|
||||
argv_init(struct argv *a)
|
||||
{
|
||||
a->capacity = 0;
|
||||
a->argc = 0;
|
||||
a->argv = NULL;
|
||||
a->capacity = 0;
|
||||
a->argc = 0;
|
||||
a->argv = NULL;
|
||||
}
|
||||
|
||||
struct argv
|
||||
argv_new (void)
|
||||
argv_new(void)
|
||||
{
|
||||
struct argv ret;
|
||||
argv_init (&ret);
|
||||
return ret;
|
||||
struct argv ret;
|
||||
argv_init(&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
argv_reset (struct argv *a)
|
||||
argv_reset(struct argv *a)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
free (a->argv[i]);
|
||||
free (a->argv);
|
||||
argv_init (a);
|
||||
size_t i;
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
free(a->argv[i]);
|
||||
free(a->argv);
|
||||
argv_init(a);
|
||||
}
|
||||
|
||||
static void
|
||||
argv_extend (struct argv *a, const size_t newcap)
|
||||
argv_extend(struct argv *a, const size_t newcap)
|
||||
{
|
||||
if (newcap > a->capacity)
|
||||
if (newcap > a->capacity)
|
||||
{
|
||||
char **newargv;
|
||||
size_t i;
|
||||
ALLOC_ARRAY_CLEAR (newargv, char *, newcap);
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
newargv[i] = a->argv[i];
|
||||
free (a->argv);
|
||||
a->argv = newargv;
|
||||
a->capacity = newcap;
|
||||
char **newargv;
|
||||
size_t i;
|
||||
ALLOC_ARRAY_CLEAR(newargv, char *, newcap);
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
newargv[i] = a->argv[i];
|
||||
free(a->argv);
|
||||
a->argv = newargv;
|
||||
a->capacity = newcap;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
argv_grow (struct argv *a, const size_t add)
|
||||
argv_grow(struct argv *a, const size_t add)
|
||||
{
|
||||
const size_t newargc = a->argc + add + 1;
|
||||
ASSERT (newargc > a->argc);
|
||||
argv_extend (a, adjust_power_of_2 (newargc));
|
||||
const size_t newargc = a->argc + add + 1;
|
||||
ASSERT(newargc > a->argc);
|
||||
argv_extend(a, adjust_power_of_2(newargc));
|
||||
}
|
||||
|
||||
static void
|
||||
argv_append (struct argv *a, char *str) /* str must have been malloced or be NULL */
|
||||
argv_append(struct argv *a, char *str) /* str must have been malloced or be NULL */
|
||||
{
|
||||
argv_grow (a, 1);
|
||||
a->argv[a->argc++] = str;
|
||||
argv_grow(a, 1);
|
||||
a->argv[a->argc++] = str;
|
||||
}
|
||||
|
||||
static struct argv
|
||||
argv_clone (const struct argv *a, const size_t headroom)
|
||||
argv_clone(const struct argv *a, const size_t headroom)
|
||||
{
|
||||
struct argv r;
|
||||
size_t i;
|
||||
struct argv r;
|
||||
size_t i;
|
||||
|
||||
argv_init (&r);
|
||||
for (i = 0; i < headroom; ++i)
|
||||
argv_append (&r, NULL);
|
||||
if (a)
|
||||
argv_init(&r);
|
||||
for (i = 0; i < headroom; ++i)
|
||||
argv_append(&r, NULL);
|
||||
if (a)
|
||||
{
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
argv_append (&r, string_alloc (a->argv[i], NULL));
|
||||
for (i = 0; i < a->argc; ++i)
|
||||
argv_append(&r, string_alloc(a->argv[i], NULL));
|
||||
}
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
struct argv
|
||||
argv_insert_head (const struct argv *a, const char *head)
|
||||
argv_insert_head(const struct argv *a, const char *head)
|
||||
{
|
||||
struct argv r;
|
||||
r = argv_clone (a, 1);
|
||||
r.argv[0] = string_alloc (head, NULL);
|
||||
return r;
|
||||
struct argv r;
|
||||
r = argv_clone(a, 1);
|
||||
r.argv[0] = string_alloc(head, NULL);
|
||||
return r;
|
||||
}
|
||||
|
||||
static char *
|
||||
argv_term (const char **f)
|
||||
argv_term(const char **f)
|
||||
{
|
||||
const char *p = *f;
|
||||
const char *term = NULL;
|
||||
size_t termlen = 0;
|
||||
const char *p = *f;
|
||||
const char *term = NULL;
|
||||
size_t termlen = 0;
|
||||
|
||||
if (*p == '\0')
|
||||
return NULL;
|
||||
|
||||
while (true)
|
||||
if (*p == '\0')
|
||||
{
|
||||
const int c = *p;
|
||||
if (c == '\0')
|
||||
break;
|
||||
if (term)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
const int c = *p;
|
||||
if (c == '\0')
|
||||
{
|
||||
if (!isspace (c))
|
||||
++termlen;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
if (term)
|
||||
{
|
||||
if (!isspace (c))
|
||||
if (!isspace(c))
|
||||
{
|
||||
term = p;
|
||||
termlen = 1;
|
||||
++termlen;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
++p;
|
||||
else
|
||||
{
|
||||
if (!isspace(c))
|
||||
{
|
||||
term = p;
|
||||
termlen = 1;
|
||||
}
|
||||
}
|
||||
++p;
|
||||
}
|
||||
*f = p;
|
||||
*f = p;
|
||||
|
||||
if (term)
|
||||
if (term)
|
||||
{
|
||||
char *ret;
|
||||
ASSERT (termlen > 0);
|
||||
ret = malloc (termlen + 1);
|
||||
check_malloc_return (ret);
|
||||
memcpy (ret, term, termlen);
|
||||
ret[termlen] = '\0';
|
||||
return ret;
|
||||
char *ret;
|
||||
ASSERT(termlen > 0);
|
||||
ret = malloc(termlen + 1);
|
||||
check_malloc_return(ret);
|
||||
memcpy(ret, term, termlen);
|
||||
ret[termlen] = '\0';
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags)
|
||||
argv_str(const struct argv *a, struct gc_arena *gc, const unsigned int flags)
|
||||
{
|
||||
if (a->argv)
|
||||
return print_argv ((const char **)a->argv, gc, flags);
|
||||
else
|
||||
return "";
|
||||
if (a->argv)
|
||||
{
|
||||
return print_argv((const char **)a->argv, gc, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
argv_msg (const int msglev, const struct argv *a)
|
||||
argv_msg(const int msglev, const struct argv *a)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
msg (msglev, "%s", argv_str (a, &gc, 0));
|
||||
gc_free (&gc);
|
||||
struct gc_arena gc = gc_new();
|
||||
msg(msglev, "%s", argv_str(a, &gc, 0));
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
void
|
||||
argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix)
|
||||
argv_msg_prefix(const int msglev, const struct argv *a, const char *prefix)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
msg (msglev, "%s: %s", prefix, argv_str (a, &gc, 0));
|
||||
gc_free (&gc);
|
||||
struct gc_arena gc = gc_new();
|
||||
msg(msglev, "%s: %s", prefix, argv_str(a, &gc, 0));
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
static void
|
||||
argv_printf_arglist (struct argv *a, const char *format, va_list arglist)
|
||||
argv_printf_arglist(struct argv *a, const char *format, va_list arglist)
|
||||
{
|
||||
char *term;
|
||||
const char *f = format;
|
||||
char *term;
|
||||
const char *f = format;
|
||||
|
||||
argv_extend (a, 1); /* ensure trailing NULL */
|
||||
argv_extend(a, 1); /* ensure trailing NULL */
|
||||
|
||||
while ((term = argv_term (&f)) != NULL)
|
||||
while ((term = argv_term(&f)) != NULL)
|
||||
{
|
||||
if (term[0] == '%')
|
||||
if (term[0] == '%')
|
||||
{
|
||||
if (!strcmp (term, "%s"))
|
||||
if (!strcmp(term, "%s"))
|
||||
{
|
||||
char *s = va_arg (arglist, char *);
|
||||
if (!s)
|
||||
s = "";
|
||||
argv_append (a, string_alloc (s, NULL));
|
||||
char *s = va_arg(arglist, char *);
|
||||
if (!s)
|
||||
{
|
||||
s = "";
|
||||
}
|
||||
argv_append(a, string_alloc(s, NULL));
|
||||
}
|
||||
else if (!strcmp (term, "%d"))
|
||||
else if (!strcmp(term, "%d"))
|
||||
{
|
||||
char numstr[64];
|
||||
openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
|
||||
argv_append (a, string_alloc (numstr, NULL));
|
||||
char numstr[64];
|
||||
openvpn_snprintf(numstr, sizeof(numstr), "%d", va_arg(arglist, int));
|
||||
argv_append(a, string_alloc(numstr, NULL));
|
||||
}
|
||||
else if (!strcmp (term, "%u"))
|
||||
else if (!strcmp(term, "%u"))
|
||||
{
|
||||
char numstr[64];
|
||||
openvpn_snprintf (numstr, sizeof (numstr), "%u", va_arg (arglist, unsigned int));
|
||||
argv_append (a, string_alloc (numstr, NULL));
|
||||
char numstr[64];
|
||||
openvpn_snprintf(numstr, sizeof(numstr), "%u", va_arg(arglist, unsigned int));
|
||||
argv_append(a, string_alloc(numstr, NULL));
|
||||
}
|
||||
else if (!strcmp (term, "%s/%d"))
|
||||
else if (!strcmp(term, "%s/%d"))
|
||||
{
|
||||
char numstr[64];
|
||||
char *s = va_arg (arglist, char *);
|
||||
char numstr[64];
|
||||
char *s = va_arg(arglist, char *);
|
||||
|
||||
if (!s)
|
||||
s = "";
|
||||
if (!s)
|
||||
{
|
||||
s = "";
|
||||
}
|
||||
|
||||
openvpn_snprintf (numstr, sizeof (numstr), "%d", va_arg (arglist, int));
|
||||
openvpn_snprintf(numstr, sizeof(numstr), "%d", va_arg(arglist, int));
|
||||
|
||||
{
|
||||
const size_t len = strlen(s) + strlen(numstr) + 2;
|
||||
char *combined = (char *) malloc (len);
|
||||
check_malloc_return (combined);
|
||||
{
|
||||
const size_t len = strlen(s) + strlen(numstr) + 2;
|
||||
char *combined = (char *) malloc(len);
|
||||
check_malloc_return(combined);
|
||||
|
||||
strcpy (combined, s);
|
||||
strcat (combined, "/");
|
||||
strcat (combined, numstr);
|
||||
argv_append (a, combined);
|
||||
}
|
||||
strcpy(combined, s);
|
||||
strcat(combined, "/");
|
||||
strcat(combined, numstr);
|
||||
argv_append(a, combined);
|
||||
}
|
||||
}
|
||||
else if (!strcmp (term, "%s%sc"))
|
||||
else if (!strcmp(term, "%s%sc"))
|
||||
{
|
||||
char *s1 = va_arg (arglist, char *);
|
||||
char *s2 = va_arg (arglist, char *);
|
||||
char *combined;
|
||||
char *s1 = va_arg(arglist, char *);
|
||||
char *s2 = va_arg(arglist, char *);
|
||||
char *combined;
|
||||
|
||||
if (!s1) s1 = "";
|
||||
if (!s2) s2 = "";
|
||||
combined = (char *) malloc (strlen(s1) + strlen(s2) + 1);
|
||||
check_malloc_return (combined);
|
||||
strcpy (combined, s1);
|
||||
strcat (combined, s2);
|
||||
argv_append (a, combined);
|
||||
if (!s1)
|
||||
{
|
||||
s1 = "";
|
||||
}
|
||||
if (!s2)
|
||||
{
|
||||
s2 = "";
|
||||
}
|
||||
combined = (char *) malloc(strlen(s1) + strlen(s2) + 1);
|
||||
check_malloc_return(combined);
|
||||
strcpy(combined, s1);
|
||||
strcat(combined, s2);
|
||||
argv_append(a, combined);
|
||||
}
|
||||
else
|
||||
ASSERT (0);
|
||||
free (term);
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
free(term);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
argv_append (a, term);
|
||||
argv_append(a, term);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
argv_printf (struct argv *a, const char *format, ...)
|
||||
argv_printf(struct argv *a, const char *format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
argv_reset (a);
|
||||
va_start (arglist, format);
|
||||
argv_printf_arglist (a, format, arglist);
|
||||
va_end (arglist);
|
||||
}
|
||||
|
||||
void
|
||||
argv_printf_cat (struct argv *a, const char *format, ...)
|
||||
{
|
||||
va_list arglist;
|
||||
va_start (arglist, format);
|
||||
argv_printf_arglist (a, format, arglist);
|
||||
va_end (arglist);
|
||||
va_list arglist;
|
||||
argv_reset(a);
|
||||
va_start(arglist, format);
|
||||
argv_printf_arglist(a, format, arglist);
|
||||
va_end(arglist);
|
||||
}
|
||||
|
||||
void
|
||||
argv_parse_cmd (struct argv *a, const char *s)
|
||||
argv_printf_cat(struct argv *a, const char *format, ...)
|
||||
{
|
||||
int nparms;
|
||||
char *parms[MAX_PARMS + 1];
|
||||
struct gc_arena gc = gc_new ();
|
||||
va_list arglist;
|
||||
va_start(arglist, format);
|
||||
argv_printf_arglist(a, format, arglist);
|
||||
va_end(arglist);
|
||||
}
|
||||
|
||||
argv_reset (a);
|
||||
argv_extend (a, 1); /* ensure trailing NULL */
|
||||
void
|
||||
argv_parse_cmd(struct argv *a, const char *s)
|
||||
{
|
||||
int nparms;
|
||||
char *parms[MAX_PARMS + 1];
|
||||
struct gc_arena gc = gc_new();
|
||||
|
||||
nparms = parse_line (s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, D_ARGV_PARSE_CMD, &gc);
|
||||
if (nparms)
|
||||
argv_reset(a);
|
||||
argv_extend(a, 1); /* ensure trailing NULL */
|
||||
|
||||
nparms = parse_line(s, parms, MAX_PARMS, "SCRIPT-ARGV", 0, D_ARGV_PARSE_CMD, &gc);
|
||||
if (nparms)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nparms; ++i)
|
||||
argv_append (a, string_alloc (parms[i], NULL));
|
||||
int i;
|
||||
for (i = 0; i < nparms; ++i)
|
||||
argv_append(a, string_alloc(parms[i], NULL));
|
||||
}
|
||||
else
|
||||
{
|
||||
argv_append(a, string_alloc(s, NULL));
|
||||
}
|
||||
else
|
||||
argv_append (a, string_alloc (s, NULL));
|
||||
|
||||
gc_free (&gc);
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,37 +34,43 @@
|
|||
#include "buffer.h"
|
||||
|
||||
struct argv {
|
||||
size_t capacity;
|
||||
size_t argc;
|
||||
char **argv;
|
||||
size_t capacity;
|
||||
size_t argc;
|
||||
char **argv;
|
||||
};
|
||||
|
||||
struct argv argv_new (void);
|
||||
void argv_reset (struct argv *a);
|
||||
const char *argv_str (const struct argv *a, struct gc_arena *gc, const unsigned int flags);
|
||||
struct argv argv_insert_head (const struct argv *a, const char *head);
|
||||
void argv_msg (const int msglev, const struct argv *a);
|
||||
void argv_msg_prefix (const int msglev, const struct argv *a, const char *prefix);
|
||||
void argv_parse_cmd (struct argv *a, const char *s);
|
||||
struct argv argv_new(void);
|
||||
|
||||
void argv_printf (struct argv *a, const char *format, ...)
|
||||
void argv_reset(struct argv *a);
|
||||
|
||||
const char *argv_str(const struct argv *a, struct gc_arena *gc, const unsigned int flags);
|
||||
|
||||
struct argv argv_insert_head(const struct argv *a, const char *head);
|
||||
|
||||
void argv_msg(const int msglev, const struct argv *a);
|
||||
|
||||
void argv_msg_prefix(const int msglev, const struct argv *a, const char *prefix);
|
||||
|
||||
void argv_parse_cmd(struct argv *a, const char *s);
|
||||
|
||||
void argv_printf(struct argv *a, const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
#if __USE_MINGW_ANSI_STDIO
|
||||
__attribute__ ((format (gnu_printf, 2, 3)))
|
||||
__attribute__ ((format(gnu_printf, 2, 3)))
|
||||
#else
|
||||
__attribute__ ((format (__printf__, 2, 3)))
|
||||
__attribute__ ((format(__printf__, 2, 3)))
|
||||
#endif
|
||||
#endif
|
||||
;
|
||||
;
|
||||
|
||||
void argv_printf_cat (struct argv *a, const char *format, ...)
|
||||
void argv_printf_cat(struct argv *a, const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
#if __USE_MINGW_ANSI_STDIO
|
||||
__attribute__ ((format (gnu_printf, 2, 3)))
|
||||
__attribute__ ((format(gnu_printf, 2, 3)))
|
||||
#else
|
||||
__attribute__ ((format (__printf__, 2, 3)))
|
||||
__attribute__ ((format(__printf__, 2, 3)))
|
||||
#endif
|
||||
#endif
|
||||
;
|
||||
;
|
||||
|
||||
#endif
|
||||
#endif /* ifndef ARGV_H */
|
||||
|
|
|
|||
|
|
@ -43,14 +43,14 @@
|
|||
|
||||
#include "memdbg.h"
|
||||
|
||||
static char base64_chars[] =
|
||||
static char base64_chars[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
/*
|
||||
* base64 encode input data of length size to malloced
|
||||
* buffer which is returned as *str. Returns string
|
||||
* length of *str.
|
||||
*/
|
||||
int
|
||||
int
|
||||
openvpn_base64_encode(const void *data, int size, char **str)
|
||||
{
|
||||
char *s, *p;
|
||||
|
|
@ -59,44 +59,58 @@ openvpn_base64_encode(const void *data, int size, char **str)
|
|||
const unsigned char *q;
|
||||
|
||||
if (size < 0)
|
||||
return -1;
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
p = s = (char *) malloc(size * 4 / 3 + 4);
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
q = (const unsigned char *) data;
|
||||
i = 0;
|
||||
for (i = 0; i < size;) {
|
||||
c = q[i++];
|
||||
c *= 256;
|
||||
if (i < size)
|
||||
c += q[i];
|
||||
i++;
|
||||
c *= 256;
|
||||
if (i < size)
|
||||
c += q[i];
|
||||
i++;
|
||||
p[0] = base64_chars[(c & 0x00fc0000) >> 18];
|
||||
p[1] = base64_chars[(c & 0x0003f000) >> 12];
|
||||
p[2] = base64_chars[(c & 0x00000fc0) >> 6];
|
||||
p[3] = base64_chars[(c & 0x0000003f) >> 0];
|
||||
if (i > size)
|
||||
p[3] = '=';
|
||||
if (i > size + 1)
|
||||
p[2] = '=';
|
||||
p += 4;
|
||||
for (i = 0; i < size; ) {
|
||||
c = q[i++];
|
||||
c *= 256;
|
||||
if (i < size)
|
||||
{
|
||||
c += q[i];
|
||||
}
|
||||
i++;
|
||||
c *= 256;
|
||||
if (i < size)
|
||||
{
|
||||
c += q[i];
|
||||
}
|
||||
i++;
|
||||
p[0] = base64_chars[(c & 0x00fc0000) >> 18];
|
||||
p[1] = base64_chars[(c & 0x0003f000) >> 12];
|
||||
p[2] = base64_chars[(c & 0x00000fc0) >> 6];
|
||||
p[3] = base64_chars[(c & 0x0000003f) >> 0];
|
||||
if (i > size)
|
||||
{
|
||||
p[3] = '=';
|
||||
}
|
||||
if (i > size + 1)
|
||||
{
|
||||
p[2] = '=';
|
||||
}
|
||||
p += 4;
|
||||
}
|
||||
*p = 0;
|
||||
*str = s;
|
||||
return strlen(s);
|
||||
}
|
||||
|
||||
static int
|
||||
static int
|
||||
pos(char c)
|
||||
{
|
||||
char *p;
|
||||
for (p = base64_chars; *p; p++)
|
||||
if (*p == c)
|
||||
return p - base64_chars;
|
||||
if (*p == c)
|
||||
{
|
||||
return p - base64_chars;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -109,18 +123,28 @@ token_decode(const char *token)
|
|||
unsigned int val = 0;
|
||||
int marker = 0;
|
||||
if (!token[0] || !token[1] || !token[2] || !token[3])
|
||||
return DECODE_ERROR;
|
||||
{
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
val *= 64;
|
||||
if (token[i] == '=')
|
||||
marker++;
|
||||
else if (marker > 0)
|
||||
return DECODE_ERROR;
|
||||
else
|
||||
val += pos(token[i]);
|
||||
val *= 64;
|
||||
if (token[i] == '=')
|
||||
{
|
||||
marker++;
|
||||
}
|
||||
else if (marker > 0)
|
||||
{
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
val += pos(token[i]);
|
||||
}
|
||||
}
|
||||
if (marker > 2)
|
||||
return DECODE_ERROR;
|
||||
{
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
return (marker << 24) | val;
|
||||
}
|
||||
/*
|
||||
|
|
@ -137,27 +161,37 @@ openvpn_base64_decode(const char *str, void *data, int size)
|
|||
|
||||
q = data;
|
||||
if (size >= 0)
|
||||
e = q + size;
|
||||
{
|
||||
e = q + size;
|
||||
}
|
||||
for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) {
|
||||
unsigned int val = token_decode(p);
|
||||
unsigned int marker = (val >> 24) & 0xff;
|
||||
if (val == DECODE_ERROR)
|
||||
return -1;
|
||||
if (e && q >= e)
|
||||
return -1;
|
||||
*q++ = (val >> 16) & 0xff;
|
||||
if (marker < 2)
|
||||
{
|
||||
if (e && q >= e)
|
||||
return -1;
|
||||
*q++ = (val >> 8) & 0xff;
|
||||
}
|
||||
if (marker < 1)
|
||||
{
|
||||
if (e && q >= e)
|
||||
return -1;
|
||||
*q++ = val & 0xff;
|
||||
}
|
||||
unsigned int val = token_decode(p);
|
||||
unsigned int marker = (val >> 24) & 0xff;
|
||||
if (val == DECODE_ERROR)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (e && q >= e)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*q++ = (val >> 16) & 0xff;
|
||||
if (marker < 2)
|
||||
{
|
||||
if (e && q >= e)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*q++ = (val >> 8) & 0xff;
|
||||
}
|
||||
if (marker < 1)
|
||||
{
|
||||
if (e && q >= e)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
*q++ = val & 0xff;
|
||||
}
|
||||
}
|
||||
return q - (unsigned char *) data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,22 +2,22 @@
|
|||
* Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan
|
||||
* (Royal Institute of Technology, Stockholm, Sweden).
|
||||
* All rights reserved.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* 2. 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.
|
||||
*
|
||||
*
|
||||
* 3. Neither the name of the Institute nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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
|
||||
|
|
@ -35,6 +35,7 @@
|
|||
#define _BASE64_H_
|
||||
|
||||
int openvpn_base64_encode(const void *data, int size, char **str);
|
||||
|
||||
int openvpn_base64_decode(const char *str, void *data, int size);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -53,60 +53,60 @@
|
|||
#define FWPM_SESSION_FLAG_DYNAMIC 0x00000001
|
||||
#endif
|
||||
|
||||
// c38d57d1-05a7-4c33-904f-7fbceee60e82
|
||||
/* c38d57d1-05a7-4c33-904f-7fbceee60e82 */
|
||||
DEFINE_GUID(
|
||||
FWPM_LAYER_ALE_AUTH_CONNECT_V4,
|
||||
0xc38d57d1,
|
||||
0x05a7,
|
||||
0x4c33,
|
||||
0x90, 0x4f, 0x7f, 0xbc, 0xee, 0xe6, 0x0e, 0x82
|
||||
);
|
||||
FWPM_LAYER_ALE_AUTH_CONNECT_V4,
|
||||
0xc38d57d1,
|
||||
0x05a7,
|
||||
0x4c33,
|
||||
0x90, 0x4f, 0x7f, 0xbc, 0xee, 0xe6, 0x0e, 0x82
|
||||
);
|
||||
|
||||
// 4a72393b-319f-44bc-84c3-ba54dcb3b6b4
|
||||
/* 4a72393b-319f-44bc-84c3-ba54dcb3b6b4 */
|
||||
DEFINE_GUID(
|
||||
FWPM_LAYER_ALE_AUTH_CONNECT_V6,
|
||||
0x4a72393b,
|
||||
0x319f,
|
||||
0x44bc,
|
||||
0x84, 0xc3, 0xba, 0x54, 0xdc, 0xb3, 0xb6, 0xb4
|
||||
);
|
||||
FWPM_LAYER_ALE_AUTH_CONNECT_V6,
|
||||
0x4a72393b,
|
||||
0x319f,
|
||||
0x44bc,
|
||||
0x84, 0xc3, 0xba, 0x54, 0xdc, 0xb3, 0xb6, 0xb4
|
||||
);
|
||||
|
||||
// d78e1e87-8644-4ea5-9437-d809ecefc971
|
||||
/* d78e1e87-8644-4ea5-9437-d809ecefc971 */
|
||||
DEFINE_GUID(
|
||||
FWPM_CONDITION_ALE_APP_ID,
|
||||
0xd78e1e87,
|
||||
0x8644,
|
||||
0x4ea5,
|
||||
0x94, 0x37, 0xd8, 0x09, 0xec, 0xef, 0xc9, 0x71
|
||||
);
|
||||
FWPM_CONDITION_ALE_APP_ID,
|
||||
0xd78e1e87,
|
||||
0x8644,
|
||||
0x4ea5,
|
||||
0x94, 0x37, 0xd8, 0x09, 0xec, 0xef, 0xc9, 0x71
|
||||
);
|
||||
|
||||
// c35a604d-d22b-4e1a-91b4-68f674ee674b
|
||||
/* c35a604d-d22b-4e1a-91b4-68f674ee674b */
|
||||
DEFINE_GUID(
|
||||
FWPM_CONDITION_IP_REMOTE_PORT,
|
||||
0xc35a604d,
|
||||
0xd22b,
|
||||
0x4e1a,
|
||||
0x91, 0xb4, 0x68, 0xf6, 0x74, 0xee, 0x67, 0x4b
|
||||
);
|
||||
FWPM_CONDITION_IP_REMOTE_PORT,
|
||||
0xc35a604d,
|
||||
0xd22b,
|
||||
0x4e1a,
|
||||
0x91, 0xb4, 0x68, 0xf6, 0x74, 0xee, 0x67, 0x4b
|
||||
);
|
||||
|
||||
// 4cd62a49-59c3-4969-b7f3-bda5d32890a4
|
||||
/* 4cd62a49-59c3-4969-b7f3-bda5d32890a4 */
|
||||
DEFINE_GUID(
|
||||
FWPM_CONDITION_IP_LOCAL_INTERFACE,
|
||||
0x4cd62a49,
|
||||
0x59c3,
|
||||
0x4969,
|
||||
0xb7, 0xf3, 0xbd, 0xa5, 0xd3, 0x28, 0x90, 0xa4
|
||||
);
|
||||
FWPM_CONDITION_IP_LOCAL_INTERFACE,
|
||||
0x4cd62a49,
|
||||
0x59c3,
|
||||
0x4969,
|
||||
0xb7, 0xf3, 0xbd, 0xa5, 0xd3, 0x28, 0x90, 0xa4
|
||||
);
|
||||
|
||||
/* UUID of WFP sublayer used by all instances of openvpn
|
||||
2f660d7e-6a37-11e6-a181-001e8c6e04a2 */
|
||||
* 2f660d7e-6a37-11e6-a181-001e8c6e04a2 */
|
||||
DEFINE_GUID(
|
||||
OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER,
|
||||
0x2f660d7e,
|
||||
0x6a37,
|
||||
0x11e6,
|
||||
0xa1, 0x81, 0x00, 0x1e, 0x8c, 0x6e, 0x04, 0xa2
|
||||
);
|
||||
OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER,
|
||||
0x2f660d7e,
|
||||
0x6a37,
|
||||
0x11e6,
|
||||
0xa1, 0x81, 0x00, 0x1e, 0x8c, 0x6e, 0x04, 0xa2
|
||||
);
|
||||
|
||||
static WCHAR *FIREWALL_NAME = L"OpenVPN";
|
||||
|
||||
|
|
@ -114,45 +114,49 @@ static WCHAR *FIREWALL_NAME = L"OpenVPN";
|
|||
* Default msg handler does nothing
|
||||
*/
|
||||
static inline void
|
||||
default_msg_handler (DWORD err, const char *msg)
|
||||
default_msg_handler(DWORD err, const char *msg)
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
#define CHECK_ERROR(err, msg) \
|
||||
if (err) { msg_handler (err, msg); goto out; }
|
||||
if (err) { msg_handler(err, msg); goto out; }
|
||||
|
||||
/*
|
||||
* Add a persistent sublayer with specified uuid.
|
||||
*/
|
||||
static DWORD
|
||||
add_sublayer (GUID uuid)
|
||||
add_sublayer(GUID uuid)
|
||||
{
|
||||
FWPM_SESSION0 session;
|
||||
HANDLE engine = NULL;
|
||||
DWORD err = 0;
|
||||
FWPM_SUBLAYER0 sublayer;
|
||||
FWPM_SESSION0 session;
|
||||
HANDLE engine = NULL;
|
||||
DWORD err = 0;
|
||||
FWPM_SUBLAYER0 sublayer;
|
||||
|
||||
memset (&session, 0, sizeof(session));
|
||||
memset (&sublayer, 0, sizeof(sublayer));
|
||||
memset(&session, 0, sizeof(session));
|
||||
memset(&sublayer, 0, sizeof(sublayer));
|
||||
|
||||
err = FwpmEngineOpen0 (NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engine);
|
||||
if (err != ERROR_SUCCESS)
|
||||
goto out;
|
||||
err = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engine);
|
||||
if (err != ERROR_SUCCESS)
|
||||
{
|
||||
goto out;
|
||||
}
|
||||
|
||||
sublayer.subLayerKey = uuid;
|
||||
sublayer.displayData.name = FIREWALL_NAME;
|
||||
sublayer.displayData.description = FIREWALL_NAME;
|
||||
sublayer.flags = 0;
|
||||
sublayer.weight = 0x100;
|
||||
sublayer.subLayerKey = uuid;
|
||||
sublayer.displayData.name = FIREWALL_NAME;
|
||||
sublayer.displayData.description = FIREWALL_NAME;
|
||||
sublayer.flags = 0;
|
||||
sublayer.weight = 0x100;
|
||||
|
||||
/* Add sublayer to the session */
|
||||
err = FwpmSubLayerAdd0 (engine, &sublayer, NULL);
|
||||
/* Add sublayer to the session */
|
||||
err = FwpmSubLayerAdd0(engine, &sublayer, NULL);
|
||||
|
||||
out:
|
||||
if (engine)
|
||||
FwpmEngineClose0 (engine);
|
||||
return err;
|
||||
if (engine)
|
||||
{
|
||||
FwpmEngineClose0(engine);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -173,160 +177,168 @@ out:
|
|||
*/
|
||||
|
||||
DWORD
|
||||
add_block_dns_filters (HANDLE *engine_handle,
|
||||
int index,
|
||||
const WCHAR *exe_path,
|
||||
block_dns_msg_handler_t msg_handler
|
||||
add_block_dns_filters(HANDLE *engine_handle,
|
||||
int index,
|
||||
const WCHAR *exe_path,
|
||||
block_dns_msg_handler_t msg_handler
|
||||
)
|
||||
{
|
||||
FWPM_SESSION0 session = {0};
|
||||
FWPM_SUBLAYER0 *sublayer_ptr = NULL;
|
||||
NET_LUID tapluid;
|
||||
UINT64 filterid;
|
||||
FWP_BYTE_BLOB *openvpnblob = NULL;
|
||||
FWPM_FILTER0 Filter = {0};
|
||||
FWPM_FILTER_CONDITION0 Condition[2] = {0};
|
||||
DWORD err = 0;
|
||||
FWPM_SESSION0 session = {0};
|
||||
FWPM_SUBLAYER0 *sublayer_ptr = NULL;
|
||||
NET_LUID tapluid;
|
||||
UINT64 filterid;
|
||||
FWP_BYTE_BLOB *openvpnblob = NULL;
|
||||
FWPM_FILTER0 Filter = {0};
|
||||
FWPM_FILTER_CONDITION0 Condition[2] = {0};
|
||||
DWORD err = 0;
|
||||
|
||||
if (!msg_handler)
|
||||
msg_handler = default_msg_handler;
|
||||
|
||||
/* Add temporary filters which don't survive reboots or crashes. */
|
||||
session.flags = FWPM_SESSION_FLAG_DYNAMIC;
|
||||
|
||||
*engine_handle = NULL;
|
||||
|
||||
err = FwpmEngineOpen0 (NULL, RPC_C_AUTHN_WINNT, NULL, &session, engine_handle);
|
||||
CHECK_ERROR (err, "FwpEngineOpen: open fwp session failed");
|
||||
msg_handler (0, "Block_DNS: WFP engine opened");
|
||||
|
||||
/* Check sublayer exists and add one if it does not. */
|
||||
if (FwpmSubLayerGetByKey0 (*engine_handle, &OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER, &sublayer_ptr)
|
||||
== ERROR_SUCCESS)
|
||||
if (!msg_handler)
|
||||
{
|
||||
msg_handler (0, "Block_DNS: Using existing sublayer");
|
||||
FwpmFreeMemory0 ((void **)&sublayer_ptr);
|
||||
msg_handler = default_msg_handler;
|
||||
}
|
||||
else
|
||||
|
||||
/* Add temporary filters which don't survive reboots or crashes. */
|
||||
session.flags = FWPM_SESSION_FLAG_DYNAMIC;
|
||||
|
||||
*engine_handle = NULL;
|
||||
|
||||
err = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, engine_handle);
|
||||
CHECK_ERROR(err, "FwpEngineOpen: open fwp session failed");
|
||||
msg_handler(0, "Block_DNS: WFP engine opened");
|
||||
|
||||
/* Check sublayer exists and add one if it does not. */
|
||||
if (FwpmSubLayerGetByKey0(*engine_handle, &OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER, &sublayer_ptr)
|
||||
== ERROR_SUCCESS)
|
||||
{
|
||||
msg_handler(0, "Block_DNS: Using existing sublayer");
|
||||
FwpmFreeMemory0((void **)&sublayer_ptr);
|
||||
}
|
||||
else
|
||||
{ /* Add a new sublayer -- as another process may add it in the meantime,
|
||||
do not treat "already exists" as an error */
|
||||
err = add_sublayer (OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER);
|
||||
* do not treat "already exists" as an error */
|
||||
err = add_sublayer(OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER);
|
||||
|
||||
if (err == FWP_E_ALREADY_EXISTS || err == ERROR_SUCCESS)
|
||||
msg_handler (0, "Block_DNS: Added a persistent sublayer with pre-defined UUID");
|
||||
else
|
||||
CHECK_ERROR (err, "add_sublayer: failed to add persistent sublayer");
|
||||
if (err == FWP_E_ALREADY_EXISTS || err == ERROR_SUCCESS)
|
||||
{
|
||||
msg_handler(0, "Block_DNS: Added a persistent sublayer with pre-defined UUID");
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_ERROR(err, "add_sublayer: failed to add persistent sublayer");
|
||||
}
|
||||
}
|
||||
|
||||
err = ConvertInterfaceIndexToLuid (index, &tapluid);
|
||||
CHECK_ERROR (err, "Convert interface index to luid failed");
|
||||
err = ConvertInterfaceIndexToLuid(index, &tapluid);
|
||||
CHECK_ERROR(err, "Convert interface index to luid failed");
|
||||
|
||||
err = FwpmGetAppIdFromFileName0 (exe_path, &openvpnblob);
|
||||
CHECK_ERROR (err, "Get byte blob for openvpn executable name failed");
|
||||
err = FwpmGetAppIdFromFileName0(exe_path, &openvpnblob);
|
||||
CHECK_ERROR(err, "Get byte blob for openvpn executable name failed");
|
||||
|
||||
/* Prepare filter. */
|
||||
Filter.subLayerKey = OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER;
|
||||
Filter.displayData.name = FIREWALL_NAME;
|
||||
Filter.weight.type = FWP_UINT8;
|
||||
Filter.weight.uint8 = 0xF;
|
||||
Filter.filterCondition = Condition;
|
||||
Filter.numFilterConditions = 2;
|
||||
/* Prepare filter. */
|
||||
Filter.subLayerKey = OPENVPN_BLOCK_OUTSIDE_DNS_SUBLAYER;
|
||||
Filter.displayData.name = FIREWALL_NAME;
|
||||
Filter.weight.type = FWP_UINT8;
|
||||
Filter.weight.uint8 = 0xF;
|
||||
Filter.filterCondition = Condition;
|
||||
Filter.numFilterConditions = 2;
|
||||
|
||||
/* First filter. Permit IPv4 DNS queries from OpenVPN itself. */
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
||||
Filter.action.type = FWP_ACTION_PERMIT;
|
||||
/* First filter. Permit IPv4 DNS queries from OpenVPN itself. */
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
||||
Filter.action.type = FWP_ACTION_PERMIT;
|
||||
|
||||
Condition[0].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
|
||||
Condition[0].matchType = FWP_MATCH_EQUAL;
|
||||
Condition[0].conditionValue.type = FWP_UINT16;
|
||||
Condition[0].conditionValue.uint16 = 53;
|
||||
Condition[0].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
|
||||
Condition[0].matchType = FWP_MATCH_EQUAL;
|
||||
Condition[0].conditionValue.type = FWP_UINT16;
|
||||
Condition[0].conditionValue.uint16 = 53;
|
||||
|
||||
Condition[1].fieldKey = FWPM_CONDITION_ALE_APP_ID;
|
||||
Condition[1].matchType = FWP_MATCH_EQUAL;
|
||||
Condition[1].conditionValue.type = FWP_BYTE_BLOB_TYPE;
|
||||
Condition[1].conditionValue.byteBlob = openvpnblob;
|
||||
Condition[1].fieldKey = FWPM_CONDITION_ALE_APP_ID;
|
||||
Condition[1].matchType = FWP_MATCH_EQUAL;
|
||||
Condition[1].conditionValue.type = FWP_BYTE_BLOB_TYPE;
|
||||
Condition[1].conditionValue.byteBlob = openvpnblob;
|
||||
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR (err, "Add filter to permit IPv4 port 53 traffic from OpenVPN failed");
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR(err, "Add filter to permit IPv4 port 53 traffic from OpenVPN failed");
|
||||
|
||||
/* Second filter. Permit IPv6 DNS queries from OpenVPN itself. */
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
||||
/* Second filter. Permit IPv6 DNS queries from OpenVPN itself. */
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
||||
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR (err, "Add filter to permit IPv6 port 53 traffic from OpenVPN failed");
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR(err, "Add filter to permit IPv6 port 53 traffic from OpenVPN failed");
|
||||
|
||||
msg_handler (0, "Block_DNS: Added permit filters for exe_path");
|
||||
msg_handler(0, "Block_DNS: Added permit filters for exe_path");
|
||||
|
||||
/* Third filter. Block all IPv4 DNS queries. */
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
||||
Filter.action.type = FWP_ACTION_BLOCK;
|
||||
Filter.weight.type = FWP_EMPTY;
|
||||
Filter.numFilterConditions = 1;
|
||||
/* Third filter. Block all IPv4 DNS queries. */
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
||||
Filter.action.type = FWP_ACTION_BLOCK;
|
||||
Filter.weight.type = FWP_EMPTY;
|
||||
Filter.numFilterConditions = 1;
|
||||
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR (err, "Add filter to block IPv4 DNS traffic failed");
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR(err, "Add filter to block IPv4 DNS traffic failed");
|
||||
|
||||
/* Forth filter. Block all IPv6 DNS queries. */
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
||||
/* Forth filter. Block all IPv6 DNS queries. */
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
||||
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR (err, "Add filter to block IPv6 DNS traffic failed");
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR(err, "Add filter to block IPv6 DNS traffic failed");
|
||||
|
||||
msg_handler (0, "Block_DNS: Added block filters for all interfaces");
|
||||
msg_handler(0, "Block_DNS: Added block filters for all interfaces");
|
||||
|
||||
/* Fifth filter. Permit IPv4 DNS queries from TAP.
|
||||
* Use a non-zero weight so that the permit filters get higher priority
|
||||
* over the block filter added with automatic weighting */
|
||||
/* Fifth filter. Permit IPv4 DNS queries from TAP.
|
||||
* Use a non-zero weight so that the permit filters get higher priority
|
||||
* over the block filter added with automatic weighting */
|
||||
|
||||
Filter.weight.type = FWP_UINT8;
|
||||
Filter.weight.uint8 = 0xE;
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
||||
Filter.action.type = FWP_ACTION_PERMIT;
|
||||
Filter.numFilterConditions = 2;
|
||||
Filter.weight.type = FWP_UINT8;
|
||||
Filter.weight.uint8 = 0xE;
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
||||
Filter.action.type = FWP_ACTION_PERMIT;
|
||||
Filter.numFilterConditions = 2;
|
||||
|
||||
Condition[1].fieldKey = FWPM_CONDITION_IP_LOCAL_INTERFACE;
|
||||
Condition[1].matchType = FWP_MATCH_EQUAL;
|
||||
Condition[1].conditionValue.type = FWP_UINT64;
|
||||
Condition[1].conditionValue.uint64 = &tapluid.Value;
|
||||
Condition[1].fieldKey = FWPM_CONDITION_IP_LOCAL_INTERFACE;
|
||||
Condition[1].matchType = FWP_MATCH_EQUAL;
|
||||
Condition[1].conditionValue.type = FWP_UINT64;
|
||||
Condition[1].conditionValue.uint64 = &tapluid.Value;
|
||||
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR (err, "Add filter to permit IPv4 DNS traffic through TAP failed");
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR(err, "Add filter to permit IPv4 DNS traffic through TAP failed");
|
||||
|
||||
/* Sixth filter. Permit IPv6 DNS queries from TAP.
|
||||
* Use same weight as IPv4 filter */
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
||||
/* Sixth filter. Permit IPv6 DNS queries from TAP.
|
||||
* Use same weight as IPv4 filter */
|
||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
||||
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR (err, "Add filter to permit IPv6 DNS traffic through TAP failed");
|
||||
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||
CHECK_ERROR(err, "Add filter to permit IPv6 DNS traffic through TAP failed");
|
||||
|
||||
msg_handler (0, "Block_DNS: Added permit filters for TAP interface");
|
||||
msg_handler(0, "Block_DNS: Added permit filters for TAP interface");
|
||||
|
||||
out:
|
||||
|
||||
if (openvpnblob)
|
||||
FwpmFreeMemory0 ((void **)&openvpnblob);
|
||||
|
||||
if (err && *engine_handle)
|
||||
if (openvpnblob)
|
||||
{
|
||||
FwpmEngineClose0 (*engine_handle);
|
||||
*engine_handle = NULL;
|
||||
FwpmFreeMemory0((void **)&openvpnblob);
|
||||
}
|
||||
|
||||
return err;
|
||||
if (err && *engine_handle)
|
||||
{
|
||||
FwpmEngineClose0(*engine_handle);
|
||||
*engine_handle = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
DWORD
|
||||
delete_block_dns_filters (HANDLE engine_handle)
|
||||
delete_block_dns_filters(HANDLE engine_handle)
|
||||
{
|
||||
DWORD err = 0;
|
||||
/*
|
||||
* For dynamic sessions closing the engine removes all filters added in the session
|
||||
*/
|
||||
if (engine_handle)
|
||||
DWORD err = 0;
|
||||
/*
|
||||
* For dynamic sessions closing the engine removes all filters added in the session
|
||||
*/
|
||||
if (engine_handle)
|
||||
{
|
||||
err = FwpmEngineClose0(engine_handle);
|
||||
err = FwpmEngineClose0(engine_handle);
|
||||
}
|
||||
return err;
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* ifdef _WIN32 */
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@
|
|||
typedef void (*block_dns_msg_handler_t) (DWORD err, const char *msg);
|
||||
|
||||
DWORD
|
||||
delete_block_dns_filters (HANDLE engine);
|
||||
delete_block_dns_filters(HANDLE engine);
|
||||
|
||||
DWORD
|
||||
add_block_dns_filters (HANDLE *engine, int iface_index, const WCHAR *exe_path,
|
||||
block_dns_msg_handler_t msg_handler_callback);
|
||||
add_block_dns_filters(HANDLE *engine, int iface_index, const WCHAR *exe_path,
|
||||
block_dns_msg_handler_t msg_handler_callback);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
1423
src/openvpn/buffer.c
1423
src/openvpn/buffer.c
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -30,49 +30,49 @@
|
|||
#include "error.h"
|
||||
|
||||
#define CIRC_LIST(name, type) \
|
||||
struct name { \
|
||||
int x_head; \
|
||||
int x_size; \
|
||||
int x_cap; \
|
||||
int x_sizeof; \
|
||||
type x_list[EMPTY_ARRAY_SIZE]; \
|
||||
}
|
||||
struct name { \
|
||||
int x_head; \
|
||||
int x_size; \
|
||||
int x_cap; \
|
||||
int x_sizeof; \
|
||||
type x_list[EMPTY_ARRAY_SIZE]; \
|
||||
}
|
||||
|
||||
#define CIRC_LIST_PUSH(obj, item) \
|
||||
{ \
|
||||
(obj)->x_head = modulo_add ((obj)->x_head, -1, (obj)->x_cap); \
|
||||
(obj)->x_list[(obj)->x_head] = (item); \
|
||||
(obj)->x_size = min_int ((obj)->x_size + 1, (obj)->x_cap); \
|
||||
}
|
||||
{ \
|
||||
(obj)->x_head = modulo_add((obj)->x_head, -1, (obj)->x_cap); \
|
||||
(obj)->x_list[(obj)->x_head] = (item); \
|
||||
(obj)->x_size = min_int((obj)->x_size + 1, (obj)->x_cap); \
|
||||
}
|
||||
|
||||
#define CIRC_LIST_SIZE(obj) \
|
||||
((obj)->x_size)
|
||||
((obj)->x_size)
|
||||
|
||||
#define CIRC_LIST_INDEX(obj, index) \
|
||||
modulo_add ((obj)->x_head, \
|
||||
index_verify ((index), (obj)->x_size, __FILE__, __LINE__), \
|
||||
(obj)->x_cap)
|
||||
modulo_add((obj)->x_head, \
|
||||
index_verify((index), (obj)->x_size, __FILE__, __LINE__), \
|
||||
(obj)->x_cap)
|
||||
|
||||
#define CIRC_LIST_ITEM(obj, index) \
|
||||
((obj)->x_list[CIRC_LIST_INDEX((obj), (index))])
|
||||
((obj)->x_list[CIRC_LIST_INDEX((obj), (index))])
|
||||
|
||||
#define CIRC_LIST_RESET(obj) \
|
||||
{ \
|
||||
(obj)->x_head = 0; \
|
||||
(obj)->x_size = 0; \
|
||||
}
|
||||
{ \
|
||||
(obj)->x_head = 0; \
|
||||
(obj)->x_size = 0; \
|
||||
}
|
||||
|
||||
#define CIRC_LIST_ALLOC(dest, list_type, size) \
|
||||
{ \
|
||||
const int so = sizeof (list_type) + sizeof ((dest)->x_list[0]) * (size); \
|
||||
(dest) = (list_type *) malloc (so); \
|
||||
check_malloc_return (dest); \
|
||||
memset ((dest), 0, so); \
|
||||
(dest)->x_cap = size; \
|
||||
(dest)->x_sizeof = so; \
|
||||
}
|
||||
{ \
|
||||
const int so = sizeof(list_type) + sizeof((dest)->x_list[0]) * (size); \
|
||||
(dest) = (list_type *) malloc(so); \
|
||||
check_malloc_return(dest); \
|
||||
memset((dest), 0, so); \
|
||||
(dest)->x_cap = size; \
|
||||
(dest)->x_sizeof = so; \
|
||||
}
|
||||
|
||||
#define CIRC_LIST_FREE(dest) \
|
||||
free (dest)
|
||||
free(dest)
|
||||
|
||||
#endif
|
||||
#endif /* ifndef CIRC_LIST_H */
|
||||
|
|
|
|||
|
|
@ -37,229 +37,243 @@
|
|||
|
||||
static bool
|
||||
add_entry(struct client_nat_option_list *dest,
|
||||
const struct client_nat_entry *e)
|
||||
const struct client_nat_entry *e)
|
||||
{
|
||||
if (dest->n >= MAX_CLIENT_NAT)
|
||||
if (dest->n >= MAX_CLIENT_NAT)
|
||||
{
|
||||
msg (M_WARN, "WARNING: client-nat table overflow (max %d entries)", MAX_CLIENT_NAT);
|
||||
return false;
|
||||
msg(M_WARN, "WARNING: client-nat table overflow (max %d entries)", MAX_CLIENT_NAT);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
dest->entries[dest->n++] = *e;
|
||||
return true;
|
||||
dest->entries[dest->n++] = *e;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
print_client_nat_list(const struct client_nat_option_list *list, int msglevel)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
int i;
|
||||
struct gc_arena gc = gc_new();
|
||||
int i;
|
||||
|
||||
msg (msglevel, "*** CNAT list");
|
||||
if (list)
|
||||
msg(msglevel, "*** CNAT list");
|
||||
if (list)
|
||||
{
|
||||
for (i = 0; i < list->n; ++i)
|
||||
{
|
||||
const struct client_nat_entry *e = &list->entries[i];
|
||||
msg (msglevel, " CNAT[%d] t=%d %s/%s/%s",
|
||||
i,
|
||||
e->type,
|
||||
print_in_addr_t (e->network, IA_NET_ORDER, &gc),
|
||||
print_in_addr_t (e->netmask, IA_NET_ORDER, &gc),
|
||||
print_in_addr_t (e->foreign_network, IA_NET_ORDER, &gc));
|
||||
}
|
||||
for (i = 0; i < list->n; ++i)
|
||||
{
|
||||
const struct client_nat_entry *e = &list->entries[i];
|
||||
msg(msglevel, " CNAT[%d] t=%d %s/%s/%s",
|
||||
i,
|
||||
e->type,
|
||||
print_in_addr_t(e->network, IA_NET_ORDER, &gc),
|
||||
print_in_addr_t(e->netmask, IA_NET_ORDER, &gc),
|
||||
print_in_addr_t(e->foreign_network, IA_NET_ORDER, &gc));
|
||||
}
|
||||
}
|
||||
gc_free (&gc);
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
struct client_nat_option_list *
|
||||
new_client_nat_list (struct gc_arena *gc)
|
||||
new_client_nat_list(struct gc_arena *gc)
|
||||
{
|
||||
struct client_nat_option_list *ret;
|
||||
ALLOC_OBJ_CLEAR_GC (ret, struct client_nat_option_list, gc);
|
||||
return ret;
|
||||
struct client_nat_option_list *ret;
|
||||
ALLOC_OBJ_CLEAR_GC(ret, struct client_nat_option_list, gc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct client_nat_option_list *
|
||||
clone_client_nat_option_list (const struct client_nat_option_list *src, struct gc_arena *gc)
|
||||
clone_client_nat_option_list(const struct client_nat_option_list *src, struct gc_arena *gc)
|
||||
{
|
||||
struct client_nat_option_list *ret;
|
||||
ALLOC_OBJ_GC (ret, struct client_nat_option_list, gc);
|
||||
*ret = *src;
|
||||
return ret;
|
||||
struct client_nat_option_list *ret;
|
||||
ALLOC_OBJ_GC(ret, struct client_nat_option_list, gc);
|
||||
*ret = *src;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
copy_client_nat_option_list (struct client_nat_option_list *dest,
|
||||
const struct client_nat_option_list *src)
|
||||
copy_client_nat_option_list(struct client_nat_option_list *dest,
|
||||
const struct client_nat_option_list *src)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < src->n; ++i)
|
||||
int i;
|
||||
for (i = 0; i < src->n; ++i)
|
||||
{
|
||||
if (!add_entry(dest, &src->entries[i]))
|
||||
break;
|
||||
if (!add_entry(dest, &src->entries[i]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
add_client_nat_to_option_list (struct client_nat_option_list *dest,
|
||||
const char *type,
|
||||
const char *network,
|
||||
const char *netmask,
|
||||
const char *foreign_network,
|
||||
int msglevel)
|
||||
add_client_nat_to_option_list(struct client_nat_option_list *dest,
|
||||
const char *type,
|
||||
const char *network,
|
||||
const char *netmask,
|
||||
const char *foreign_network,
|
||||
int msglevel)
|
||||
{
|
||||
struct client_nat_entry e;
|
||||
bool ok;
|
||||
struct client_nat_entry e;
|
||||
bool ok;
|
||||
|
||||
if (!strcmp(type, "snat"))
|
||||
e.type = CN_SNAT;
|
||||
else if (!strcmp(type, "dnat"))
|
||||
e.type = CN_DNAT;
|
||||
else
|
||||
if (!strcmp(type, "snat"))
|
||||
{
|
||||
msg(msglevel, "client-nat: type must be 'snat' or 'dnat'");
|
||||
return;
|
||||
e.type = CN_SNAT;
|
||||
}
|
||||
else if (!strcmp(type, "dnat"))
|
||||
{
|
||||
e.type = CN_DNAT;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg(msglevel, "client-nat: type must be 'snat' or 'dnat'");
|
||||
return;
|
||||
}
|
||||
|
||||
e.network = getaddr(0, network, 0, &ok, NULL);
|
||||
if (!ok)
|
||||
e.network = getaddr(0, network, 0, &ok, NULL);
|
||||
if (!ok)
|
||||
{
|
||||
msg(msglevel, "client-nat: bad network: %s", network);
|
||||
return;
|
||||
msg(msglevel, "client-nat: bad network: %s", network);
|
||||
return;
|
||||
}
|
||||
e.netmask = getaddr(0, netmask, 0, &ok, NULL);
|
||||
if (!ok)
|
||||
e.netmask = getaddr(0, netmask, 0, &ok, NULL);
|
||||
if (!ok)
|
||||
{
|
||||
msg(msglevel, "client-nat: bad netmask: %s", netmask);
|
||||
return;
|
||||
msg(msglevel, "client-nat: bad netmask: %s", netmask);
|
||||
return;
|
||||
}
|
||||
e.foreign_network = getaddr(0, foreign_network, 0, &ok, NULL);
|
||||
if (!ok)
|
||||
e.foreign_network = getaddr(0, foreign_network, 0, &ok, NULL);
|
||||
if (!ok)
|
||||
{
|
||||
msg(msglevel, "client-nat: bad foreign network: %s", foreign_network);
|
||||
return;
|
||||
msg(msglevel, "client-nat: bad foreign network: %s", foreign_network);
|
||||
return;
|
||||
}
|
||||
|
||||
add_entry(dest, &e);
|
||||
add_entry(dest, &e);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
print_checksum (struct openvpn_iphdr *iph, const char *prefix)
|
||||
print_checksum(struct openvpn_iphdr *iph, const char *prefix)
|
||||
{
|
||||
uint16_t *sptr;
|
||||
unsigned int sum = 0;
|
||||
int i = 0;
|
||||
for (sptr = (uint16_t *)iph; (uint8_t *)sptr < (uint8_t *)iph + sizeof(struct openvpn_iphdr); sptr++)
|
||||
uint16_t *sptr;
|
||||
unsigned int sum = 0;
|
||||
int i = 0;
|
||||
for (sptr = (uint16_t *)iph; (uint8_t *)sptr < (uint8_t *)iph + sizeof(struct openvpn_iphdr); sptr++)
|
||||
{
|
||||
i += 1;
|
||||
sum += *sptr;
|
||||
i += 1;
|
||||
sum += *sptr;
|
||||
}
|
||||
msg (M_INFO, "** CKSUM[%d] %s %08x", i, prefix, sum);
|
||||
msg(M_INFO, "** CKSUM[%d] %s %08x", i, prefix, sum);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
print_pkt (struct openvpn_iphdr *iph, const char *prefix, const int direction, const int msglevel)
|
||||
print_pkt(struct openvpn_iphdr *iph, const char *prefix, const int direction, const int msglevel)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct gc_arena gc = gc_new();
|
||||
|
||||
char *dirstr = "???";
|
||||
if (direction == CN_OUTGOING)
|
||||
dirstr = "OUT";
|
||||
else if (direction == CN_INCOMING)
|
||||
dirstr = "IN";
|
||||
char *dirstr = "???";
|
||||
if (direction == CN_OUTGOING)
|
||||
{
|
||||
dirstr = "OUT";
|
||||
}
|
||||
else if (direction == CN_INCOMING)
|
||||
{
|
||||
dirstr = "IN";
|
||||
}
|
||||
|
||||
msg(msglevel, "** CNAT %s %s %s -> %s",
|
||||
dirstr,
|
||||
prefix,
|
||||
print_in_addr_t (iph->saddr, IA_NET_ORDER, &gc),
|
||||
print_in_addr_t (iph->daddr, IA_NET_ORDER, &gc));
|
||||
|
||||
gc_free (&gc);
|
||||
msg(msglevel, "** CNAT %s %s %s -> %s",
|
||||
dirstr,
|
||||
prefix,
|
||||
print_in_addr_t(iph->saddr, IA_NET_ORDER, &gc),
|
||||
print_in_addr_t(iph->daddr, IA_NET_ORDER, &gc));
|
||||
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
void
|
||||
client_nat_transform (const struct client_nat_option_list *list,
|
||||
struct buffer *ipbuf,
|
||||
const int direction)
|
||||
client_nat_transform(const struct client_nat_option_list *list,
|
||||
struct buffer *ipbuf,
|
||||
const int direction)
|
||||
{
|
||||
struct ip_tcp_udp_hdr *h = (struct ip_tcp_udp_hdr *) BPTR (ipbuf);
|
||||
int i;
|
||||
uint32_t addr, *addr_ptr;
|
||||
const uint32_t *from, *to;
|
||||
int accumulate = 0;
|
||||
unsigned int amask;
|
||||
unsigned int alog = 0;
|
||||
struct ip_tcp_udp_hdr *h = (struct ip_tcp_udp_hdr *) BPTR(ipbuf);
|
||||
int i;
|
||||
uint32_t addr, *addr_ptr;
|
||||
const uint32_t *from, *to;
|
||||
int accumulate = 0;
|
||||
unsigned int amask;
|
||||
unsigned int alog = 0;
|
||||
|
||||
if (check_debug_level (D_CLIENT_NAT))
|
||||
print_pkt (&h->ip, "BEFORE", direction, D_CLIENT_NAT);
|
||||
|
||||
for (i = 0; i < list->n; ++i)
|
||||
if (check_debug_level(D_CLIENT_NAT))
|
||||
{
|
||||
const struct client_nat_entry *e = &list->entries[i]; /* current NAT rule */
|
||||
if (e->type ^ direction)
|
||||
{
|
||||
addr = *(addr_ptr = &h->ip.daddr);
|
||||
amask = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = *(addr_ptr = &h->ip.saddr);
|
||||
amask = 1;
|
||||
}
|
||||
if (direction)
|
||||
{
|
||||
from = &e->foreign_network;
|
||||
to = &e->network;
|
||||
}
|
||||
else
|
||||
{
|
||||
from = &e->network;
|
||||
to = &e->foreign_network;
|
||||
}
|
||||
|
||||
if (((addr & e->netmask) == *from) && !(amask & alog))
|
||||
{
|
||||
/* pre-adjust IP checksum */
|
||||
ADD_CHECKSUM_32(accumulate, addr);
|
||||
|
||||
/* do NAT transform */
|
||||
addr = (addr & ~e->netmask) | *to;
|
||||
|
||||
/* post-adjust IP checksum */
|
||||
SUB_CHECKSUM_32(accumulate, addr);
|
||||
|
||||
/* write the modified address to packet */
|
||||
*addr_ptr = addr;
|
||||
|
||||
/* mark as modified */
|
||||
alog |= amask;
|
||||
}
|
||||
print_pkt(&h->ip, "BEFORE", direction, D_CLIENT_NAT);
|
||||
}
|
||||
if (alog)
|
||||
|
||||
for (i = 0; i < list->n; ++i)
|
||||
{
|
||||
if (check_debug_level (D_CLIENT_NAT))
|
||||
print_pkt (&h->ip, "AFTER", direction, D_CLIENT_NAT);
|
||||
const struct client_nat_entry *e = &list->entries[i]; /* current NAT rule */
|
||||
if (e->type ^ direction)
|
||||
{
|
||||
addr = *(addr_ptr = &h->ip.daddr);
|
||||
amask = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = *(addr_ptr = &h->ip.saddr);
|
||||
amask = 1;
|
||||
}
|
||||
if (direction)
|
||||
{
|
||||
from = &e->foreign_network;
|
||||
to = &e->network;
|
||||
}
|
||||
else
|
||||
{
|
||||
from = &e->network;
|
||||
to = &e->foreign_network;
|
||||
}
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, h->ip.check);
|
||||
if (((addr & e->netmask) == *from) && !(amask & alog))
|
||||
{
|
||||
/* pre-adjust IP checksum */
|
||||
ADD_CHECKSUM_32(accumulate, addr);
|
||||
|
||||
if (h->ip.protocol == OPENVPN_IPPROTO_TCP)
|
||||
{
|
||||
if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct openvpn_tcphdr))
|
||||
{
|
||||
ADJUST_CHECKSUM(accumulate, h->u.tcp.check);
|
||||
}
|
||||
}
|
||||
else if (h->ip.protocol == OPENVPN_IPPROTO_UDP)
|
||||
{
|
||||
if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct openvpn_udphdr))
|
||||
{
|
||||
ADJUST_CHECKSUM(accumulate, h->u.udp.check);
|
||||
}
|
||||
}
|
||||
/* do NAT transform */
|
||||
addr = (addr & ~e->netmask) | *to;
|
||||
|
||||
/* post-adjust IP checksum */
|
||||
SUB_CHECKSUM_32(accumulate, addr);
|
||||
|
||||
/* write the modified address to packet */
|
||||
*addr_ptr = addr;
|
||||
|
||||
/* mark as modified */
|
||||
alog |= amask;
|
||||
}
|
||||
}
|
||||
if (alog)
|
||||
{
|
||||
if (check_debug_level(D_CLIENT_NAT))
|
||||
{
|
||||
print_pkt(&h->ip, "AFTER", direction, D_CLIENT_NAT);
|
||||
}
|
||||
|
||||
ADJUST_CHECKSUM(accumulate, h->ip.check);
|
||||
|
||||
if (h->ip.protocol == OPENVPN_IPPROTO_TCP)
|
||||
{
|
||||
if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct openvpn_tcphdr))
|
||||
{
|
||||
ADJUST_CHECKSUM(accumulate, h->u.tcp.check);
|
||||
}
|
||||
}
|
||||
else if (h->ip.protocol == OPENVPN_IPPROTO_UDP)
|
||||
{
|
||||
if (BLEN(ipbuf) >= sizeof(struct openvpn_iphdr) + sizeof(struct openvpn_udphdr))
|
||||
{
|
||||
ADJUST_CHECKSUM(accumulate, h->u.udp.check);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,33 +33,36 @@
|
|||
#define CN_INCOMING 1
|
||||
|
||||
struct client_nat_entry {
|
||||
# define CN_SNAT 0
|
||||
# define CN_DNAT 1
|
||||
int type;
|
||||
in_addr_t network;
|
||||
in_addr_t netmask;
|
||||
in_addr_t foreign_network;
|
||||
#define CN_SNAT 0
|
||||
#define CN_DNAT 1
|
||||
int type;
|
||||
in_addr_t network;
|
||||
in_addr_t netmask;
|
||||
in_addr_t foreign_network;
|
||||
};
|
||||
|
||||
struct client_nat_option_list {
|
||||
int n;
|
||||
struct client_nat_entry entries[MAX_CLIENT_NAT];
|
||||
int n;
|
||||
struct client_nat_entry entries[MAX_CLIENT_NAT];
|
||||
};
|
||||
|
||||
struct client_nat_option_list *new_client_nat_list (struct gc_arena *gc);
|
||||
struct client_nat_option_list *clone_client_nat_option_list (const struct client_nat_option_list *src, struct gc_arena *gc);
|
||||
void copy_client_nat_option_list (struct client_nat_option_list *dest, const struct client_nat_option_list *src);
|
||||
struct client_nat_option_list *new_client_nat_list(struct gc_arena *gc);
|
||||
|
||||
struct client_nat_option_list *clone_client_nat_option_list(const struct client_nat_option_list *src, struct gc_arena *gc);
|
||||
|
||||
void copy_client_nat_option_list(struct client_nat_option_list *dest, const struct client_nat_option_list *src);
|
||||
|
||||
void print_client_nat_list(const struct client_nat_option_list *list, int msglevel);
|
||||
|
||||
void add_client_nat_to_option_list (struct client_nat_option_list *dest,
|
||||
const char *type,
|
||||
const char *network,
|
||||
const char *netmask,
|
||||
const char *foreign_network,
|
||||
int msglevel);
|
||||
void add_client_nat_to_option_list(struct client_nat_option_list *dest,
|
||||
const char *type,
|
||||
const char *network,
|
||||
const char *netmask,
|
||||
const char *foreign_network,
|
||||
int msglevel);
|
||||
|
||||
void client_nat_transform (const struct client_nat_option_list *list,
|
||||
struct buffer *ipbuf,
|
||||
const int direction);
|
||||
void client_nat_transform(const struct client_nat_option_list *list,
|
||||
struct buffer *ipbuf,
|
||||
const int direction);
|
||||
|
||||
#endif
|
||||
#endif /* if !defined(CLINAT_H) */
|
||||
|
|
|
|||
|
|
@ -29,15 +29,15 @@
|
|||
* Statistics counters and associated printf formats.
|
||||
*/
|
||||
#ifdef USE_64_BIT_COUNTERS
|
||||
typedef unsigned long long int counter_type;
|
||||
# ifdef _WIN32
|
||||
# define counter_format "%I64u"
|
||||
# else
|
||||
# define counter_format "%llu"
|
||||
# endif
|
||||
typedef unsigned long long int counter_type;
|
||||
#ifdef _WIN32
|
||||
#define counter_format "%I64u"
|
||||
#else
|
||||
typedef unsigned int counter_type;
|
||||
# define counter_format "%u"
|
||||
#define counter_format "%llu"
|
||||
#endif
|
||||
#else /* ifdef USE_64_BIT_COUNTERS */
|
||||
typedef unsigned int counter_type;
|
||||
#define counter_format "%u"
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -102,4 +102,4 @@ typedef unsigned long ptr_type;
|
|||
*/
|
||||
#define SCRIPT_SECURITY_WARNING "WARNING: External program may not be called unless '--script-security 2' or higher is enabled. See --help text or man page for detailed info."
|
||||
|
||||
#endif
|
||||
#endif /* ifndef COMMON_H */
|
||||
|
|
|
|||
|
|
@ -45,263 +45,277 @@
|
|||
#include "memdbg.h"
|
||||
|
||||
static void
|
||||
lz4_compress_init (struct compress_context *compctx)
|
||||
lz4_compress_init(struct compress_context *compctx)
|
||||
{
|
||||
msg (D_INIT_MEDIUM, "LZ4 compression initializing");
|
||||
ASSERT(compctx->flags & COMP_F_SWAP);
|
||||
msg(D_INIT_MEDIUM, "LZ4 compression initializing");
|
||||
ASSERT(compctx->flags & COMP_F_SWAP);
|
||||
}
|
||||
|
||||
static void
|
||||
lz4v2_compress_init (struct compress_context *compctx)
|
||||
lz4v2_compress_init(struct compress_context *compctx)
|
||||
{
|
||||
msg (D_INIT_MEDIUM, "LZ4v2 compression initializing");
|
||||
msg(D_INIT_MEDIUM, "LZ4v2 compression initializing");
|
||||
}
|
||||
|
||||
static void
|
||||
lz4_compress_uninit (struct compress_context *compctx)
|
||||
lz4_compress_uninit(struct compress_context *compctx)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
do_lz4_compress (struct buffer *buf,
|
||||
struct buffer *work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
do_lz4_compress(struct buffer *buf,
|
||||
struct buffer *work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
/*
|
||||
* In order to attempt compression, length must be at least COMPRESS_THRESHOLD.
|
||||
*/
|
||||
if (buf->len >= COMPRESS_THRESHOLD)
|
||||
/*
|
||||
* In order to attempt compression, length must be at least COMPRESS_THRESHOLD.
|
||||
*/
|
||||
if (buf->len >= COMPRESS_THRESHOLD)
|
||||
{
|
||||
const size_t ps = PAYLOAD_SIZE (frame);
|
||||
int zlen_max = ps + COMP_EXTRA_BUFFER (ps);
|
||||
int zlen;
|
||||
const size_t ps = PAYLOAD_SIZE(frame);
|
||||
int zlen_max = ps + COMP_EXTRA_BUFFER(ps);
|
||||
int zlen;
|
||||
|
||||
ASSERT (buf_init (work, FRAME_HEADROOM (frame)));
|
||||
ASSERT (buf_safe (work, zlen_max));
|
||||
ASSERT(buf_init(work, FRAME_HEADROOM(frame)));
|
||||
ASSERT(buf_safe(work, zlen_max));
|
||||
|
||||
if (buf->len > ps)
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "LZ4 compression buffer overflow");
|
||||
buf->len = 0;
|
||||
return false;
|
||||
}
|
||||
if (buf->len > ps)
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "LZ4 compression buffer overflow");
|
||||
buf->len = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
zlen = LZ4_compress_limitedOutput((const char *)BPTR(buf), (char *)BPTR(work), BLEN(buf), zlen_max );
|
||||
zlen = LZ4_compress_limitedOutput((const char *)BPTR(buf), (char *)BPTR(work), BLEN(buf), zlen_max );
|
||||
|
||||
if (zlen <= 0)
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "LZ4 compression error");
|
||||
buf->len = 0;
|
||||
return false;
|
||||
}
|
||||
if (zlen <= 0)
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "LZ4 compression error");
|
||||
buf->len = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
ASSERT (buf_safe (work, zlen));
|
||||
work->len = zlen;
|
||||
ASSERT(buf_safe(work, zlen));
|
||||
work->len = zlen;
|
||||
|
||||
|
||||
dmsg (D_COMP, "LZ4 compress %d -> %d", buf->len, work->len);
|
||||
compctx->pre_compress += buf->len;
|
||||
compctx->post_compress += work->len;
|
||||
return true;
|
||||
dmsg(D_COMP, "LZ4 compress %d -> %d", buf->len, work->len);
|
||||
compctx->pre_compress += buf->len;
|
||||
compctx->post_compress += work->len;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lz4_compress (struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
lz4_compress(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
bool compressed;
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
|
||||
compressed = do_lz4_compress(buf, &work, compctx, frame);
|
||||
|
||||
/* On error do_lz4_compress sets buf len to zero, just return */
|
||||
if (buf->len == 0)
|
||||
return;
|
||||
|
||||
/* did compression save us anything? */
|
||||
{
|
||||
uint8_t comp_head_byte = NO_COMPRESS_BYTE_SWAP;
|
||||
if (compressed && work.len < buf->len)
|
||||
{
|
||||
*buf = work;
|
||||
comp_head_byte = LZ4_COMPRESS_BYTE;
|
||||
}
|
||||
|
||||
bool compressed;
|
||||
if (buf->len <= 0)
|
||||
{
|
||||
uint8_t *head = BPTR (buf);
|
||||
uint8_t *tail = BEND (buf);
|
||||
ASSERT (buf_safe (buf, 1));
|
||||
++buf->len;
|
||||
|
||||
/* move head byte of payload to tail */
|
||||
*tail = *head;
|
||||
*head = comp_head_byte;
|
||||
return;
|
||||
}
|
||||
|
||||
compressed = do_lz4_compress(buf, &work, compctx, frame);
|
||||
|
||||
/* On error do_lz4_compress sets buf len to zero, just return */
|
||||
if (buf->len == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* did compression save us anything? */
|
||||
{
|
||||
uint8_t comp_head_byte = NO_COMPRESS_BYTE_SWAP;
|
||||
if (compressed && work.len < buf->len)
|
||||
{
|
||||
*buf = work;
|
||||
comp_head_byte = LZ4_COMPRESS_BYTE;
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t *head = BPTR(buf);
|
||||
uint8_t *tail = BEND(buf);
|
||||
ASSERT(buf_safe(buf, 1));
|
||||
++buf->len;
|
||||
|
||||
/* move head byte of payload to tail */
|
||||
*tail = *head;
|
||||
*head = comp_head_byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lz4v2_compress (struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
lz4v2_compress(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
bool compressed;
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
|
||||
compressed = do_lz4_compress(buf, &work, compctx, frame);
|
||||
|
||||
/* On Error just return */
|
||||
if (buf->len == 0)
|
||||
return;
|
||||
|
||||
/* did compression save us anything? Include 2 byte compression header
|
||||
in calculation */
|
||||
if (compressed && work.len + 2 < buf->len)
|
||||
bool compressed;
|
||||
if (buf->len <= 0)
|
||||
{
|
||||
ASSERT(buf_prepend(&work, 2));
|
||||
uint8_t *head = BPTR (&work);
|
||||
head[0] = COMP_ALGV2_INDICATOR_BYTE;
|
||||
head[1] = COMP_ALGV2_LZ4_BYTE;
|
||||
*buf = work;
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
compressed = do_lz4_compress(buf, &work, compctx, frame);
|
||||
|
||||
/* On Error just return */
|
||||
if (buf->len == 0)
|
||||
{
|
||||
compv2_escape_data_ifneeded(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* did compression save us anything? Include 2 byte compression header
|
||||
* in calculation */
|
||||
if (compressed && work.len + 2 < buf->len)
|
||||
{
|
||||
ASSERT(buf_prepend(&work, 2));
|
||||
uint8_t *head = BPTR(&work);
|
||||
head[0] = COMP_ALGV2_INDICATOR_BYTE;
|
||||
head[1] = COMP_ALGV2_LZ4_BYTE;
|
||||
*buf = work;
|
||||
}
|
||||
else
|
||||
{
|
||||
compv2_escape_data_ifneeded(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
do_lz4_decompress(size_t zlen_max,
|
||||
struct buffer *work,
|
||||
struct buffer *buf,
|
||||
struct compress_context *compctx)
|
||||
struct buffer *work,
|
||||
struct buffer *buf,
|
||||
struct compress_context *compctx)
|
||||
{
|
||||
int uncomp_len;
|
||||
ASSERT (buf_safe (work, zlen_max));
|
||||
uncomp_len = LZ4_decompress_safe((const char *)BPTR(buf), (char *)BPTR(work), (size_t)BLEN(buf), zlen_max);
|
||||
if (uncomp_len <= 0)
|
||||
int uncomp_len;
|
||||
ASSERT(buf_safe(work, zlen_max));
|
||||
uncomp_len = LZ4_decompress_safe((const char *)BPTR(buf), (char *)BPTR(work), (size_t)BLEN(buf), zlen_max);
|
||||
if (uncomp_len <= 0)
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "LZ4 decompression error: %d", uncomp_len);
|
||||
buf->len = 0;
|
||||
return;
|
||||
dmsg(D_COMP_ERRORS, "LZ4 decompression error: %d", uncomp_len);
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT (buf_safe (work, uncomp_len));
|
||||
work->len = uncomp_len;
|
||||
ASSERT(buf_safe(work, uncomp_len));
|
||||
work->len = uncomp_len;
|
||||
|
||||
dmsg (D_COMP, "LZ4 decompress %d -> %d", buf->len, work->len);
|
||||
compctx->pre_decompress += buf->len;
|
||||
compctx->post_decompress += work->len;
|
||||
dmsg(D_COMP, "LZ4 decompress %d -> %d", buf->len, work->len);
|
||||
compctx->pre_decompress += buf->len;
|
||||
compctx->post_decompress += work->len;
|
||||
|
||||
*buf = *work;
|
||||
*buf = *work;
|
||||
}
|
||||
|
||||
static void
|
||||
lz4_decompress (struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
lz4_decompress(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
size_t zlen_max = EXPANDED_SIZE (frame);
|
||||
uint8_t c; /* flag indicating whether or not our peer compressed */
|
||||
size_t zlen_max = EXPANDED_SIZE(frame);
|
||||
uint8_t c; /* flag indicating whether or not our peer compressed */
|
||||
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
if (buf->len <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT (buf_init (&work, FRAME_HEADROOM (frame)));
|
||||
ASSERT(buf_init(&work, FRAME_HEADROOM(frame)));
|
||||
|
||||
/* do unframing/swap (assumes buf->len > 0) */
|
||||
{
|
||||
uint8_t *head = BPTR (buf);
|
||||
/* do unframing/swap (assumes buf->len > 0) */
|
||||
{
|
||||
uint8_t *head = BPTR(buf);
|
||||
c = *head;
|
||||
--buf->len;
|
||||
*head = *BEND(buf);
|
||||
}
|
||||
|
||||
if (c == LZ4_COMPRESS_BYTE) /* packet was compressed */
|
||||
{
|
||||
do_lz4_decompress(zlen_max, &work, buf, compctx);
|
||||
}
|
||||
else if (c == NO_COMPRESS_BYTE_SWAP) /* packet was not compressed */
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "Bad LZ4 decompression header byte: %d", c);
|
||||
buf->len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lz4v2_decompress(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
size_t zlen_max = EXPANDED_SIZE(frame);
|
||||
uint8_t c; /* flag indicating whether or not our peer compressed */
|
||||
|
||||
if (buf->len <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(buf_init(&work, FRAME_HEADROOM(frame)));
|
||||
|
||||
/* do unframing/swap (assumes buf->len > 0) */
|
||||
uint8_t *head = BPTR(buf);
|
||||
c = *head;
|
||||
--buf->len;
|
||||
*head = *BEND (buf);
|
||||
}
|
||||
|
||||
if (c == LZ4_COMPRESS_BYTE) /* packet was compressed */
|
||||
/* Not compressed */
|
||||
if (c != COMP_ALGV2_INDICATOR_BYTE)
|
||||
{
|
||||
do_lz4_decompress(zlen_max, &work, buf, compctx);
|
||||
}
|
||||
else if (c == NO_COMPRESS_BYTE_SWAP) /* packet was not compressed */
|
||||
{
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "Bad LZ4 decompression header byte: %d", c);
|
||||
buf->len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lz4v2_decompress (struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
{
|
||||
size_t zlen_max = EXPANDED_SIZE (frame);
|
||||
uint8_t c; /* flag indicating whether or not our peer compressed */
|
||||
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
|
||||
ASSERT (buf_init (&work, FRAME_HEADROOM (frame)));
|
||||
|
||||
/* do unframing/swap (assumes buf->len > 0) */
|
||||
uint8_t *head = BPTR (buf);
|
||||
c = *head;
|
||||
|
||||
/* Not compressed */
|
||||
if (c != COMP_ALGV2_INDICATOR_BYTE) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Packet to short to make sense */
|
||||
if (buf->len <= 1)
|
||||
{
|
||||
buf->len=0;
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
c = head[1];
|
||||
if (c == COMP_ALGV2_LZ4_BYTE) /* packet was compressed */
|
||||
/* Packet to short to make sense */
|
||||
if (buf->len <= 1)
|
||||
{
|
||||
buf_advance(buf,2);
|
||||
do_lz4_decompress(zlen_max, &work, buf, compctx);
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
else if (c == COMP_ALGV2_UNCOMPRESSED_BYTE)
|
||||
|
||||
c = head[1];
|
||||
if (c == COMP_ALGV2_LZ4_BYTE) /* packet was compressed */
|
||||
{
|
||||
buf_advance(buf,2);
|
||||
buf_advance(buf,2);
|
||||
do_lz4_decompress(zlen_max, &work, buf, compctx);
|
||||
}
|
||||
else
|
||||
else if (c == COMP_ALGV2_UNCOMPRESSED_BYTE)
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "Bad LZ4v2 decompression header byte: %d", c);
|
||||
buf->len = 0;
|
||||
buf_advance(buf,2);
|
||||
}
|
||||
else
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "Bad LZ4v2 decompression header byte: %d", c);
|
||||
buf->len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const struct compress_alg lz4_alg = {
|
||||
"lz4",
|
||||
lz4_compress_init,
|
||||
lz4_compress_uninit,
|
||||
lz4_compress,
|
||||
lz4_decompress
|
||||
"lz4",
|
||||
lz4_compress_init,
|
||||
lz4_compress_uninit,
|
||||
lz4_compress,
|
||||
lz4_decompress
|
||||
};
|
||||
|
||||
const struct compress_alg lz4v2_alg = {
|
||||
"lz4v2",
|
||||
lz4v2_compress_init,
|
||||
lz4_compress_uninit,
|
||||
lz4v2_compress,
|
||||
lz4v2_decompress
|
||||
"lz4v2",
|
||||
lz4v2_compress_init,
|
||||
lz4_compress_uninit,
|
||||
lz4v2_compress,
|
||||
lz4v2_decompress
|
||||
};
|
||||
|
||||
#else
|
||||
static void dummy(void) {}
|
||||
#else /* if defined(ENABLE_LZ4) */
|
||||
static void
|
||||
dummy(void) {
|
||||
}
|
||||
#endif /* ENABLE_LZ4 */
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ extern const struct compress_alg lz4v2_alg;
|
|||
|
||||
struct lz4_workspace
|
||||
{
|
||||
int dummy;
|
||||
int dummy;
|
||||
};
|
||||
|
||||
#endif /* ENABLE_LZ4 */
|
||||
|
|
|
|||
|
|
@ -41,59 +41,67 @@
|
|||
struct compress_context *
|
||||
comp_init(const struct compress_options *opt)
|
||||
{
|
||||
struct compress_context *compctx = NULL;
|
||||
switch (opt->alg)
|
||||
struct compress_context *compctx = NULL;
|
||||
switch (opt->alg)
|
||||
{
|
||||
case COMP_ALG_STUB:
|
||||
ALLOC_OBJ_CLEAR (compctx, struct compress_context);
|
||||
compctx->flags = opt->flags;
|
||||
compctx->alg = comp_stub_alg;
|
||||
break;
|
||||
case COMP_ALGV2_UNCOMPRESSED:
|
||||
ALLOC_OBJ_CLEAR (compctx, struct compress_context);
|
||||
compctx->flags = opt->flags;
|
||||
compctx->alg = compv2_stub_alg;
|
||||
break;
|
||||
case COMP_ALG_STUB:
|
||||
ALLOC_OBJ_CLEAR(compctx, struct compress_context);
|
||||
compctx->flags = opt->flags;
|
||||
compctx->alg = comp_stub_alg;
|
||||
break;
|
||||
|
||||
case COMP_ALGV2_UNCOMPRESSED:
|
||||
ALLOC_OBJ_CLEAR(compctx, struct compress_context);
|
||||
compctx->flags = opt->flags;
|
||||
compctx->alg = compv2_stub_alg;
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_LZO
|
||||
case COMP_ALG_LZO:
|
||||
ALLOC_OBJ_CLEAR (compctx, struct compress_context);
|
||||
compctx->flags = opt->flags;
|
||||
compctx->alg = lzo_alg;
|
||||
break;
|
||||
case COMP_ALG_LZO:
|
||||
ALLOC_OBJ_CLEAR(compctx, struct compress_context);
|
||||
compctx->flags = opt->flags;
|
||||
compctx->alg = lzo_alg;
|
||||
break;
|
||||
|
||||
#endif
|
||||
#ifdef ENABLE_LZ4
|
||||
case COMP_ALG_LZ4:
|
||||
ALLOC_OBJ_CLEAR (compctx, struct compress_context);
|
||||
compctx->flags = opt->flags;
|
||||
compctx->alg = lz4_alg;
|
||||
break;
|
||||
case COMP_ALGV2_LZ4:
|
||||
ALLOC_OBJ_CLEAR (compctx, struct compress_context);
|
||||
compctx->flags = opt->flags;
|
||||
compctx->alg = lz4v2_alg;
|
||||
break;
|
||||
case COMP_ALG_LZ4:
|
||||
ALLOC_OBJ_CLEAR(compctx, struct compress_context);
|
||||
compctx->flags = opt->flags;
|
||||
compctx->alg = lz4_alg;
|
||||
break;
|
||||
|
||||
case COMP_ALGV2_LZ4:
|
||||
ALLOC_OBJ_CLEAR(compctx, struct compress_context);
|
||||
compctx->flags = opt->flags;
|
||||
compctx->alg = lz4v2_alg;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (compctx)
|
||||
(*compctx->alg.compress_init)(compctx);
|
||||
if (compctx)
|
||||
{
|
||||
(*compctx->alg.compress_init)(compctx);
|
||||
}
|
||||
|
||||
return compctx;
|
||||
return compctx;
|
||||
}
|
||||
|
||||
/* In the v2 compression schemes, an uncompressed packet has
|
||||
* has no opcode in front, unless the first byte is 0x50. In this
|
||||
* case the packet needs to be escaped */
|
||||
void
|
||||
compv2_escape_data_ifneeded (struct buffer *buf)
|
||||
compv2_escape_data_ifneeded(struct buffer *buf)
|
||||
{
|
||||
uint8_t *head = BPTR (buf);
|
||||
uint8_t *head = BPTR(buf);
|
||||
if (head[0] != COMP_ALGV2_INDICATOR_BYTE)
|
||||
return;
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Header is 0x50 */
|
||||
ASSERT(buf_prepend(buf, 2));
|
||||
|
||||
head = BPTR (buf);
|
||||
head = BPTR(buf);
|
||||
head[0] = COMP_ALGV2_INDICATOR_BYTE;
|
||||
head[1] = COMP_ALGV2_UNCOMPRESSED;
|
||||
}
|
||||
|
|
@ -102,37 +110,37 @@ compv2_escape_data_ifneeded (struct buffer *buf)
|
|||
void
|
||||
comp_uninit(struct compress_context *compctx)
|
||||
{
|
||||
if (compctx)
|
||||
if (compctx)
|
||||
{
|
||||
(*compctx->alg.compress_uninit)(compctx);
|
||||
free(compctx);
|
||||
(*compctx->alg.compress_uninit)(compctx);
|
||||
free(compctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
comp_add_to_extra_frame(struct frame *frame)
|
||||
{
|
||||
/* Leave room for our one-byte compressed/didn't-compress prefix byte. */
|
||||
frame_add_to_extra_frame (frame, COMP_PREFIX_LEN);
|
||||
/* Leave room for our one-byte compressed/didn't-compress prefix byte. */
|
||||
frame_add_to_extra_frame(frame, COMP_PREFIX_LEN);
|
||||
}
|
||||
|
||||
void
|
||||
comp_add_to_extra_buffer(struct frame *frame)
|
||||
{
|
||||
/* Leave room for compression buffer to expand in worst case scenario
|
||||
where data is totally uncompressible */
|
||||
frame_add_to_extra_buffer (frame, COMP_EXTRA_BUFFER (EXPANDED_SIZE(frame)));
|
||||
/* Leave room for compression buffer to expand in worst case scenario
|
||||
* where data is totally uncompressible */
|
||||
frame_add_to_extra_buffer(frame, COMP_EXTRA_BUFFER(EXPANDED_SIZE(frame)));
|
||||
}
|
||||
|
||||
void
|
||||
comp_print_stats (const struct compress_context *compctx, struct status_output *so)
|
||||
comp_print_stats(const struct compress_context *compctx, struct status_output *so)
|
||||
{
|
||||
if (compctx)
|
||||
if (compctx)
|
||||
{
|
||||
status_printf (so, "pre-compress bytes," counter_format, compctx->pre_compress);
|
||||
status_printf (so, "post-compress bytes," counter_format, compctx->post_compress);
|
||||
status_printf (so, "pre-decompress bytes," counter_format, compctx->pre_decompress);
|
||||
status_printf (so, "post-decompress bytes," counter_format, compctx->post_decompress);
|
||||
status_printf(so, "pre-compress bytes," counter_format, compctx->pre_compress);
|
||||
status_printf(so, "post-compress bytes," counter_format, compctx->post_compress);
|
||||
status_printf(so, "pre-decompress bytes," counter_format, compctx->pre_decompress);
|
||||
status_printf(so, "post-decompress bytes," counter_format, compctx->post_decompress);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -142,25 +150,27 @@ comp_print_stats (const struct compress_context *compctx, struct status_output *
|
|||
void
|
||||
comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out)
|
||||
{
|
||||
if (opt)
|
||||
if (opt)
|
||||
{
|
||||
bool lzo_avail = false;
|
||||
if (!(opt->flags & COMP_F_ADVERTISE_STUBS_ONLY))
|
||||
{
|
||||
bool lzo_avail = false;
|
||||
if (!(opt->flags & COMP_F_ADVERTISE_STUBS_ONLY))
|
||||
{
|
||||
#if defined(ENABLE_LZ4)
|
||||
buf_printf (out, "IV_LZ4=1\n");
|
||||
buf_printf (out, "IV_LZ4v2=1\n");
|
||||
buf_printf(out, "IV_LZ4=1\n");
|
||||
buf_printf(out, "IV_LZ4v2=1\n");
|
||||
#endif
|
||||
#if defined(ENABLE_LZO)
|
||||
buf_printf (out, "IV_LZO=1\n");
|
||||
lzo_avail = true;
|
||||
buf_printf(out, "IV_LZO=1\n");
|
||||
lzo_avail = true;
|
||||
#endif
|
||||
}
|
||||
if (!lzo_avail)
|
||||
buf_printf (out, "IV_LZO_STUB=1\n");
|
||||
buf_printf (out, "IV_COMP_STUB=1\n");
|
||||
buf_printf (out, "IV_COMP_STUBv2=1\n");
|
||||
buf_printf (out, "IV_TCPNL=1\n");
|
||||
}
|
||||
if (!lzo_avail)
|
||||
{
|
||||
buf_printf(out, "IV_LZO_STUB=1\n");
|
||||
}
|
||||
buf_printf(out, "IV_COMP_STUB=1\n");
|
||||
buf_printf(out, "IV_COMP_STUBv2=1\n");
|
||||
buf_printf(out, "IV_TCPNL=1\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,11 +46,11 @@
|
|||
|
||||
/* algorithm v2 */
|
||||
#define COMP_ALGV2_UNCOMPRESSED 10
|
||||
#define COMP_ALGV2_LZ4 11
|
||||
#define COMP_ALGV2_LZ4 11
|
||||
/*
|
||||
#define COMP_ALGV2_LZO 12
|
||||
#define COMP_ALGV2_SNAPPY 13
|
||||
*/
|
||||
#define COMP_ALGV2_LZO 12
|
||||
#define COMP_ALGV2_SNAPPY 13
|
||||
*/
|
||||
|
||||
/* Compression flags */
|
||||
#define COMP_F_ADAPTIVE (1<<0) /* COMP_ALG_LZO only */
|
||||
|
|
@ -76,11 +76,11 @@
|
|||
#define NO_COMPRESS_BYTE_SWAP 0xFB /* to maintain payload alignment, replace this byte with last byte of packet */
|
||||
|
||||
/* V2 on wire code */
|
||||
#define COMP_ALGV2_INDICATOR_BYTE 0x50
|
||||
#define COMP_ALGV2_UNCOMPRESSED_BYTE 0
|
||||
#define COMP_ALGV2_LZ4_BYTE 1
|
||||
#define COMP_ALGV2_LZO_BYTE 2
|
||||
#define COMP_ALGV2_SNAPPY_BYTE 3
|
||||
#define COMP_ALGV2_INDICATOR_BYTE 0x50
|
||||
#define COMP_ALGV2_UNCOMPRESSED_BYTE 0
|
||||
#define COMP_ALGV2_LZ4_BYTE 1
|
||||
#define COMP_ALGV2_LZO_BYTE 2
|
||||
#define COMP_ALGV2_SNAPPY_BYTE 3
|
||||
|
||||
/*
|
||||
* Compress worst case size expansion (for any algorithm)
|
||||
|
|
@ -104,16 +104,16 @@ struct compress_context;
|
|||
*/
|
||||
struct compress_alg
|
||||
{
|
||||
const char *name;
|
||||
void (*compress_init)(struct compress_context *compctx);
|
||||
void (*compress_uninit)(struct compress_context *compctx);
|
||||
void (*compress)(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame);
|
||||
const char *name;
|
||||
void (*compress_init)(struct compress_context *compctx);
|
||||
void (*compress_uninit)(struct compress_context *compctx);
|
||||
void (*compress)(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame);
|
||||
|
||||
void (*decompress)(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame);
|
||||
void (*decompress)(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame);
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -133,8 +133,8 @@ struct compress_alg
|
|||
*/
|
||||
struct compress_options
|
||||
{
|
||||
int alg;
|
||||
unsigned int flags;
|
||||
int alg;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -143,10 +143,10 @@ struct compress_options
|
|||
union compress_workspace_union
|
||||
{
|
||||
#ifdef ENABLE_LZO
|
||||
struct lzo_compress_workspace lzo;
|
||||
struct lzo_compress_workspace lzo;
|
||||
#endif
|
||||
#ifdef ENABLE_LZ4
|
||||
struct lz4_workspace lz4;
|
||||
struct lz4_workspace lz4;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -155,15 +155,15 @@ union compress_workspace_union
|
|||
*/
|
||||
struct compress_context
|
||||
{
|
||||
unsigned int flags;
|
||||
struct compress_alg alg;
|
||||
union compress_workspace_union wu;
|
||||
unsigned int flags;
|
||||
struct compress_alg alg;
|
||||
union compress_workspace_union wu;
|
||||
|
||||
/* statistics */
|
||||
counter_type pre_decompress;
|
||||
counter_type post_decompress;
|
||||
counter_type pre_compress;
|
||||
counter_type post_compress;
|
||||
/* statistics */
|
||||
counter_type pre_decompress;
|
||||
counter_type post_decompress;
|
||||
counter_type pre_compress;
|
||||
counter_type post_compress;
|
||||
};
|
||||
|
||||
extern const struct compress_alg comp_stub_alg;
|
||||
|
|
@ -174,25 +174,26 @@ struct compress_context *comp_init(const struct compress_options *opt);
|
|||
void comp_uninit(struct compress_context *compctx);
|
||||
|
||||
void comp_add_to_extra_frame(struct frame *frame);
|
||||
|
||||
void comp_add_to_extra_buffer(struct frame *frame);
|
||||
|
||||
void comp_print_stats (const struct compress_context *compctx, struct status_output *so);
|
||||
void comp_print_stats(const struct compress_context *compctx, struct status_output *so);
|
||||
|
||||
void comp_generate_peer_info_string(const struct compress_options *opt, struct buffer *out);
|
||||
|
||||
void compv2_escape_data_ifneeded (struct buffer *buf);
|
||||
void compv2_escape_data_ifneeded(struct buffer *buf);
|
||||
|
||||
static inline bool
|
||||
comp_enabled(const struct compress_options *info)
|
||||
{
|
||||
return info->alg != COMP_ALG_UNDEF;
|
||||
return info->alg != COMP_ALG_UNDEF;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
comp_unswapped_prefix(const struct compress_options *info)
|
||||
{
|
||||
return !(info->flags & COMP_F_SWAP);
|
||||
return !(info->flags & COMP_F_SWAP);
|
||||
}
|
||||
|
||||
#endif /* USE_COMP */
|
||||
#endif
|
||||
#endif /* ifndef OPENVPN_COMP_H */
|
||||
|
|
|
|||
|
|
@ -39,131 +39,146 @@
|
|||
#include "memdbg.h"
|
||||
|
||||
static void
|
||||
stub_compress_init (struct compress_context *compctx)
|
||||
stub_compress_init(struct compress_context *compctx)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
stub_compress_uninit (struct compress_context *compctx)
|
||||
stub_compress_uninit(struct compress_context *compctx)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
stub_compress (struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
{
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
if (compctx->flags & COMP_F_SWAP)
|
||||
{
|
||||
uint8_t *head = BPTR (buf);
|
||||
uint8_t *tail = BEND (buf);
|
||||
ASSERT (buf_safe (buf, 1));
|
||||
++buf->len;
|
||||
|
||||
/* move head byte of payload to tail */
|
||||
*tail = *head;
|
||||
*head = NO_COMPRESS_BYTE_SWAP;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *header = buf_prepend (buf, 1);
|
||||
*header = NO_COMPRESS_BYTE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stub_decompress (struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
{
|
||||
uint8_t c;
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
if (compctx->flags & COMP_F_SWAP)
|
||||
{
|
||||
uint8_t *head = BPTR (buf);
|
||||
c = *head;
|
||||
--buf->len;
|
||||
*head = *BEND (buf);
|
||||
if (c != NO_COMPRESS_BYTE_SWAP)
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "Bad compression stub (swap) decompression header byte: %d", c);
|
||||
buf->len = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = *BPTR (buf);
|
||||
ASSERT (buf_advance (buf, 1));
|
||||
if (c != NO_COMPRESS_BYTE)
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "Bad compression stub decompression header byte: %d", c);
|
||||
buf->len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
stubv2_compress (struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
stub_compress(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (compctx->flags & COMP_F_SWAP)
|
||||
{
|
||||
uint8_t *head = BPTR(buf);
|
||||
uint8_t *tail = BEND(buf);
|
||||
ASSERT(buf_safe(buf, 1));
|
||||
++buf->len;
|
||||
|
||||
compv2_escape_data_ifneeded (buf);
|
||||
/* move head byte of payload to tail */
|
||||
*tail = *head;
|
||||
*head = NO_COMPRESS_BYTE_SWAP;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *header = buf_prepend(buf, 1);
|
||||
*header = NO_COMPRESS_BYTE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
stubv2_decompress (struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
stub_decompress(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
uint8_t c;
|
||||
if (buf->len <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (compctx->flags & COMP_F_SWAP)
|
||||
{
|
||||
uint8_t *head = BPTR(buf);
|
||||
c = *head;
|
||||
--buf->len;
|
||||
*head = *BEND(buf);
|
||||
if (c != NO_COMPRESS_BYTE_SWAP)
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "Bad compression stub (swap) decompression header byte: %d", c);
|
||||
buf->len = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
c = *BPTR(buf);
|
||||
ASSERT(buf_advance(buf, 1));
|
||||
if (c != NO_COMPRESS_BYTE)
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "Bad compression stub decompression header byte: %d", c);
|
||||
buf->len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *head = BPTR (buf);
|
||||
|
||||
/* no compression or packet to short*/
|
||||
if (head[0] != COMP_ALGV2_INDICATOR_BYTE)
|
||||
return;
|
||||
static void
|
||||
stubv2_compress(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
if (buf->len <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* compression header (0x50) is present */
|
||||
buf_advance(buf, 1);
|
||||
compv2_escape_data_ifneeded(buf);
|
||||
}
|
||||
|
||||
/* Packet buffer too short (only 1 byte) */
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
static void
|
||||
stubv2_decompress(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
if (buf->len <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
head = BPTR (buf);
|
||||
buf_advance(buf, 1);
|
||||
uint8_t *head = BPTR(buf);
|
||||
|
||||
if (head[0] != COMP_ALGV2_UNCOMPRESSED_BYTE) {
|
||||
dmsg (D_COMP_ERRORS, "Bad compression stubv2 decompression header byte: %d", *head);
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
/* no compression or packet to short*/
|
||||
if (head[0] != COMP_ALGV2_INDICATOR_BYTE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* compression header (0x50) is present */
|
||||
buf_advance(buf, 1);
|
||||
|
||||
/* Packet buffer too short (only 1 byte) */
|
||||
if (buf->len <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
head = BPTR(buf);
|
||||
buf_advance(buf, 1);
|
||||
|
||||
if (head[0] != COMP_ALGV2_UNCOMPRESSED_BYTE)
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "Bad compression stubv2 decompression header byte: %d", *head);
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const struct compress_alg compv2_stub_alg = {
|
||||
"stubv2",
|
||||
stub_compress_init,
|
||||
stub_compress_uninit,
|
||||
stubv2_compress,
|
||||
stubv2_decompress
|
||||
"stubv2",
|
||||
stub_compress_init,
|
||||
stub_compress_uninit,
|
||||
stubv2_compress,
|
||||
stubv2_decompress
|
||||
};
|
||||
|
||||
const struct compress_alg comp_stub_alg = {
|
||||
"stub",
|
||||
stub_compress_init,
|
||||
stub_compress_uninit,
|
||||
stub_compress,
|
||||
stub_decompress
|
||||
"stub",
|
||||
stub_compress_init,
|
||||
stub_compress_uninit,
|
||||
stub_compress,
|
||||
stub_decompress
|
||||
};
|
||||
|
||||
#else
|
||||
static void dummy(void) {}
|
||||
#else /* if defined(USE_COMP) */
|
||||
static void
|
||||
dummy(void) {
|
||||
}
|
||||
#endif /* USE_STUB */
|
||||
|
|
|
|||
|
|
@ -44,19 +44,21 @@
|
|||
struct _query_user query_user[QUERY_USER_NUMSLOTS]; /* GLOBAL */
|
||||
|
||||
|
||||
void query_user_clear()
|
||||
void
|
||||
query_user_clear()
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < QUERY_USER_NUMSLOTS; i++ ) {
|
||||
CLEAR(query_user[i]);
|
||||
for (i = 0; i < QUERY_USER_NUMSLOTS; i++) {
|
||||
CLEAR(query_user[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void query_user_add(char *prompt, size_t prompt_len,
|
||||
char *resp, size_t resp_len,
|
||||
bool echo)
|
||||
void
|
||||
query_user_add(char *prompt, size_t prompt_len,
|
||||
char *resp, size_t resp_len,
|
||||
bool echo)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -67,9 +69,10 @@ void query_user_add(char *prompt, size_t prompt_len,
|
|||
|
||||
/* Seek to the last unused slot */
|
||||
for (i = 0; i < QUERY_USER_NUMSLOTS; i++) {
|
||||
if( query_user[i].prompt == NULL ) {
|
||||
break;
|
||||
}
|
||||
if (query_user[i].prompt == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT( i < QUERY_USER_NUMSLOTS ); /* Unlikely, but we want to panic if it happens */
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ extern struct _query_user query_user[]; /**< Global variable, declared in conso
|
|||
* Wipes all data put into all of the query_user structs
|
||||
*
|
||||
*/
|
||||
void query_user_clear ();
|
||||
void query_user_clear();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -60,9 +60,9 @@ void query_user_clear ();
|
|||
* @param echo Should the user input be echoed to the user? If False, input will be masked
|
||||
*
|
||||
*/
|
||||
void query_user_add (char *prompt, size_t prompt_len,
|
||||
char *resp, size_t resp_len,
|
||||
bool echo);
|
||||
void query_user_add(char *prompt, size_t prompt_len,
|
||||
char *resp, size_t resp_len,
|
||||
bool echo);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -73,7 +73,7 @@ void query_user_add (char *prompt, size_t prompt_len,
|
|||
*
|
||||
* @return True if executing all the defined steps completed successfully
|
||||
*/
|
||||
bool query_user_exec_builtin ();
|
||||
bool query_user_exec_builtin();
|
||||
|
||||
|
||||
#if defined(ENABLE_SYSTEMD)
|
||||
|
|
@ -84,7 +84,7 @@ bool query_user_exec_builtin ();
|
|||
*
|
||||
* @return True if executing all the defined steps completed successfully
|
||||
*/
|
||||
bool query_user_exec ();
|
||||
bool query_user_exec();
|
||||
|
||||
#else /* ENABLE_SYSTEMD not defined*/
|
||||
/**
|
||||
|
|
@ -92,7 +92,8 @@ bool query_user_exec ();
|
|||
* been enabled
|
||||
*
|
||||
*/
|
||||
static bool query_user_exec ()
|
||||
static bool
|
||||
query_user_exec()
|
||||
{
|
||||
return query_user_exec_builtin();
|
||||
}
|
||||
|
|
@ -106,13 +107,14 @@ static bool query_user_exec ()
|
|||
* to be called at start-up initialization of OpenVPN.
|
||||
*
|
||||
*/
|
||||
static inline bool query_user_SINGLE (char *prompt, size_t prompt_len,
|
||||
char *resp, size_t resp_len,
|
||||
bool echo)
|
||||
static inline bool
|
||||
query_user_SINGLE(char *prompt, size_t prompt_len,
|
||||
char *resp, size_t resp_len,
|
||||
bool echo)
|
||||
{
|
||||
query_user_clear();
|
||||
query_user_add(prompt, prompt_len, resp, resp_len, echo);
|
||||
return query_user_exec();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* ifndef CONSOLE_H */
|
||||
|
|
|
|||
|
|
@ -56,64 +56,81 @@
|
|||
* @return Return false on input error, or if service
|
||||
* exit event is signaled.
|
||||
*/
|
||||
static bool get_console_input_win32 (const char *prompt, const bool echo, char *input, const int capacity)
|
||||
static bool
|
||||
get_console_input_win32(const char *prompt, const bool echo, char *input, const int capacity)
|
||||
{
|
||||
HANDLE in = INVALID_HANDLE_VALUE;
|
||||
HANDLE err = INVALID_HANDLE_VALUE;
|
||||
DWORD len = 0;
|
||||
|
||||
ASSERT (prompt);
|
||||
ASSERT (input);
|
||||
ASSERT (capacity > 0);
|
||||
ASSERT(prompt);
|
||||
ASSERT(input);
|
||||
ASSERT(capacity > 0);
|
||||
|
||||
input[0] = '\0';
|
||||
|
||||
in = GetStdHandle (STD_INPUT_HANDLE);
|
||||
err = get_orig_stderr ();
|
||||
in = GetStdHandle(STD_INPUT_HANDLE);
|
||||
err = get_orig_stderr();
|
||||
|
||||
if (in != INVALID_HANDLE_VALUE
|
||||
&& err != INVALID_HANDLE_VALUE
|
||||
&& !win32_service_interrupt (&win32_signal)
|
||||
&& WriteFile (err, prompt, strlen (prompt), &len, NULL))
|
||||
&& !win32_service_interrupt(&win32_signal)
|
||||
&& WriteFile(err, prompt, strlen(prompt), &len, NULL))
|
||||
{
|
||||
bool is_console = (GetFileType (in) == FILE_TYPE_CHAR);
|
||||
bool is_console = (GetFileType(in) == FILE_TYPE_CHAR);
|
||||
DWORD flags_save = 0;
|
||||
int status = 0;
|
||||
WCHAR *winput;
|
||||
|
||||
if (is_console)
|
||||
{
|
||||
if (GetConsoleMode (in, &flags_save))
|
||||
{
|
||||
{
|
||||
if (GetConsoleMode(in, &flags_save))
|
||||
{
|
||||
DWORD flags = ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
|
||||
if (echo)
|
||||
{
|
||||
flags |= ENABLE_ECHO_INPUT;
|
||||
SetConsoleMode (in, flags);
|
||||
} else
|
||||
}
|
||||
SetConsoleMode(in, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
is_console = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_console)
|
||||
{
|
||||
winput = malloc (capacity * sizeof (WCHAR));
|
||||
winput = malloc(capacity * sizeof(WCHAR));
|
||||
if (winput == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
status = ReadConsoleW (in, winput, capacity, &len, NULL);
|
||||
WideCharToMultiByte (CP_UTF8, 0, winput, len, input, capacity, NULL, NULL);
|
||||
free (winput);
|
||||
} else
|
||||
status = ReadFile (in, input, capacity, &len, NULL);
|
||||
status = ReadConsoleW(in, winput, capacity, &len, NULL);
|
||||
WideCharToMultiByte(CP_UTF8, 0, winput, len, input, capacity, NULL, NULL);
|
||||
free(winput);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ReadFile(in, input, capacity, &len, NULL);
|
||||
}
|
||||
|
||||
string_null_terminate (input, (int)len, capacity);
|
||||
chomp (input);
|
||||
string_null_terminate(input, (int)len, capacity);
|
||||
chomp(input);
|
||||
|
||||
if (!echo)
|
||||
WriteFile (err, "\r\n", 2, &len, NULL);
|
||||
{
|
||||
WriteFile(err, "\r\n", 2, &len, NULL);
|
||||
}
|
||||
if (is_console)
|
||||
SetConsoleMode (in, flags_save);
|
||||
if (status && !win32_service_interrupt (&win32_signal))
|
||||
{
|
||||
SetConsoleMode(in, flags_save);
|
||||
}
|
||||
if (status && !win32_service_interrupt(&win32_signal))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -134,12 +151,15 @@ static bool get_console_input_win32 (const char *prompt, const bool echo, char *
|
|||
* or stdin/stderr, depending on the write flag
|
||||
*
|
||||
*/
|
||||
static FILE * open_tty (const bool write)
|
||||
static FILE *
|
||||
open_tty(const bool write)
|
||||
{
|
||||
FILE *ret;
|
||||
ret = fopen ("/dev/tty", write ? "w" : "r");
|
||||
ret = fopen("/dev/tty", write ? "w" : "r");
|
||||
if (!ret)
|
||||
{
|
||||
ret = write ? stderr : stdin;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -149,10 +169,13 @@ static FILE * open_tty (const bool write)
|
|||
* @params fp FILE pointer to close
|
||||
*
|
||||
*/
|
||||
static void close_tty (FILE *fp)
|
||||
static void
|
||||
close_tty(FILE *fp)
|
||||
{
|
||||
if (fp != stderr && fp != stdin)
|
||||
fclose (fp);
|
||||
{
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* HAVE_GETPASS */
|
||||
|
|
@ -168,26 +191,27 @@ static void close_tty (FILE *fp)
|
|||
*
|
||||
* @returns Returns True if user input was gathered
|
||||
*/
|
||||
static bool get_console_input (const char *prompt, const bool echo, char *input, const int capacity)
|
||||
static bool
|
||||
get_console_input(const char *prompt, const bool echo, char *input, const int capacity)
|
||||
{
|
||||
bool ret = false;
|
||||
ASSERT (prompt);
|
||||
ASSERT (input);
|
||||
ASSERT (capacity > 0);
|
||||
ASSERT(prompt);
|
||||
ASSERT(input);
|
||||
ASSERT(capacity > 0);
|
||||
input[0] = '\0';
|
||||
|
||||
#if defined(_WIN32)
|
||||
return get_console_input_win32 (prompt, echo, input, capacity);
|
||||
return get_console_input_win32(prompt, echo, input, capacity);
|
||||
#elif defined(HAVE_GETPASS)
|
||||
|
||||
/* did we --daemon'ize before asking for passwords?
|
||||
* (in which case neither stdin or stderr are connected to a tty and
|
||||
* /dev/tty can not be open()ed anymore)
|
||||
*/
|
||||
if ( !isatty(0) && !isatty(2) )
|
||||
if (!isatty(0) && !isatty(2) )
|
||||
{
|
||||
int fd = open( "/dev/tty", O_RDWR );
|
||||
if ( fd < 0 )
|
||||
if (fd < 0)
|
||||
{
|
||||
msg(M_FATAL, "neither stdin nor stderr are a tty device and you have neither a "
|
||||
"controlling tty nor systemd - can't ask for '%s'. If you used --daemon, "
|
||||
|
|
@ -201,30 +225,32 @@ static bool get_console_input (const char *prompt, const bool echo, char *input,
|
|||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = open_tty (true);
|
||||
fprintf (fp, "%s", prompt);
|
||||
fflush (fp);
|
||||
close_tty (fp);
|
||||
fp = open_tty(true);
|
||||
fprintf(fp, "%s", prompt);
|
||||
fflush(fp);
|
||||
close_tty(fp);
|
||||
|
||||
fp = open_tty (false);
|
||||
if (fgets (input, capacity, fp) != NULL)
|
||||
fp = open_tty(false);
|
||||
if (fgets(input, capacity, fp) != NULL)
|
||||
{
|
||||
chomp (input);
|
||||
chomp(input);
|
||||
ret = true;
|
||||
}
|
||||
close_tty (fp);
|
||||
} else {
|
||||
char *gp = getpass (prompt);
|
||||
close_tty(fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *gp = getpass(prompt);
|
||||
if (gp)
|
||||
{
|
||||
strncpynt (input, gp, capacity);
|
||||
secure_memzero (gp, strlen (gp));
|
||||
strncpynt(input, gp, capacity);
|
||||
secure_memzero(gp, strlen(gp));
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
msg (M_FATAL, "Sorry, but I can't get console input on this OS (%s)", prompt);
|
||||
#endif
|
||||
#else /* if defined(_WIN32) */
|
||||
msg(M_FATAL, "Sorry, but I can't get console input on this OS (%s)", prompt);
|
||||
#endif /* if defined(_WIN32) */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +267,8 @@ static bool get_console_input (const char *prompt, const bool echo, char *input,
|
|||
* query_user_exec() will call this function instead.
|
||||
*
|
||||
*/
|
||||
bool query_user_exec_builtin()
|
||||
bool
|
||||
query_user_exec_builtin()
|
||||
{
|
||||
bool ret = true; /* Presume everything goes okay */
|
||||
int i;
|
||||
|
|
@ -249,12 +276,12 @@ bool query_user_exec_builtin()
|
|||
/* Loop through configured query_user slots */
|
||||
for (i = 0; i < QUERY_USER_NUMSLOTS && query_user[i].response != NULL; i++)
|
||||
{
|
||||
if (!get_console_input(query_user[i].prompt, query_user[i].echo,
|
||||
query_user[i].response, query_user[i].response_len) )
|
||||
{
|
||||
/* Force the final result state to failed on failure */
|
||||
ret = false;
|
||||
}
|
||||
if (!get_console_input(query_user[i].prompt, query_user[i].echo,
|
||||
query_user[i].response, query_user[i].response_len) )
|
||||
{
|
||||
/* Force the final result state to failed on failure */
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
*/
|
||||
|
||||
static bool
|
||||
check_systemd_running ()
|
||||
check_systemd_running()
|
||||
{
|
||||
struct stat c;
|
||||
|
||||
|
|
@ -51,40 +51,41 @@ check_systemd_running ()
|
|||
* being available */
|
||||
|
||||
return (sd_booted() > 0)
|
||||
&& (stat(SYSTEMD_ASK_PASSWORD_PATH, &c) == 0);
|
||||
&& (stat(SYSTEMD_ASK_PASSWORD_PATH, &c) == 0);
|
||||
|
||||
}
|
||||
|
||||
static bool
|
||||
get_console_input_systemd (const char *prompt, const bool echo, char *input, const int capacity)
|
||||
get_console_input_systemd(const char *prompt, const bool echo, char *input, const int capacity)
|
||||
{
|
||||
int std_out;
|
||||
bool ret = false;
|
||||
struct argv argv = argv_new ();
|
||||
struct argv argv = argv_new();
|
||||
|
||||
argv_printf (&argv, SYSTEMD_ASK_PASSWORD_PATH);
|
||||
argv_printf(&argv, SYSTEMD_ASK_PASSWORD_PATH);
|
||||
#ifdef SYSTEMD_NEWER_THAN_216
|
||||
/* the --echo support arrived in upstream systemd 217 */
|
||||
if( echo )
|
||||
if (echo)
|
||||
{
|
||||
argv_printf_cat(&argv, "--echo");
|
||||
argv_printf_cat(&argv, "--echo");
|
||||
}
|
||||
#endif
|
||||
argv_printf_cat (&argv, "--icon network-vpn");
|
||||
argv_printf_cat (&argv, "%s", prompt);
|
||||
argv_printf_cat(&argv, "--icon network-vpn");
|
||||
argv_printf_cat(&argv, "%s", prompt);
|
||||
|
||||
if ((std_out = openvpn_popen (&argv, NULL)) < 0) {
|
||||
return false;
|
||||
}
|
||||
memset (input, 0, capacity);
|
||||
if (read (std_out, input, capacity-1) != 0)
|
||||
if ((std_out = openvpn_popen(&argv, NULL)) < 0)
|
||||
{
|
||||
chomp (input);
|
||||
ret = true;
|
||||
return false;
|
||||
}
|
||||
close (std_out);
|
||||
memset(input, 0, capacity);
|
||||
if (read(std_out, input, capacity-1) != 0)
|
||||
{
|
||||
chomp(input);
|
||||
ret = true;
|
||||
}
|
||||
close(std_out);
|
||||
|
||||
argv_reset (&argv);
|
||||
argv_reset(&argv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -94,7 +95,8 @@ get_console_input_systemd (const char *prompt, const bool echo, char *input, con
|
|||
* it will fall back to use query_user_exec_builtin() instead.
|
||||
*
|
||||
*/
|
||||
bool query_user_exec()
|
||||
bool
|
||||
query_user_exec()
|
||||
{
|
||||
bool ret = true; /* Presume everything goes okay */
|
||||
int i;
|
||||
|
|
@ -108,12 +110,12 @@ bool query_user_exec()
|
|||
/* Loop through the complete query setup and when needed, collect the information */
|
||||
for (i = 0; i < QUERY_USER_NUMSLOTS && query_user[i].response != NULL; i++)
|
||||
{
|
||||
if (!get_console_input_systemd(query_user[i].prompt, query_user[i].echo,
|
||||
query_user[i].response, query_user[i].response_len) )
|
||||
{
|
||||
/* Force the final result state to failed on failure */
|
||||
ret = false;
|
||||
}
|
||||
if (!get_console_input_systemd(query_user[i].prompt, query_user[i].echo,
|
||||
query_user[i].response, query_user[i].response_len) )
|
||||
{
|
||||
/* Force the final result state to failed on failure */
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
|||
2410
src/openvpn/crypto.c
2410
src/openvpn/crypto.c
File diff suppressed because it is too large
Load diff
|
|
@ -134,7 +134,7 @@
|
|||
|
||||
/** Wrapper struct to pass around MD5 digests */
|
||||
struct md5_digest {
|
||||
uint8_t digest[MD5_DIGEST_LENGTH];
|
||||
uint8_t digest[MD5_DIGEST_LENGTH];
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -142,10 +142,10 @@ struct md5_digest {
|
|||
*/
|
||||
struct key_type
|
||||
{
|
||||
uint8_t cipher_length; /**< Cipher length, in bytes */
|
||||
uint8_t hmac_length; /**< HMAC length, in bytes */
|
||||
const cipher_kt_t *cipher; /**< Cipher static parameters */
|
||||
const md_kt_t *digest; /**< Message digest static parameters */
|
||||
uint8_t cipher_length; /**< Cipher length, in bytes */
|
||||
uint8_t hmac_length; /**< HMAC length, in bytes */
|
||||
const cipher_kt_t *cipher; /**< Cipher static parameters */
|
||||
const md_kt_t *digest; /**< Message digest static parameters */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -154,10 +154,10 @@ struct key_type
|
|||
*/
|
||||
struct key
|
||||
{
|
||||
uint8_t cipher[MAX_CIPHER_KEY_LENGTH];
|
||||
/**< %Key material for cipher operations. */
|
||||
uint8_t hmac[MAX_HMAC_KEY_LENGTH];
|
||||
/**< %Key material for HMAC operations. */
|
||||
uint8_t cipher[MAX_CIPHER_KEY_LENGTH];
|
||||
/**< %Key material for cipher operations. */
|
||||
uint8_t hmac[MAX_HMAC_KEY_LENGTH];
|
||||
/**< %Key material for HMAC operations. */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -167,11 +167,11 @@ struct key
|
|||
*/
|
||||
struct key_ctx
|
||||
{
|
||||
cipher_ctx_t *cipher; /**< Generic cipher %context. */
|
||||
hmac_ctx_t *hmac; /**< Generic HMAC %context. */
|
||||
uint8_t implicit_iv[OPENVPN_MAX_IV_LENGTH];
|
||||
/**< The implicit part of the IV */
|
||||
size_t implicit_iv_len; /**< The length of implicit_iv */
|
||||
cipher_ctx_t *cipher; /**< Generic cipher %context. */
|
||||
hmac_ctx_t *hmac; /**< Generic HMAC %context. */
|
||||
uint8_t implicit_iv[OPENVPN_MAX_IV_LENGTH];
|
||||
/**< The implicit part of the IV */
|
||||
size_t implicit_iv_len; /**< The length of implicit_iv */
|
||||
};
|
||||
|
||||
#define KEY_DIRECTION_BIDIRECTIONAL 0 /* same keys for both directions */
|
||||
|
|
@ -184,9 +184,9 @@ struct key_ctx
|
|||
*/
|
||||
struct key2
|
||||
{
|
||||
int n; /**< The number of \c key objects stored
|
||||
int n; /**< The number of \c key objects stored
|
||||
* in the \c key2.keys array. */
|
||||
struct key keys[2]; /**< Two unidirectional sets of %key
|
||||
struct key keys[2]; /**< Two unidirectional sets of %key
|
||||
* material. */
|
||||
};
|
||||
|
||||
|
|
@ -201,11 +201,11 @@ struct key2
|
|||
*/
|
||||
struct key_direction_state
|
||||
{
|
||||
int out_key; /**< Index into the \c key2.keys array for
|
||||
int out_key; /**< Index into the \c key2.keys array for
|
||||
* the sending direction. */
|
||||
int in_key; /**< Index into the \c key2.keys array for
|
||||
int in_key; /**< Index into the \c key2.keys array for
|
||||
* the receiving direction. */
|
||||
int need_keys; /**< The number of key objects necessary
|
||||
int need_keys; /**< The number of key objects necessary
|
||||
* to support both sending and
|
||||
* receiving.
|
||||
*
|
||||
|
|
@ -222,11 +222,11 @@ struct key_direction_state
|
|||
*/
|
||||
struct key_ctx_bi
|
||||
{
|
||||
struct key_ctx encrypt; /**< Cipher and/or HMAC contexts for sending
|
||||
* direction. */
|
||||
struct key_ctx decrypt; /**< cipher and/or HMAC contexts for
|
||||
struct key_ctx encrypt; /**< Cipher and/or HMAC contexts for sending
|
||||
* direction. */
|
||||
struct key_ctx decrypt; /**< cipher and/or HMAC contexts for
|
||||
* receiving direction. */
|
||||
bool initialized;
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -235,69 +235,69 @@ struct key_ctx_bi
|
|||
*/
|
||||
struct crypto_options
|
||||
{
|
||||
struct key_ctx_bi key_ctx_bi;
|
||||
/**< OpenSSL cipher and HMAC contexts for
|
||||
* both sending and receiving
|
||||
* directions. */
|
||||
struct packet_id packet_id; /**< Current packet ID state for both
|
||||
struct key_ctx_bi key_ctx_bi;
|
||||
/**< OpenSSL cipher and HMAC contexts for
|
||||
* both sending and receiving
|
||||
* directions. */
|
||||
struct packet_id packet_id; /**< Current packet ID state for both
|
||||
* sending and receiving directions. */
|
||||
struct packet_id_persist *pid_persist;
|
||||
/**< Persistent packet ID state for
|
||||
* keeping state between successive
|
||||
* OpenVPN process startups. */
|
||||
struct packet_id_persist *pid_persist;
|
||||
/**< Persistent packet ID state for
|
||||
* keeping state between successive
|
||||
* OpenVPN process startups. */
|
||||
|
||||
# define CO_PACKET_ID_LONG_FORM (1<<0)
|
||||
/**< Bit-flag indicating whether to use
|
||||
* OpenVPN's long packet ID format. */
|
||||
# define CO_USE_IV (1<<1)
|
||||
/**< Bit-flag indicating whether to
|
||||
* generate a pseudo-random IV for each
|
||||
* packet being encrypted. */
|
||||
# define CO_IGNORE_PACKET_ID (1<<2)
|
||||
/**< Bit-flag indicating whether to ignore
|
||||
* the packet ID of a received packet.
|
||||
* This flag is used during processing
|
||||
* of the first packet received from a
|
||||
* client. */
|
||||
# define CO_MUTE_REPLAY_WARNINGS (1<<3)
|
||||
/**< Bit-flag indicating not to display
|
||||
* replay warnings. */
|
||||
unsigned int flags; /**< Bit-flags determining behavior of
|
||||
#define CO_PACKET_ID_LONG_FORM (1<<0)
|
||||
/**< Bit-flag indicating whether to use
|
||||
* OpenVPN's long packet ID format. */
|
||||
#define CO_USE_IV (1<<1)
|
||||
/**< Bit-flag indicating whether to
|
||||
* generate a pseudo-random IV for each
|
||||
* packet being encrypted. */
|
||||
#define CO_IGNORE_PACKET_ID (1<<2)
|
||||
/**< Bit-flag indicating whether to ignore
|
||||
* the packet ID of a received packet.
|
||||
* This flag is used during processing
|
||||
* of the first packet received from a
|
||||
* client. */
|
||||
#define CO_MUTE_REPLAY_WARNINGS (1<<3)
|
||||
/**< Bit-flag indicating not to display
|
||||
* replay warnings. */
|
||||
unsigned int flags; /**< Bit-flags determining behavior of
|
||||
* security operation functions. */
|
||||
};
|
||||
|
||||
#define CRYPT_ERROR(format) \
|
||||
do { msg (D_CRYPT_ERRORS, "%s: " format, error_prefix); goto error_exit; } while (false)
|
||||
do { msg(D_CRYPT_ERRORS, "%s: " format, error_prefix); goto error_exit; } while (false)
|
||||
|
||||
/**
|
||||
* Minimal IV length for AEAD mode ciphers (in bytes):
|
||||
* 4-byte packet id + 8 bytes implicit IV.
|
||||
*/
|
||||
#define OPENVPN_AEAD_MIN_IV_LEN (sizeof (packet_id_type) + 8)
|
||||
#define OPENVPN_AEAD_MIN_IV_LEN (sizeof(packet_id_type) + 8)
|
||||
|
||||
#define RKF_MUST_SUCCEED (1<<0)
|
||||
#define RKF_INLINE (1<<1)
|
||||
void read_key_file (struct key2 *key2, const char *file, const unsigned int flags);
|
||||
void read_key_file(struct key2 *key2, const char *file, const unsigned int flags);
|
||||
|
||||
int write_key_file (const int nkeys, const char *filename);
|
||||
int write_key_file(const int nkeys, const char *filename);
|
||||
|
||||
int read_passphrase_hash (const char *passphrase_file,
|
||||
const md_kt_t *digest,
|
||||
uint8_t *output,
|
||||
int len);
|
||||
int read_passphrase_hash(const char *passphrase_file,
|
||||
const md_kt_t *digest,
|
||||
uint8_t *output,
|
||||
int len);
|
||||
|
||||
void generate_key_random (struct key *key, const struct key_type *kt);
|
||||
void generate_key_random(struct key *key, const struct key_type *kt);
|
||||
|
||||
void check_replay_iv_consistency(const struct key_type *kt, bool packet_id, bool use_iv);
|
||||
|
||||
bool check_key (struct key *key, const struct key_type *kt);
|
||||
bool check_key(struct key *key, const struct key_type *kt);
|
||||
|
||||
void fixup_key (struct key *key, const struct key_type *kt);
|
||||
void fixup_key(struct key *key, const struct key_type *kt);
|
||||
|
||||
bool write_key (const struct key *key, const struct key_type *kt,
|
||||
struct buffer *buf);
|
||||
bool write_key(const struct key *key, const struct key_type *kt,
|
||||
struct buffer *buf);
|
||||
|
||||
int read_key (struct key *key, const struct key_type *kt, struct buffer *buf);
|
||||
int read_key(struct key *key, const struct key_type *kt, struct buffer *buf);
|
||||
|
||||
/**
|
||||
* Initialize a key_type structure with.
|
||||
|
|
@ -311,20 +311,20 @@ int read_key (struct key *key, const struct key_type *kt, struct buffer *buf);
|
|||
* more ciphers than static key mode.
|
||||
* @param warn Print warnings when null cipher / auth is used.
|
||||
*/
|
||||
void init_key_type (struct key_type *kt, const char *ciphername,
|
||||
const char *authname, int keysize, bool tls_mode, bool warn);
|
||||
void init_key_type(struct key_type *kt, const char *ciphername,
|
||||
const char *authname, int keysize, bool tls_mode, bool warn);
|
||||
|
||||
/*
|
||||
* Key context functions
|
||||
*/
|
||||
|
||||
void init_key_ctx (struct key_ctx *ctx, struct key *key,
|
||||
const struct key_type *kt, int enc,
|
||||
const char *prefix);
|
||||
void init_key_ctx(struct key_ctx *ctx, struct key *key,
|
||||
const struct key_type *kt, int enc,
|
||||
const char *prefix);
|
||||
|
||||
void free_key_ctx (struct key_ctx *ctx);
|
||||
void free_key_ctx(struct key_ctx *ctx);
|
||||
|
||||
void free_key_ctx_bi (struct key_ctx_bi *ctx);
|
||||
void free_key_ctx_bi(struct key_ctx_bi *ctx);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
@ -357,8 +357,8 @@ void free_key_ctx_bi (struct key_ctx_bi *ctx);
|
|||
* contain the processed packet ready for sending, or be empty if an
|
||||
* error occurred.
|
||||
*/
|
||||
void openvpn_encrypt (struct buffer *buf, struct buffer work,
|
||||
struct crypto_options *opt);
|
||||
void openvpn_encrypt(struct buffer *buf, struct buffer work,
|
||||
struct crypto_options *opt);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -394,33 +394,33 @@ void openvpn_encrypt (struct buffer *buf, struct buffer work,
|
|||
* the plaintext packet ready for further processing, or be empty if
|
||||
* an error occurred.
|
||||
*/
|
||||
bool openvpn_decrypt (struct buffer *buf, struct buffer work,
|
||||
struct crypto_options *opt, const struct frame* frame,
|
||||
const uint8_t *ad_start);
|
||||
bool openvpn_decrypt(struct buffer *buf, struct buffer work,
|
||||
struct crypto_options *opt, const struct frame *frame,
|
||||
const uint8_t *ad_start);
|
||||
|
||||
/** @} name Functions for performing security operations on data channel packets */
|
||||
|
||||
/**
|
||||
* Check packet ID for replay, and perform replay administration.
|
||||
*
|
||||
* @param opt Crypto options for this packet, contains replay state.
|
||||
* @param pin Packet ID read from packet.
|
||||
* @param error_prefix Prefix to use when printing error messages.
|
||||
* @param gc Garbage collector to use.
|
||||
* @param opt Crypto options for this packet, contains replay state.
|
||||
* @param pin Packet ID read from packet.
|
||||
* @param error_prefix Prefix to use when printing error messages.
|
||||
* @param gc Garbage collector to use.
|
||||
*
|
||||
* @return true if packet ID is validated to be not a replay, false otherwise.
|
||||
*/
|
||||
bool crypto_check_replay(struct crypto_options *opt,
|
||||
const struct packet_id_net *pin, const char *error_prefix,
|
||||
struct gc_arena *gc);
|
||||
const struct packet_id_net *pin, const char *error_prefix,
|
||||
struct gc_arena *gc);
|
||||
|
||||
|
||||
/** Calculate crypto overhead and adjust frame to account for that */
|
||||
void crypto_adjust_frame_parameters(struct frame *frame,
|
||||
const struct key_type* kt,
|
||||
bool use_iv,
|
||||
bool packet_id,
|
||||
bool packet_id_long_form);
|
||||
const struct key_type *kt,
|
||||
bool use_iv,
|
||||
bool packet_id,
|
||||
bool packet_id_long_form);
|
||||
|
||||
/** Return the worst-case OpenVPN crypto overhead (in bytes) */
|
||||
size_t crypto_max_overhead(void);
|
||||
|
|
@ -438,10 +438,10 @@ size_t crypto_max_overhead(void);
|
|||
* Pseudo-random number generator initialisation.
|
||||
* (see \c prng_rand_bytes())
|
||||
*
|
||||
* @param md_name Name of the message digest to use
|
||||
* @param nonce_secret_len_param Length of the nonce to use
|
||||
* @param md_name Name of the message digest to use
|
||||
* @param nonce_secret_len_param Length of the nonce to use
|
||||
*/
|
||||
void prng_init (const char *md_name, const int nonce_secret_len_parm);
|
||||
void prng_init(const char *md_name, const int nonce_secret_len_parm);
|
||||
|
||||
/*
|
||||
* Message digest-based pseudo random number generator.
|
||||
|
|
@ -455,37 +455,37 @@ void prng_init (const char *md_name, const int nonce_secret_len_parm);
|
|||
*
|
||||
* Retrieves len bytes of pseudo random data, and places it in output.
|
||||
*
|
||||
* @param output Output buffer
|
||||
* @param len Length of the output buffer
|
||||
* @param output Output buffer
|
||||
* @param len Length of the output buffer
|
||||
*/
|
||||
void prng_bytes (uint8_t *output, int len);
|
||||
void prng_bytes(uint8_t *output, int len);
|
||||
|
||||
void prng_uninit ();
|
||||
void prng_uninit();
|
||||
|
||||
void test_crypto (struct crypto_options *co, struct frame* f);
|
||||
void test_crypto(struct crypto_options *co, struct frame *f);
|
||||
|
||||
|
||||
/* key direction functions */
|
||||
|
||||
void key_direction_state_init (struct key_direction_state *kds, int key_direction);
|
||||
void key_direction_state_init(struct key_direction_state *kds, int key_direction);
|
||||
|
||||
void verify_fix_key2 (struct key2 *key2, const struct key_type *kt, const char *shared_secret_file);
|
||||
void verify_fix_key2(struct key2 *key2, const struct key_type *kt, const char *shared_secret_file);
|
||||
|
||||
void must_have_n_keys (const char *filename, const char *option, const struct key2 *key2, int n);
|
||||
void must_have_n_keys(const char *filename, const char *option, const struct key2 *key2, int n);
|
||||
|
||||
int ascii2keydirection (int msglevel, const char *str);
|
||||
int ascii2keydirection(int msglevel, const char *str);
|
||||
|
||||
const char *keydirection2ascii (int kd, bool remote);
|
||||
const char *keydirection2ascii(int kd, bool remote);
|
||||
|
||||
/* print keys */
|
||||
void key2_print (const struct key2* k,
|
||||
const struct key_type *kt,
|
||||
const char* prefix0,
|
||||
const char* prefix1);
|
||||
void key2_print(const struct key2 *k,
|
||||
const struct key_type *kt,
|
||||
const char *prefix0,
|
||||
const char *prefix1);
|
||||
|
||||
void crypto_read_openvpn_key (const struct key_type *key_type,
|
||||
struct key_ctx_bi *ctx, const char *key_file, const char *key_inline,
|
||||
const int key_direction, const char *key_name, const char *opt_name);
|
||||
void crypto_read_openvpn_key(const struct key_type *key_type,
|
||||
struct key_ctx_bi *ctx, const char *key_file, const char *key_inline,
|
||||
const int key_direction, const char *key_name, const char *opt_name);
|
||||
|
||||
/*
|
||||
* Inline functions
|
||||
|
|
@ -496,23 +496,23 @@ void crypto_read_openvpn_key (const struct key_type *key_type,
|
|||
* Returns 0 when data is equal, non-zero otherwise.
|
||||
*/
|
||||
static inline int
|
||||
memcmp_constant_time (const void *a, const void *b, size_t size) {
|
||||
const uint8_t * a1 = a;
|
||||
const uint8_t * b1 = b;
|
||||
int ret = 0;
|
||||
size_t i;
|
||||
memcmp_constant_time(const void *a, const void *b, size_t size) {
|
||||
const uint8_t *a1 = a;
|
||||
const uint8_t *b1 = b;
|
||||
int ret = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
ret |= *a1++ ^ *b1++;
|
||||
}
|
||||
for (i = 0; i < size; i++) {
|
||||
ret |= *a1++ ^ *b1++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
key_ctx_bi_defined(const struct key_ctx_bi* key)
|
||||
key_ctx_bi_defined(const struct key_ctx_bi *key)
|
||||
{
|
||||
return key->encrypt.cipher || key->encrypt.hmac || key->decrypt.cipher || key->decrypt.hmac;
|
||||
return key->encrypt.cipher || key->encrypt.hmac || key->decrypt.cipher || key->decrypt.hmac;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -45,12 +45,12 @@
|
|||
#define OPENVPN_MAX_CIPHER_BLOCK_SIZE 32
|
||||
|
||||
/* Maximum HMAC digest size (bytes) */
|
||||
#define OPENVPN_MAX_HMAC_SIZE 64
|
||||
#define OPENVPN_MAX_HMAC_SIZE 64
|
||||
|
||||
/** Struct used in cipher name translation table */
|
||||
typedef struct {
|
||||
const char *openvpn_name; /**< Cipher name used by OpenVPN */
|
||||
const char *lib_name; /**< Cipher name used by crypto library */
|
||||
const char *openvpn_name; /**< Cipher name used by OpenVPN */
|
||||
const char *lib_name; /**< Cipher name used by crypto library */
|
||||
} cipher_name_pair;
|
||||
|
||||
/** Cipher name translation table */
|
||||
|
|
@ -61,16 +61,16 @@ extern const size_t cipher_name_translation_table_count;
|
|||
* This routine should have additional OpenSSL crypto library initialisations
|
||||
* used by both crypto and ssl components of OpenVPN.
|
||||
*/
|
||||
void crypto_init_lib (void);
|
||||
void crypto_init_lib(void);
|
||||
|
||||
void crypto_uninit_lib (void);
|
||||
void crypto_uninit_lib(void);
|
||||
|
||||
void crypto_clear_error (void);
|
||||
void crypto_clear_error(void);
|
||||
|
||||
/*
|
||||
* Initialise the given named crypto engine.
|
||||
*/
|
||||
void crypto_init_lib_engine (const char *engine_name);
|
||||
void crypto_init_lib_engine(const char *engine_name);
|
||||
|
||||
#ifdef DMALLOC
|
||||
/*
|
||||
|
|
@ -78,26 +78,27 @@ void crypto_init_lib_engine (const char *engine_name);
|
|||
* OpenSSL to use our private malloc/realloc/free functions so that
|
||||
* we can dispatch them to dmalloc.
|
||||
*/
|
||||
void crypto_init_dmalloc (void);
|
||||
void crypto_init_dmalloc(void);
|
||||
|
||||
#endif /* DMALLOC */
|
||||
|
||||
/**
|
||||
* Translate a data channel cipher name from the OpenVPN config file
|
||||
* 'language' to the crypto library specific name.
|
||||
*/
|
||||
const char * translate_cipher_name_from_openvpn (const char *cipher_name);
|
||||
const char *translate_cipher_name_from_openvpn(const char *cipher_name);
|
||||
|
||||
/**
|
||||
* Translate a data channel cipher name from the crypto library specific name
|
||||
* to the OpenVPN config file 'language'.
|
||||
*/
|
||||
const char * translate_cipher_name_from_openvpn (const char *cipher_name);
|
||||
const char *translate_cipher_name_from_openvpn(const char *cipher_name);
|
||||
|
||||
void show_available_ciphers (void);
|
||||
void show_available_ciphers(void);
|
||||
|
||||
void show_available_digests (void);
|
||||
void show_available_digests(void);
|
||||
|
||||
void show_available_engines (void);
|
||||
void show_available_engines(void);
|
||||
|
||||
/*
|
||||
*
|
||||
|
|
@ -112,12 +113,12 @@ void show_available_engines (void);
|
|||
* Wrapper for secure random number generator. Retrieves len bytes of random
|
||||
* data, and places it in output.
|
||||
*
|
||||
* @param output Output buffer
|
||||
* @param len Length of the output buffer, in bytes
|
||||
* @param output Output buffer
|
||||
* @param len Length of the output buffer, in bytes
|
||||
*
|
||||
* @return \c 1 on success, \c 0 on failure
|
||||
* @return \c 1 on success, \c 0 on failure
|
||||
*/
|
||||
int rand_bytes (uint8_t *output, int len);
|
||||
int rand_bytes(uint8_t *output, int len);
|
||||
|
||||
/*
|
||||
*
|
||||
|
|
@ -130,42 +131,42 @@ int rand_bytes (uint8_t *output, int len);
|
|||
* Return number of DES cblocks (1 cblock = length of a single-DES key) for the
|
||||
* current key type or 0 if not a DES cipher.
|
||||
*
|
||||
* @param kt Type of key
|
||||
* @param kt Type of key
|
||||
*
|
||||
* @return Number of DES cblocks that the key consists of, or 0.
|
||||
* @return Number of DES cblocks that the key consists of, or 0.
|
||||
*/
|
||||
int key_des_num_cblocks (const cipher_kt_t *kt);
|
||||
int key_des_num_cblocks(const cipher_kt_t *kt);
|
||||
|
||||
/*
|
||||
* Check the given DES key. Checks the given key's length, weakness and parity.
|
||||
*
|
||||
* @param key Key to check
|
||||
* @param key_len Length of the key, in bytes
|
||||
* @param ndc Number of DES cblocks that the key is made up of.
|
||||
* @param key Key to check
|
||||
* @param key_len Length of the key, in bytes
|
||||
* @param ndc Number of DES cblocks that the key is made up of.
|
||||
*
|
||||
* @return \c true if the key is valid, \c false otherwise.
|
||||
* @return \c true if the key is valid, \c false otherwise.
|
||||
*/
|
||||
bool key_des_check (uint8_t *key, int key_len, int ndc);
|
||||
bool key_des_check(uint8_t *key, int key_len, int ndc);
|
||||
|
||||
/*
|
||||
* Fix the given DES key, setting its parity to odd.
|
||||
*
|
||||
* @param key Key to check
|
||||
* @param key_len Length of the key, in bytes
|
||||
* @param ndc Number of DES cblocks that the key is made up of.
|
||||
* @param key Key to check
|
||||
* @param key_len Length of the key, in bytes
|
||||
* @param ndc Number of DES cblocks that the key is made up of.
|
||||
*/
|
||||
void key_des_fixup (uint8_t *key, int key_len, int ndc);
|
||||
void key_des_fixup(uint8_t *key, int key_len, int ndc);
|
||||
|
||||
/**
|
||||
* Encrypt the given block, using DES ECB mode
|
||||
*
|
||||
* @param key DES key to use.
|
||||
* @param src Buffer containing the 8-byte source.
|
||||
* @param dst Buffer containing the 8-byte destination
|
||||
* @param key DES key to use.
|
||||
* @param src Buffer containing the 8-byte source.
|
||||
* @param dst Buffer containing the 8-byte destination
|
||||
*/
|
||||
void cipher_des_encrypt_ecb (const unsigned char key[DES_KEY_LENGTH],
|
||||
unsigned char src[DES_KEY_LENGTH],
|
||||
unsigned char dst[DES_KEY_LENGTH]);
|
||||
void cipher_des_encrypt_ecb(const unsigned char key[DES_KEY_LENGTH],
|
||||
unsigned char src[DES_KEY_LENGTH],
|
||||
unsigned char dst[DES_KEY_LENGTH]);
|
||||
|
||||
/*
|
||||
*
|
||||
|
|
@ -191,98 +192,98 @@ void cipher_des_encrypt_ecb (const unsigned char key[DES_KEY_LENGTH],
|
|||
* contents of these parameters are library-specific, and can be used to
|
||||
* initialise encryption/decryption.
|
||||
*
|
||||
* @param ciphername Name of the cipher to retrieve parameters for (e.g.
|
||||
* \c AES-128-CBC).
|
||||
* @param ciphername Name of the cipher to retrieve parameters for (e.g.
|
||||
* \c AES-128-CBC).
|
||||
*
|
||||
* @return A statically allocated structure containing parameters
|
||||
* for the given cipher, or NULL if no matching parameters
|
||||
* were found.
|
||||
* @return A statically allocated structure containing parameters
|
||||
* for the given cipher, or NULL if no matching parameters
|
||||
* were found.
|
||||
*/
|
||||
const cipher_kt_t * cipher_kt_get (const char *ciphername);
|
||||
const cipher_kt_t *cipher_kt_get(const char *ciphername);
|
||||
|
||||
/**
|
||||
* Retrieve a string describing the cipher (e.g. \c AES-128-CBC).
|
||||
*
|
||||
* @param cipher_kt Static cipher parameters
|
||||
* @param cipher_kt Static cipher parameters
|
||||
*
|
||||
* @return a statically allocated string describing the cipher.
|
||||
*/
|
||||
const char * cipher_kt_name (const cipher_kt_t *cipher_kt);
|
||||
const char *cipher_kt_name(const cipher_kt_t *cipher_kt);
|
||||
|
||||
/**
|
||||
* Returns the size of keys used by the cipher, in bytes. If the cipher has a
|
||||
* variable key size, return the default key size.
|
||||
*
|
||||
* @param cipher_kt Static cipher parameters
|
||||
* @param cipher_kt Static cipher parameters
|
||||
*
|
||||
* @return (Default) size of keys used by the cipher, in bytes.
|
||||
* @return (Default) size of keys used by the cipher, in bytes.
|
||||
*/
|
||||
int cipher_kt_key_size (const cipher_kt_t *cipher_kt);
|
||||
int cipher_kt_key_size(const cipher_kt_t *cipher_kt);
|
||||
|
||||
/**
|
||||
* Returns the size of the IV used by the cipher, in bytes, or 0 if no IV is
|
||||
* used.
|
||||
*
|
||||
* @param cipher_kt Static cipher parameters
|
||||
* @param cipher_kt Static cipher parameters
|
||||
*
|
||||
* @return Size of the IV, in bytes, or 0 if the cipher does not
|
||||
* use an IV.
|
||||
* @return Size of the IV, in bytes, or 0 if the cipher does not
|
||||
* use an IV.
|
||||
*/
|
||||
int cipher_kt_iv_size (const cipher_kt_t *cipher_kt);
|
||||
int cipher_kt_iv_size(const cipher_kt_t *cipher_kt);
|
||||
|
||||
/**
|
||||
* Returns the block size of the cipher, in bytes.
|
||||
*
|
||||
* @param cipher_kt Static cipher parameters
|
||||
* @param cipher_kt Static cipher parameters
|
||||
*
|
||||
* @return Block size, in bytes.
|
||||
* @return Block size, in bytes.
|
||||
*/
|
||||
int cipher_kt_block_size (const cipher_kt_t *cipher_kt);
|
||||
int cipher_kt_block_size(const cipher_kt_t *cipher_kt);
|
||||
|
||||
/**
|
||||
* Returns the MAC tag size of the cipher, in bytes.
|
||||
*
|
||||
* @param ctx Static cipher parameters.
|
||||
* @param ctx Static cipher parameters.
|
||||
*
|
||||
* @return Tag size in bytes, or 0 if the tag size could not be
|
||||
* determined.
|
||||
* @return Tag size in bytes, or 0 if the tag size could not be
|
||||
* determined.
|
||||
*/
|
||||
int cipher_kt_tag_size (const cipher_kt_t *cipher_kt);
|
||||
int cipher_kt_tag_size(const cipher_kt_t *cipher_kt);
|
||||
|
||||
/**
|
||||
* Returns the mode that the cipher runs in.
|
||||
*
|
||||
* @param cipher_kt Static cipher parameters. May not be NULL.
|
||||
* @param cipher_kt Static cipher parameters. May not be NULL.
|
||||
*
|
||||
* @return Cipher mode, either \c OPENVPN_MODE_CBC, \c
|
||||
* OPENVPN_MODE_OFB or \c OPENVPN_MODE_CFB
|
||||
* @return Cipher mode, either \c OPENVPN_MODE_CBC, \c
|
||||
* OPENVPN_MODE_OFB or \c OPENVPN_MODE_CFB
|
||||
*/
|
||||
int cipher_kt_mode (const cipher_kt_t *cipher_kt);
|
||||
int cipher_kt_mode(const cipher_kt_t *cipher_kt);
|
||||
|
||||
/**
|
||||
* Check if the supplied cipher is a supported CBC mode cipher.
|
||||
*
|
||||
* @param cipher Static cipher parameters.
|
||||
* @param cipher Static cipher parameters.
|
||||
*
|
||||
* @return true iff the cipher is a CBC mode cipher.
|
||||
* @return true iff the cipher is a CBC mode cipher.
|
||||
*/
|
||||
bool cipher_kt_mode_cbc(const cipher_kt_t *cipher);
|
||||
|
||||
/**
|
||||
* Check if the supplied cipher is a supported OFB or CFB mode cipher.
|
||||
*
|
||||
* @param cipher Static cipher parameters.
|
||||
* @param cipher Static cipher parameters.
|
||||
*
|
||||
* @return true iff the cipher is a OFB or CFB mode cipher.
|
||||
* @return true iff the cipher is a OFB or CFB mode cipher.
|
||||
*/
|
||||
bool cipher_kt_mode_ofb_cfb(const cipher_kt_t *cipher);
|
||||
|
||||
/**
|
||||
* Check if the supplied cipher is a supported AEAD mode cipher.
|
||||
*
|
||||
* @param cipher Static cipher parameters.
|
||||
* @param cipher Static cipher parameters.
|
||||
*
|
||||
* @return true iff the cipher is a AEAD mode cipher.
|
||||
* @return true iff the cipher is a AEAD mode cipher.
|
||||
*/
|
||||
bool cipher_kt_mode_aead(const cipher_kt_t *cipher);
|
||||
|
||||
|
|
@ -296,94 +297,94 @@ bool cipher_kt_mode_aead(const cipher_kt_t *cipher);
|
|||
/**
|
||||
* Initialise a cipher context, based on the given key and key type.
|
||||
*
|
||||
* @param ctx Cipher context. May not be NULL
|
||||
* @param key Buffer containing the key to use
|
||||
* @param key_len Length of the key, in bytes
|
||||
* @param kt Static cipher parameters to use
|
||||
* @param enc Whether to encrypt or decrypt (either
|
||||
* \c MBEDTLS_OP_ENCRYPT or \c MBEDTLS_OP_DECRYPT).
|
||||
* @param ctx Cipher context. May not be NULL
|
||||
* @param key Buffer containing the key to use
|
||||
* @param key_len Length of the key, in bytes
|
||||
* @param kt Static cipher parameters to use
|
||||
* @param enc Whether to encrypt or decrypt (either
|
||||
* \c MBEDTLS_OP_ENCRYPT or \c MBEDTLS_OP_DECRYPT).
|
||||
*/
|
||||
void cipher_ctx_init (cipher_ctx_t *ctx, uint8_t *key, int key_len,
|
||||
const cipher_kt_t *kt, int enc);
|
||||
void cipher_ctx_init(cipher_ctx_t *ctx, uint8_t *key, int key_len,
|
||||
const cipher_kt_t *kt, int enc);
|
||||
|
||||
/**
|
||||
* Cleanup the specified context.
|
||||
*
|
||||
* @param ctx Cipher context to cleanup.
|
||||
* @param ctx Cipher context to cleanup.
|
||||
*/
|
||||
void cipher_ctx_cleanup (cipher_ctx_t *ctx);
|
||||
void cipher_ctx_cleanup(cipher_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* Returns the size of the IV used by the cipher, in bytes, or 0 if no IV is
|
||||
* used.
|
||||
*
|
||||
* @param ctx The cipher's context
|
||||
* @param ctx The cipher's context
|
||||
*
|
||||
* @return Size of the IV, in bytes, or \c 0 if the cipher does not
|
||||
* use an IV or ctx was NULL.
|
||||
* @return Size of the IV, in bytes, or \c 0 if the cipher does not
|
||||
* use an IV or ctx was NULL.
|
||||
*/
|
||||
int cipher_ctx_iv_length (const cipher_ctx_t *ctx);
|
||||
int cipher_ctx_iv_length(const cipher_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* Gets the computed message authenticated code (MAC) tag for this cipher.
|
||||
*
|
||||
* @param ctx The cipher's context
|
||||
* @param tag The buffer to write computed tag in.
|
||||
* @param tag_size The tag buffer size, in bytes.
|
||||
* @param ctx The cipher's context
|
||||
* @param tag The buffer to write computed tag in.
|
||||
* @param tag_size The tag buffer size, in bytes.
|
||||
*/
|
||||
int cipher_ctx_get_tag (cipher_ctx_t *ctx, uint8_t* tag, int tag_len);
|
||||
int cipher_ctx_get_tag(cipher_ctx_t *ctx, uint8_t *tag, int tag_len);
|
||||
|
||||
/**
|
||||
* Returns the block size of the cipher, in bytes.
|
||||
*
|
||||
* @param ctx The cipher's context
|
||||
* @param ctx The cipher's context
|
||||
*
|
||||
* @return Block size, in bytes, or 0 if ctx was NULL.
|
||||
* @return Block size, in bytes, or 0 if ctx was NULL.
|
||||
*/
|
||||
int cipher_ctx_block_size (const cipher_ctx_t *ctx);
|
||||
int cipher_ctx_block_size(const cipher_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* Returns the mode that the cipher runs in.
|
||||
*
|
||||
* @param ctx Cipher's context. May not be NULL.
|
||||
* @param ctx Cipher's context. May not be NULL.
|
||||
*
|
||||
* @return Cipher mode, either \c OPENVPN_MODE_CBC, \c
|
||||
* OPENVPN_MODE_OFB or \c OPENVPN_MODE_CFB
|
||||
* @return Cipher mode, either \c OPENVPN_MODE_CBC, \c
|
||||
* OPENVPN_MODE_OFB or \c OPENVPN_MODE_CFB
|
||||
*/
|
||||
int cipher_ctx_mode (const cipher_ctx_t *ctx);
|
||||
int cipher_ctx_mode(const cipher_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* Returns the static cipher parameters for this context.
|
||||
*
|
||||
* @param ctx Cipher's context.
|
||||
* @param ctx Cipher's context.
|
||||
*
|
||||
* @return Static cipher parameters for the supplied context, or
|
||||
* NULL if unable to determine cipher parameters.
|
||||
* @return Static cipher parameters for the supplied context, or
|
||||
* NULL if unable to determine cipher parameters.
|
||||
*/
|
||||
const cipher_kt_t *cipher_ctx_get_cipher_kt (const cipher_ctx_t *ctx);
|
||||
const cipher_kt_t *cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx);
|
||||
|
||||
/**
|
||||
* Resets the given cipher context, setting the IV to the specified value.
|
||||
* Preserves the associated key information.
|
||||
*
|
||||
* @param ctx Cipher's context. May not be NULL.
|
||||
* @param iv_buf The IV to use.
|
||||
* @param ctx Cipher's context. May not be NULL.
|
||||
* @param iv_buf The IV to use.
|
||||
*
|
||||
* @return \c 0 on failure, \c 1 on success.
|
||||
* @return \c 0 on failure, \c 1 on success.
|
||||
*/
|
||||
int cipher_ctx_reset (cipher_ctx_t *ctx, uint8_t *iv_buf);
|
||||
int cipher_ctx_reset(cipher_ctx_t *ctx, uint8_t *iv_buf);
|
||||
|
||||
/**
|
||||
* Updates the given cipher context, providing additional data (AD) for
|
||||
* authenticated encryption with additional data (AEAD) cipher modes.
|
||||
*
|
||||
* @param ctx Cipher's context. May not be NULL.
|
||||
* @param src Source buffer
|
||||
* @param src_len Length of the source buffer, in bytes
|
||||
* @param ctx Cipher's context. May not be NULL.
|
||||
* @param src Source buffer
|
||||
* @param src_len Length of the source buffer, in bytes
|
||||
*
|
||||
* @return \c 0 on failure, \c 1 on success.
|
||||
* @return \c 0 on failure, \c 1 on success.
|
||||
*/
|
||||
int cipher_ctx_update_ad (cipher_ctx_t *ctx, const uint8_t *src, int src_len);
|
||||
int cipher_ctx_update_ad(cipher_ctx_t *ctx, const uint8_t *src, int src_len);
|
||||
|
||||
/**
|
||||
* Updates the given cipher context, encrypting data in the source buffer, and
|
||||
|
|
@ -394,28 +395,28 @@ int cipher_ctx_update_ad (cipher_ctx_t *ctx, const uint8_t *src, int src_len);
|
|||
* to \c cipher_ctx_final(). This implies that dst should have enough room for
|
||||
* src_len + \c cipher_ctx_block_size().
|
||||
*
|
||||
* @param ctx Cipher's context. May not be NULL.
|
||||
* @param dst Destination buffer
|
||||
* @param dst_len Length of the destination buffer, in bytes
|
||||
* @param src Source buffer
|
||||
* @param src_len Length of the source buffer, in bytes
|
||||
* @param ctx Cipher's context. May not be NULL.
|
||||
* @param dst Destination buffer
|
||||
* @param dst_len Length of the destination buffer, in bytes
|
||||
* @param src Source buffer
|
||||
* @param src_len Length of the source buffer, in bytes
|
||||
*
|
||||
* @return \c 0 on failure, \c 1 on success.
|
||||
* @return \c 0 on failure, \c 1 on success.
|
||||
*/
|
||||
int cipher_ctx_update (cipher_ctx_t *ctx, uint8_t *dst, int *dst_len,
|
||||
uint8_t *src, int src_len);
|
||||
int cipher_ctx_update(cipher_ctx_t *ctx, uint8_t *dst, int *dst_len,
|
||||
uint8_t *src, int src_len);
|
||||
|
||||
/**
|
||||
* Pads the final cipher block using PKCS padding, and output to the destination
|
||||
* buffer.
|
||||
*
|
||||
* @param ctx Cipher's context. May not be NULL.
|
||||
* @param dst Destination buffer
|
||||
* @param dst_len Length of the destination buffer, in bytes
|
||||
* @param ctx Cipher's context. May not be NULL.
|
||||
* @param dst Destination buffer
|
||||
* @param dst_len Length of the destination buffer, in bytes
|
||||
*
|
||||
* @return \c 0 on failure, \c 1 on success.
|
||||
* @return \c 0 on failure, \c 1 on success.
|
||||
*/
|
||||
int cipher_ctx_final (cipher_ctx_t *ctx, uint8_t *dst, int *dst_len);
|
||||
int cipher_ctx_final(cipher_ctx_t *ctx, uint8_t *dst, int *dst_len);
|
||||
|
||||
/**
|
||||
* Like \c cipher_ctx_final, but check the computed authentication tag against
|
||||
|
|
@ -430,8 +431,8 @@ int cipher_ctx_final (cipher_ctx_t *ctx, uint8_t *dst, int *dst_len);
|
|||
*
|
||||
* @return \c 0 on failure, \c 1 on success.
|
||||
*/
|
||||
int cipher_ctx_final_check_tag (cipher_ctx_t *ctx, uint8_t *dst, int *dst_len,
|
||||
uint8_t *tag, size_t tag_len);
|
||||
int cipher_ctx_final_check_tag(cipher_ctx_t *ctx, uint8_t *dst, int *dst_len,
|
||||
uint8_t *tag, size_t tag_len);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -454,32 +455,32 @@ int cipher_ctx_final_check_tag (cipher_ctx_t *ctx, uint8_t *dst, int *dst_len,
|
|||
* contents of these parameters are library-specific, and can be used to
|
||||
* initialise HMAC or message digest operations.
|
||||
*
|
||||
* @param digest Name of the digest to retrieve parameters for (e.g.
|
||||
* \c MD5).
|
||||
* @param digest Name of the digest to retrieve parameters for (e.g.
|
||||
* \c MD5).
|
||||
*
|
||||
* @return A statically allocated structure containing parameters
|
||||
* for the given message digest.
|
||||
* @return A statically allocated structure containing parameters
|
||||
* for the given message digest.
|
||||
*/
|
||||
const md_kt_t * md_kt_get (const char *digest);
|
||||
const md_kt_t *md_kt_get(const char *digest);
|
||||
|
||||
/**
|
||||
* Retrieve a string describing the digest digest (e.g. \c SHA1).
|
||||
*
|
||||
* @param kt Static message digest parameters
|
||||
* @param kt Static message digest parameters
|
||||
*
|
||||
* @return Statically allocated string describing the message
|
||||
* digest.
|
||||
* @return Statically allocated string describing the message
|
||||
* digest.
|
||||
*/
|
||||
const char * md_kt_name (const md_kt_t *kt);
|
||||
const char *md_kt_name(const md_kt_t *kt);
|
||||
|
||||
/**
|
||||
* Returns the size of the message digest, in bytes.
|
||||
*
|
||||
* @param kt Static message digest parameters
|
||||
* @param kt Static message digest parameters
|
||||
*
|
||||
* @return Message digest size, in bytes, or 0 if ctx was NULL.
|
||||
* @return Message digest size, in bytes, or 0 if ctx was NULL.
|
||||
*/
|
||||
int md_kt_size (const md_kt_t *kt);
|
||||
int md_kt_size(const md_kt_t *kt);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -491,55 +492,55 @@ int md_kt_size (const md_kt_t *kt);
|
|||
/*
|
||||
* Calculates the message digest for the given buffer.
|
||||
*
|
||||
* @param kt Static message digest parameters
|
||||
* @param src Buffer to digest. May not be NULL.
|
||||
* @param src_len The length of the incoming buffer.
|
||||
* @param dst Buffer to write the message digest to. May not be NULL.
|
||||
* @param kt Static message digest parameters
|
||||
* @param src Buffer to digest. May not be NULL.
|
||||
* @param src_len The length of the incoming buffer.
|
||||
* @param dst Buffer to write the message digest to. May not be NULL.
|
||||
*
|
||||
* @return \c 1 on success, \c 0 on failure
|
||||
* @return \c 1 on success, \c 0 on failure
|
||||
*/
|
||||
int md_full (const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst);
|
||||
int md_full(const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst);
|
||||
|
||||
/*
|
||||
* Initialises the given message digest context.
|
||||
*
|
||||
* @param ctx Message digest context
|
||||
* @param kt Static message digest parameters
|
||||
* @param ctx Message digest context
|
||||
* @param kt Static message digest parameters
|
||||
*/
|
||||
void md_ctx_init (md_ctx_t *ctx, const md_kt_t *kt);
|
||||
void md_ctx_init(md_ctx_t *ctx, const md_kt_t *kt);
|
||||
|
||||
/*
|
||||
* Free the given message digest context.
|
||||
*
|
||||
* @param ctx Message digest context
|
||||
* @param ctx Message digest context
|
||||
*/
|
||||
void md_ctx_cleanup(md_ctx_t *ctx);
|
||||
|
||||
/*
|
||||
* Returns the size of the message digest output by the given context
|
||||
*
|
||||
* @param ctx Message digest context.
|
||||
* @param ctx Message digest context.
|
||||
*
|
||||
* @return Size of the message digest, or \0 if ctx is NULL.
|
||||
* @return Size of the message digest, or \0 if ctx is NULL.
|
||||
*/
|
||||
int md_ctx_size (const md_ctx_t *ctx);
|
||||
int md_ctx_size(const md_ctx_t *ctx);
|
||||
|
||||
/*
|
||||
* Process the given data for use in the message digest.
|
||||
*
|
||||
* @param ctx Message digest context. May not be NULL.
|
||||
* @param src Buffer to digest. May not be NULL.
|
||||
* @param src_len The length of the incoming buffer.
|
||||
* @param ctx Message digest context. May not be NULL.
|
||||
* @param src Buffer to digest. May not be NULL.
|
||||
* @param src_len The length of the incoming buffer.
|
||||
*/
|
||||
void md_ctx_update (md_ctx_t *ctx, const uint8_t *src, int src_len);
|
||||
void md_ctx_update(md_ctx_t *ctx, const uint8_t *src, int src_len);
|
||||
|
||||
/*
|
||||
* Output the message digest to the given buffer.
|
||||
*
|
||||
* @param ctx Message digest context. May not be NULL.
|
||||
* @param dst Buffer to write the message digest to. May not be NULL.
|
||||
* @param ctx Message digest context. May not be NULL.
|
||||
* @param dst Buffer to write the message digest to. May not be NULL.
|
||||
*/
|
||||
void md_ctx_final (md_ctx_t *ctx, uint8_t *dst);
|
||||
void md_ctx_final(md_ctx_t *ctx, uint8_t *dst);
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -552,73 +553,73 @@ void md_ctx_final (md_ctx_t *ctx, uint8_t *dst);
|
|||
* Initialises the given HMAC context, using the given digest
|
||||
* and key.
|
||||
*
|
||||
* @param ctx HMAC context to intialise
|
||||
* @param key The key to use for the HMAC
|
||||
* @param key_len The key length to use
|
||||
* @param kt Static message digest parameters
|
||||
* @param ctx HMAC context to intialise
|
||||
* @param key The key to use for the HMAC
|
||||
* @param key_len The key length to use
|
||||
* @param kt Static message digest parameters
|
||||
*
|
||||
*/
|
||||
void hmac_ctx_init (hmac_ctx_t *ctx, const uint8_t *key, int key_length,
|
||||
const md_kt_t *kt);
|
||||
void hmac_ctx_init(hmac_ctx_t *ctx, const uint8_t *key, int key_length,
|
||||
const md_kt_t *kt);
|
||||
|
||||
/*
|
||||
* Free the given HMAC context.
|
||||
*
|
||||
* @param ctx HMAC context
|
||||
* @param ctx HMAC context
|
||||
*/
|
||||
void hmac_ctx_cleanup(hmac_ctx_t *ctx);
|
||||
|
||||
/*
|
||||
* Returns the size of the HMAC output by the given HMAC Context
|
||||
*
|
||||
* @param ctx HMAC context.
|
||||
* @param ctx HMAC context.
|
||||
*
|
||||
* @return Size of the HMAC, or \0 if ctx is NULL.
|
||||
* @return Size of the HMAC, or \0 if ctx is NULL.
|
||||
*/
|
||||
int hmac_ctx_size (const hmac_ctx_t *ctx);
|
||||
int hmac_ctx_size(const hmac_ctx_t *ctx);
|
||||
|
||||
/*
|
||||
* Resets the given HMAC context, preserving the associated key information
|
||||
*
|
||||
* @param ctx HMAC context. May not be NULL.
|
||||
* @param ctx HMAC context. May not be NULL.
|
||||
*/
|
||||
void hmac_ctx_reset (hmac_ctx_t *ctx);
|
||||
void hmac_ctx_reset(hmac_ctx_t *ctx);
|
||||
|
||||
/*
|
||||
* Process the given data for use in the HMAC.
|
||||
*
|
||||
* @param ctx HMAC context. May not be NULL.
|
||||
* @param src The buffer to HMAC. May not be NULL.
|
||||
* @param src_len The length of the incoming buffer.
|
||||
* @param ctx HMAC context. May not be NULL.
|
||||
* @param src The buffer to HMAC. May not be NULL.
|
||||
* @param src_len The length of the incoming buffer.
|
||||
*/
|
||||
void hmac_ctx_update (hmac_ctx_t *ctx, const uint8_t *src, int src_len);
|
||||
void hmac_ctx_update(hmac_ctx_t *ctx, const uint8_t *src, int src_len);
|
||||
|
||||
/*
|
||||
* Output the HMAC to the given buffer.
|
||||
*
|
||||
* @param ctx HMAC context. May not be NULL.
|
||||
* @param dst buffer to write the HMAC to. May not be NULL.
|
||||
* @param ctx HMAC context. May not be NULL.
|
||||
* @param dst buffer to write the HMAC to. May not be NULL.
|
||||
*/
|
||||
void hmac_ctx_final (hmac_ctx_t *ctx, uint8_t *dst);
|
||||
void hmac_ctx_final(hmac_ctx_t *ctx, uint8_t *dst);
|
||||
|
||||
/**
|
||||
* Translate an OpenVPN cipher name to a crypto library cipher name.
|
||||
*
|
||||
* @param cipher_name An OpenVPN cipher name
|
||||
* @param cipher_name An OpenVPN cipher name
|
||||
*
|
||||
* @return The corresponding crypto library cipher name, or NULL
|
||||
* if no matching cipher name was found.
|
||||
* @return The corresponding crypto library cipher name, or NULL
|
||||
* if no matching cipher name was found.
|
||||
*/
|
||||
const char * translate_cipher_name_from_openvpn (const char *cipher_name);
|
||||
const char *translate_cipher_name_from_openvpn(const char *cipher_name);
|
||||
|
||||
/**
|
||||
* Translate a crypto library cipher name to an OpenVPN cipher name.
|
||||
*
|
||||
* @param cipher_name A crypto library cipher name
|
||||
* @param cipher_name A crypto library cipher name
|
||||
*
|
||||
* @return The corresponding OpenVPN cipher name, or NULL if no
|
||||
* matching cipher name was found.
|
||||
* @return The corresponding OpenVPN cipher name, or NULL if no
|
||||
* matching cipher name was found.
|
||||
*/
|
||||
const char * translate_cipher_name_to_openvpn (const char *cipher_name);
|
||||
const char *translate_cipher_name_to_openvpn(const char *cipher_name);
|
||||
|
||||
#endif /* CRYPTO_BACKEND_H_ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -50,29 +50,29 @@ typedef mbedtls_md_context_t md_ctx_t;
|
|||
typedef mbedtls_md_context_t hmac_ctx_t;
|
||||
|
||||
/** Maximum length of an IV */
|
||||
#define OPENVPN_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH
|
||||
#define OPENVPN_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH
|
||||
|
||||
/** Cipher is in CBC mode */
|
||||
#define OPENVPN_MODE_CBC MBEDTLS_MODE_CBC
|
||||
#define OPENVPN_MODE_CBC MBEDTLS_MODE_CBC
|
||||
|
||||
/** Cipher is in OFB mode */
|
||||
#define OPENVPN_MODE_OFB MBEDTLS_MODE_OFB
|
||||
#define OPENVPN_MODE_OFB MBEDTLS_MODE_OFB
|
||||
|
||||
/** Cipher is in CFB mode */
|
||||
#define OPENVPN_MODE_CFB MBEDTLS_MODE_CFB
|
||||
#define OPENVPN_MODE_CFB MBEDTLS_MODE_CFB
|
||||
|
||||
/** Cipher is in GCM mode */
|
||||
#define OPENVPN_MODE_GCM MBEDTLS_MODE_GCM
|
||||
#define OPENVPN_MODE_GCM MBEDTLS_MODE_GCM
|
||||
|
||||
/** Cipher should encrypt */
|
||||
#define OPENVPN_OP_ENCRYPT MBEDTLS_ENCRYPT
|
||||
#define OPENVPN_OP_ENCRYPT MBEDTLS_ENCRYPT
|
||||
|
||||
/** Cipher should decrypt */
|
||||
#define OPENVPN_OP_DECRYPT MBEDTLS_DECRYPT
|
||||
#define OPENVPN_OP_DECRYPT MBEDTLS_DECRYPT
|
||||
|
||||
#define MD4_DIGEST_LENGTH 16
|
||||
#define MD5_DIGEST_LENGTH 16
|
||||
#define SHA_DIGEST_LENGTH 20
|
||||
#define MD4_DIGEST_LENGTH 16
|
||||
#define MD5_DIGEST_LENGTH 16
|
||||
#define SHA_DIGEST_LENGTH 20
|
||||
#define DES_KEY_LENGTH 8
|
||||
|
||||
/**
|
||||
|
|
@ -92,14 +92,15 @@ mbedtls_ctr_drbg_context *rand_ctx_get();
|
|||
* Enable prediction resistance on the random number generator.
|
||||
*/
|
||||
void rand_ctx_enable_prediction_resistance();
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Log the supplied mbed TLS error, prefixed by supplied prefix.
|
||||
*
|
||||
* @param flags Flags to indicate error type and priority.
|
||||
* @param errval mbed TLS error code to convert to error message.
|
||||
* @param prefix Prefix to mbed TLS error message.
|
||||
* @param flags Flags to indicate error type and priority.
|
||||
* @param errval mbed TLS error code to convert to error message.
|
||||
* @param prefix Prefix to mbed TLS error message.
|
||||
*
|
||||
* @returns true if no errors are detected, false otherwise.
|
||||
*/
|
||||
|
|
@ -108,23 +109,25 @@ bool mbed_log_err(unsigned int flags, int errval, const char *prefix);
|
|||
/**
|
||||
* Log the supplied mbed TLS error, prefixed by function name and line number.
|
||||
*
|
||||
* @param flags Flags to indicate error type and priority.
|
||||
* @param errval mbed TLS error code to convert to error message.
|
||||
* @param func Function name where error was reported.
|
||||
* @param line Line number where error was reported.
|
||||
* @param flags Flags to indicate error type and priority.
|
||||
* @param errval mbed TLS error code to convert to error message.
|
||||
* @param func Function name where error was reported.
|
||||
* @param line Line number where error was reported.
|
||||
*
|
||||
* @returns true if no errors are detected, false otherwise.
|
||||
*/
|
||||
bool mbed_log_func_line(unsigned int flags, int errval, const char *func,
|
||||
int line);
|
||||
int line);
|
||||
|
||||
/** Wraps mbed_log_func_line() to prevent function calls for non-errors */
|
||||
static inline bool mbed_log_func_line_lite(unsigned int flags, int errval,
|
||||
const char *func, int line) {
|
||||
if (errval) {
|
||||
return mbed_log_func_line (flags, errval, func, line);
|
||||
}
|
||||
return true;
|
||||
static inline bool
|
||||
mbed_log_func_line_lite(unsigned int flags, int errval,
|
||||
const char *func, int line) {
|
||||
if (errval)
|
||||
{
|
||||
return mbed_log_func_line(flags, errval, func, line);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -135,12 +138,12 @@ static inline bool mbed_log_func_line_lite(unsigned int flags, int errval,
|
|||
* or
|
||||
* ASSERT (mbed_ok (mbedtls_ssl_func()));
|
||||
*
|
||||
* @param errval mbed TLS error code to convert to error message.
|
||||
* @param errval mbed TLS error code to convert to error message.
|
||||
*
|
||||
* @returns true if no errors are detected, false otherwise.
|
||||
*/
|
||||
#define mbed_ok(errval) \
|
||||
mbed_log_func_line_lite(D_CRYPT_ERRORS, errval, __func__, __LINE__)
|
||||
mbed_log_func_line_lite(D_CRYPT_ERRORS, errval, __func__, __LINE__)
|
||||
|
||||
|
||||
#endif /* CRYPTO_MBEDTLS_H_ */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -50,39 +50,39 @@ typedef EVP_MD_CTX md_ctx_t;
|
|||
typedef HMAC_CTX hmac_ctx_t;
|
||||
|
||||
/** Maximum length of an IV */
|
||||
#define OPENVPN_MAX_IV_LENGTH EVP_MAX_IV_LENGTH
|
||||
#define OPENVPN_MAX_IV_LENGTH EVP_MAX_IV_LENGTH
|
||||
|
||||
/** Cipher is in CBC mode */
|
||||
#define OPENVPN_MODE_CBC EVP_CIPH_CBC_MODE
|
||||
#define OPENVPN_MODE_CBC EVP_CIPH_CBC_MODE
|
||||
|
||||
/** Cipher is in OFB mode */
|
||||
#define OPENVPN_MODE_OFB EVP_CIPH_OFB_MODE
|
||||
#define OPENVPN_MODE_OFB EVP_CIPH_OFB_MODE
|
||||
|
||||
/** Cipher is in CFB mode */
|
||||
#define OPENVPN_MODE_CFB EVP_CIPH_CFB_MODE
|
||||
#define OPENVPN_MODE_CFB EVP_CIPH_CFB_MODE
|
||||
|
||||
#ifdef HAVE_AEAD_CIPHER_MODES
|
||||
|
||||
/** Cipher is in GCM mode */
|
||||
#define OPENVPN_MODE_GCM EVP_CIPH_GCM_MODE
|
||||
#define OPENVPN_MODE_GCM EVP_CIPH_GCM_MODE
|
||||
|
||||
#endif /* HAVE_AEAD_CIPHER_MODES */
|
||||
|
||||
/** Cipher should encrypt */
|
||||
#define OPENVPN_OP_ENCRYPT 1
|
||||
#define OPENVPN_OP_ENCRYPT 1
|
||||
|
||||
/** Cipher should decrypt */
|
||||
#define OPENVPN_OP_DECRYPT 0
|
||||
#define OPENVPN_OP_DECRYPT 0
|
||||
|
||||
#define DES_KEY_LENGTH 8
|
||||
#define MD4_DIGEST_LENGTH 16
|
||||
#define MD4_DIGEST_LENGTH 16
|
||||
|
||||
/**
|
||||
* Retrieve any occurred OpenSSL errors and print those errors.
|
||||
*
|
||||
* Note that this function uses the not thread-safe OpenSSL error API.
|
||||
*
|
||||
* @param flags Flags to indicate error type and priority.
|
||||
* @param flags Flags to indicate error type and priority.
|
||||
*/
|
||||
void crypto_print_openssl_errors(const unsigned int flags);
|
||||
|
||||
|
|
@ -91,15 +91,15 @@ void crypto_print_openssl_errors(const unsigned int flags);
|
|||
*
|
||||
* This is just a convenience wrapper for often occurring situations.
|
||||
*
|
||||
* @param flags Flags to indicate error type and priority.
|
||||
* @param format Format string to print.
|
||||
* @param format args (optional) arguments for the format string.
|
||||
* @param flags Flags to indicate error type and priority.
|
||||
* @param format Format string to print.
|
||||
* @param format args (optional) arguments for the format string.
|
||||
*/
|
||||
# define crypto_msg(flags, ...) \
|
||||
do { \
|
||||
crypto_print_openssl_errors(nonfatal(flags)); \
|
||||
msg((flags), __VA_ARGS__); \
|
||||
} while (false)
|
||||
#define crypto_msg(flags, ...) \
|
||||
do { \
|
||||
crypto_print_openssl_errors(nonfatal(flags)); \
|
||||
msg((flags), __VA_ARGS__); \
|
||||
} while (false)
|
||||
|
||||
|
||||
#endif /* CRYPTO_OPENSSL_H_ */
|
||||
|
|
|
|||
|
|
@ -68,32 +68,32 @@
|
|||
#endif
|
||||
|
||||
/* Size of an SSL signature: MD5+SHA1 */
|
||||
#define SSL_SIG_LENGTH 36
|
||||
#define SSL_SIG_LENGTH 36
|
||||
|
||||
/* try to funnel any Windows/CryptoAPI error messages to OpenSSL ERR_... */
|
||||
#define ERR_LIB_CRYPTOAPI (ERR_LIB_USER + 69) /* 69 is just a number... */
|
||||
#define ERR_LIB_CRYPTOAPI (ERR_LIB_USER + 69) /* 69 is just a number... */
|
||||
#define CRYPTOAPIerr(f) err_put_ms_error(GetLastError(), (f), __FILE__, __LINE__)
|
||||
#define CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE 100
|
||||
#define CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE 101
|
||||
#define CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE 100
|
||||
#define CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE 101
|
||||
#define CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY 102
|
||||
#define CRYPTOAPI_F_CRYPT_CREATE_HASH 103
|
||||
#define CRYPTOAPI_F_CRYPT_GET_HASH_PARAM 104
|
||||
#define CRYPTOAPI_F_CRYPT_SET_HASH_PARAM 105
|
||||
#define CRYPTOAPI_F_CRYPT_SIGN_HASH 106
|
||||
#define CRYPTOAPI_F_LOAD_LIBRARY 107
|
||||
#define CRYPTOAPI_F_GET_PROC_ADDRESS 108
|
||||
#define CRYPTOAPI_F_CRYPT_CREATE_HASH 103
|
||||
#define CRYPTOAPI_F_CRYPT_GET_HASH_PARAM 104
|
||||
#define CRYPTOAPI_F_CRYPT_SET_HASH_PARAM 105
|
||||
#define CRYPTOAPI_F_CRYPT_SIGN_HASH 106
|
||||
#define CRYPTOAPI_F_LOAD_LIBRARY 107
|
||||
#define CRYPTOAPI_F_GET_PROC_ADDRESS 108
|
||||
|
||||
static ERR_STRING_DATA CRYPTOAPI_str_functs[] = {
|
||||
{ ERR_PACK(ERR_LIB_CRYPTOAPI, 0, 0), "microsoft cryptoapi"},
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE, 0), "CertOpenSystemStore" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE, 0), "CertFindCertificateInStore" },
|
||||
static ERR_STRING_DATA CRYPTOAPI_str_functs[] = {
|
||||
{ ERR_PACK(ERR_LIB_CRYPTOAPI, 0, 0), "microsoft cryptoapi"},
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE, 0), "CertOpenSystemStore" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE, 0), "CertFindCertificateInStore" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY, 0), "CryptAcquireCertificatePrivateKey" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CRYPT_CREATE_HASH, 0), "CryptCreateHash" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CRYPT_GET_HASH_PARAM, 0), "CryptGetHashParam" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CRYPT_SET_HASH_PARAM, 0), "CryptSetHashParam" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CRYPT_SIGN_HASH, 0), "CryptSignHash" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_LOAD_LIBRARY, 0), "LoadLibrary" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_GET_PROC_ADDRESS, 0), "GetProcAddress" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CRYPT_CREATE_HASH, 0), "CryptCreateHash" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CRYPT_GET_HASH_PARAM, 0), "CryptGetHashParam" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CRYPT_SET_HASH_PARAM, 0), "CryptSetHashParam" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_CRYPT_SIGN_HASH, 0), "CryptSignHash" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_LOAD_LIBRARY, 0), "LoadLibrary" },
|
||||
{ ERR_PACK(0, CRYPTOAPI_F_GET_PROC_ADDRESS, 0), "GetProcAddress" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
|
@ -104,76 +104,94 @@ typedef struct _CAPI_DATA {
|
|||
BOOL free_crypt_prov;
|
||||
} CAPI_DATA;
|
||||
|
||||
static char *ms_error_text(DWORD ms_err)
|
||||
static char *
|
||||
ms_error_text(DWORD ms_err)
|
||||
{
|
||||
LPVOID lpMsgBuf = NULL;
|
||||
char *rv = NULL;
|
||||
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, ms_err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
|
||||
(LPTSTR) &lpMsgBuf, 0, NULL);
|
||||
if (lpMsgBuf) {
|
||||
char *p;
|
||||
rv = string_alloc(lpMsgBuf, NULL);
|
||||
LocalFree(lpMsgBuf);
|
||||
/* trim to the left */
|
||||
if (rv)
|
||||
for (p = rv + strlen(rv) - 1; p >= rv; p--) {
|
||||
if (isspace(*p))
|
||||
*p = '\0';
|
||||
else
|
||||
break;
|
||||
}
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
|FORMAT_MESSAGE_FROM_SYSTEM
|
||||
|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, ms_err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
|
||||
(LPTSTR) &lpMsgBuf, 0, NULL);
|
||||
if (lpMsgBuf)
|
||||
{
|
||||
char *p;
|
||||
rv = string_alloc(lpMsgBuf, NULL);
|
||||
LocalFree(lpMsgBuf);
|
||||
/* trim to the left */
|
||||
if (rv)
|
||||
{
|
||||
for (p = rv + strlen(rv) - 1; p >= rv; p--) {
|
||||
if (isspace(*p))
|
||||
{
|
||||
*p = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void err_put_ms_error(DWORD ms_err, int func, const char *file, int line)
|
||||
static void
|
||||
err_put_ms_error(DWORD ms_err, int func, const char *file, int line)
|
||||
{
|
||||
static int init = 0;
|
||||
# define ERR_MAP_SZ 16
|
||||
#define ERR_MAP_SZ 16
|
||||
static struct {
|
||||
int err;
|
||||
DWORD ms_err; /* I don't think we get more than 16 *different* errors */
|
||||
int err;
|
||||
DWORD ms_err; /* I don't think we get more than 16 *different* errors */
|
||||
} err_map[ERR_MAP_SZ]; /* in here, before we give up the whole thing... */
|
||||
int i;
|
||||
|
||||
if (ms_err == 0)
|
||||
/* 0 is not an error */
|
||||
return;
|
||||
if (!init) {
|
||||
ERR_load_strings(ERR_LIB_CRYPTOAPI, CRYPTOAPI_str_functs);
|
||||
memset(&err_map, 0, sizeof(err_map));
|
||||
init++;
|
||||
{
|
||||
/* 0 is not an error */
|
||||
return;
|
||||
}
|
||||
if (!init)
|
||||
{
|
||||
ERR_load_strings(ERR_LIB_CRYPTOAPI, CRYPTOAPI_str_functs);
|
||||
memset(&err_map, 0, sizeof(err_map));
|
||||
init++;
|
||||
}
|
||||
/* since MS error codes are 32 bit, and the ones in the ERR_... system is
|
||||
* only 12, we must have a mapping table between them. */
|
||||
for (i = 0; i < ERR_MAP_SZ; i++) {
|
||||
if (err_map[i].ms_err == ms_err) {
|
||||
ERR_PUT_error(ERR_LIB_CRYPTOAPI, func, err_map[i].err, file, line);
|
||||
break;
|
||||
} else if (err_map[i].ms_err == 0 ) {
|
||||
/* end of table, add new entry */
|
||||
ERR_STRING_DATA *esd = calloc(2, sizeof(*esd));
|
||||
if (esd == NULL)
|
||||
break;
|
||||
err_map[i].ms_err = ms_err;
|
||||
err_map[i].err = esd->error = i + 100;
|
||||
esd->string = ms_error_text(ms_err);
|
||||
check_malloc_return(esd->string);
|
||||
ERR_load_strings(ERR_LIB_CRYPTOAPI, esd);
|
||||
ERR_PUT_error(ERR_LIB_CRYPTOAPI, func, err_map[i].err, file, line);
|
||||
break;
|
||||
}
|
||||
if (err_map[i].ms_err == ms_err)
|
||||
{
|
||||
ERR_PUT_error(ERR_LIB_CRYPTOAPI, func, err_map[i].err, file, line);
|
||||
break;
|
||||
}
|
||||
else if (err_map[i].ms_err == 0)
|
||||
{
|
||||
/* end of table, add new entry */
|
||||
ERR_STRING_DATA *esd = calloc(2, sizeof(*esd));
|
||||
if (esd == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
err_map[i].ms_err = ms_err;
|
||||
err_map[i].err = esd->error = i + 100;
|
||||
esd->string = ms_error_text(ms_err);
|
||||
check_malloc_return(esd->string);
|
||||
ERR_load_strings(ERR_LIB_CRYPTOAPI, esd);
|
||||
ERR_PUT_error(ERR_LIB_CRYPTOAPI, func, err_map[i].err, file, line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* encrypt */
|
||||
static int rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
|
||||
static int
|
||||
rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
/* I haven't been able to trigger this one, but I want to know if it happens... */
|
||||
assert(0);
|
||||
|
|
@ -182,7 +200,8 @@ static int rsa_pub_enc(int flen, const unsigned char *from, unsigned char *to, R
|
|||
}
|
||||
|
||||
/* verify arbitrary data */
|
||||
static int rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
|
||||
static int
|
||||
rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
/* I haven't been able to trigger this one, but I want to know if it happens... */
|
||||
assert(0);
|
||||
|
|
@ -191,68 +210,78 @@ static int rsa_pub_dec(int flen, const unsigned char *from, unsigned char *to, R
|
|||
}
|
||||
|
||||
/* sign arbitrary data */
|
||||
static int rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
|
||||
static int
|
||||
rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data;
|
||||
HCRYPTHASH hash;
|
||||
DWORD hash_size, len, i;
|
||||
unsigned char *buf;
|
||||
|
||||
if (cd == NULL) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
if (cd == NULL)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
if (padding != RSA_PKCS1_PADDING) {
|
||||
/* AFAICS, CryptSignHash() *always* uses PKCS1 padding. */
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
return 0;
|
||||
if (padding != RSA_PKCS1_PADDING)
|
||||
{
|
||||
/* AFAICS, CryptSignHash() *always* uses PKCS1 padding. */
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
|
||||
return 0;
|
||||
}
|
||||
/* Unfortunately, there is no "CryptSign()" function in CryptoAPI, that would
|
||||
* be way to straightforward for M$, I guess... So we have to do it this
|
||||
* tricky way instead, by creating a "Hash", and load the already-made hash
|
||||
* from 'from' into it. */
|
||||
/* For now, we only support NID_md5_sha1 */
|
||||
if (flen != SSL_SIG_LENGTH) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
|
||||
return 0;
|
||||
if (flen != SSL_SIG_LENGTH)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (!CryptCreateHash(cd->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash)) {
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_CREATE_HASH);
|
||||
return 0;
|
||||
if (!CryptCreateHash(cd->crypt_prov, CALG_SSL3_SHAMD5, 0, 0, &hash))
|
||||
{
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_CREATE_HASH);
|
||||
return 0;
|
||||
}
|
||||
len = sizeof(hash_size);
|
||||
if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len, 0)) {
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_GET_HASH_PARAM);
|
||||
if (!CryptGetHashParam(hash, HP_HASHSIZE, (BYTE *) &hash_size, &len, 0))
|
||||
{
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_GET_HASH_PARAM);
|
||||
CryptDestroyHash(hash);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
if ((int) hash_size != flen) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
|
||||
if ((int) hash_size != flen)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, RSA_R_INVALID_MESSAGE_LENGTH);
|
||||
CryptDestroyHash(hash);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0)) {
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_SET_HASH_PARAM);
|
||||
if (!CryptSetHashParam(hash, HP_HASHVAL, (BYTE * ) from, 0))
|
||||
{
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_SET_HASH_PARAM);
|
||||
CryptDestroyHash(hash);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = RSA_size(rsa);
|
||||
buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
if (buf == NULL)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
|
||||
CryptDestroyHash(hash);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
if (!CryptSignHash(hash, cd->key_spec, NULL, 0, buf, &len)) {
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_SIGN_HASH);
|
||||
if (!CryptSignHash(hash, cd->key_spec, NULL, 0, buf, &len))
|
||||
{
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_SIGN_HASH);
|
||||
CryptDestroyHash(hash);
|
||||
free(buf);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
/* and now, we have to reverse the byte-order in the result from CryptSignHash()... */
|
||||
for (i = 0; i < len; i++)
|
||||
to[i] = buf[len - i - 1];
|
||||
to[i] = buf[len - i - 1];
|
||||
free(buf);
|
||||
|
||||
CryptDestroyHash(hash);
|
||||
|
|
@ -260,7 +289,8 @@ static int rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to,
|
|||
}
|
||||
|
||||
/* decrypt */
|
||||
static int rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
|
||||
static int
|
||||
rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)
|
||||
{
|
||||
/* I haven't been able to trigger this one, but I want to know if it happens... */
|
||||
assert(0);
|
||||
|
|
@ -269,30 +299,39 @@ static int rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to,
|
|||
}
|
||||
|
||||
/* called at RSA_new */
|
||||
static int init(RSA *rsa)
|
||||
static int
|
||||
init(RSA *rsa)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* called at RSA_free */
|
||||
static int finish(RSA *rsa)
|
||||
static int
|
||||
finish(RSA *rsa)
|
||||
{
|
||||
CAPI_DATA *cd = (CAPI_DATA *) rsa->meth->app_data;
|
||||
|
||||
if (cd == NULL)
|
||||
return 0;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (cd->crypt_prov && cd->free_crypt_prov)
|
||||
CryptReleaseContext(cd->crypt_prov, 0);
|
||||
{
|
||||
CryptReleaseContext(cd->crypt_prov, 0);
|
||||
}
|
||||
if (cd->cert_context)
|
||||
CertFreeCertificateContext(cd->cert_context);
|
||||
{
|
||||
CertFreeCertificateContext(cd->cert_context);
|
||||
}
|
||||
free(rsa->meth->app_data);
|
||||
free((char *) rsa->meth);
|
||||
rsa->meth = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const CERT_CONTEXT *find_certificate_in_store(const char *cert_prop, HCERTSTORE cert_store)
|
||||
static const CERT_CONTEXT *
|
||||
find_certificate_in_store(const char *cert_prop, HCERTSTORE cert_store)
|
||||
{
|
||||
/* Find, and use, the desired certificate from the store. The
|
||||
* 'cert_prop' certificate search string can look like this:
|
||||
|
|
@ -302,50 +341,68 @@ static const CERT_CONTEXT *find_certificate_in_store(const char *cert_prop, HCER
|
|||
*/
|
||||
const CERT_CONTEXT *rv = NULL;
|
||||
|
||||
if (!strncmp(cert_prop, "SUBJ:", 5)) {
|
||||
/* skip the tag */
|
||||
cert_prop += 5;
|
||||
rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
0, CERT_FIND_SUBJECT_STR_A, cert_prop, NULL);
|
||||
if (!strncmp(cert_prop, "SUBJ:", 5))
|
||||
{
|
||||
/* skip the tag */
|
||||
cert_prop += 5;
|
||||
rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
0, CERT_FIND_SUBJECT_STR_A, cert_prop, NULL);
|
||||
|
||||
} else if (!strncmp(cert_prop, "THUMB:", 6)) {
|
||||
unsigned char hash[255];
|
||||
char *p;
|
||||
int i, x = 0;
|
||||
CRYPT_HASH_BLOB blob;
|
||||
}
|
||||
else if (!strncmp(cert_prop, "THUMB:", 6))
|
||||
{
|
||||
unsigned char hash[255];
|
||||
char *p;
|
||||
int i, x = 0;
|
||||
CRYPT_HASH_BLOB blob;
|
||||
|
||||
/* skip the tag */
|
||||
cert_prop += 6;
|
||||
for (p = (char *) cert_prop, i = 0; *p && i < sizeof(hash); i++) {
|
||||
if (*p >= '0' && *p <= '9')
|
||||
x = (*p - '0') << 4;
|
||||
else if (*p >= 'A' && *p <= 'F')
|
||||
x = (*p - 'A' + 10) << 4;
|
||||
else if (*p >= 'a' && *p <= 'f')
|
||||
x = (*p - 'a' + 10) << 4;
|
||||
if (!*++p) /* unexpected end of string */
|
||||
break;
|
||||
if (*p >= '0' && *p <= '9')
|
||||
x += *p - '0';
|
||||
else if (*p >= 'A' && *p <= 'F')
|
||||
x += *p - 'A' + 10;
|
||||
else if (*p >= 'a' && *p <= 'f')
|
||||
x += *p - 'a' + 10;
|
||||
hash[i] = x;
|
||||
/* skip any space(s) between hex numbers */
|
||||
for (p++; *p && *p == ' '; p++);
|
||||
}
|
||||
blob.cbData = i;
|
||||
blob.pbData = (unsigned char *) &hash;
|
||||
rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
0, CERT_FIND_HASH, &blob, NULL);
|
||||
/* skip the tag */
|
||||
cert_prop += 6;
|
||||
for (p = (char *) cert_prop, i = 0; *p && i < sizeof(hash); i++) {
|
||||
if (*p >= '0' && *p <= '9')
|
||||
{
|
||||
x = (*p - '0') << 4;
|
||||
}
|
||||
else if (*p >= 'A' && *p <= 'F')
|
||||
{
|
||||
x = (*p - 'A' + 10) << 4;
|
||||
}
|
||||
else if (*p >= 'a' && *p <= 'f')
|
||||
{
|
||||
x = (*p - 'a' + 10) << 4;
|
||||
}
|
||||
if (!*++p) /* unexpected end of string */
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (*p >= '0' && *p <= '9')
|
||||
{
|
||||
x += *p - '0';
|
||||
}
|
||||
else if (*p >= 'A' && *p <= 'F')
|
||||
{
|
||||
x += *p - 'A' + 10;
|
||||
}
|
||||
else if (*p >= 'a' && *p <= 'f')
|
||||
{
|
||||
x += *p - 'a' + 10;
|
||||
}
|
||||
hash[i] = x;
|
||||
/* skip any space(s) between hex numbers */
|
||||
for (p++; *p && *p == ' '; p++) ;
|
||||
}
|
||||
blob.cbData = i;
|
||||
blob.pbData = (unsigned char *) &hash;
|
||||
rv = CertFindCertificateInStore(cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
|
||||
0, CERT_FIND_HASH, &blob, NULL);
|
||||
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
|
||||
int
|
||||
SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
|
||||
{
|
||||
HCERTSTORE cs;
|
||||
X509 *cert = NULL;
|
||||
|
|
@ -353,50 +410,57 @@ int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
|
|||
CAPI_DATA *cd = calloc(1, sizeof(*cd));
|
||||
RSA_METHOD *my_rsa_method = calloc(1, sizeof(*my_rsa_method));
|
||||
|
||||
if (cd == NULL || my_rsa_method == NULL) {
|
||||
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
if (cd == NULL || my_rsa_method == NULL)
|
||||
{
|
||||
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
/* search CURRENT_USER first, then LOCAL_MACHINE */
|
||||
cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER |
|
||||
CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY");
|
||||
if (cs == NULL) {
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE);
|
||||
goto err;
|
||||
cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER
|
||||
|CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY");
|
||||
if (cs == NULL)
|
||||
{
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE);
|
||||
goto err;
|
||||
}
|
||||
cd->cert_context = find_certificate_in_store(cert_prop, cs);
|
||||
CertCloseStore(cs, 0);
|
||||
if (!cd->cert_context) {
|
||||
cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE |
|
||||
CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY");
|
||||
if (cs == NULL) {
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE);
|
||||
goto err;
|
||||
}
|
||||
cd->cert_context = find_certificate_in_store(cert_prop, cs);
|
||||
CertCloseStore(cs, 0);
|
||||
if (cd->cert_context == NULL) {
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE);
|
||||
goto err;
|
||||
}
|
||||
if (!cd->cert_context)
|
||||
{
|
||||
cs = CertOpenStore((LPCSTR) CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE
|
||||
|CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, L"MY");
|
||||
if (cs == NULL)
|
||||
{
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CERT_OPEN_SYSTEM_STORE);
|
||||
goto err;
|
||||
}
|
||||
cd->cert_context = find_certificate_in_store(cert_prop, cs);
|
||||
CertCloseStore(cs, 0);
|
||||
if (cd->cert_context == NULL)
|
||||
{
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CERT_FIND_CERTIFICATE_IN_STORE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* cert_context->pbCertEncoded is the cert X509 DER encoded. */
|
||||
cert = d2i_X509(NULL, (const unsigned char **) &cd->cert_context->pbCertEncoded,
|
||||
cd->cert_context->cbCertEncoded);
|
||||
if (cert == NULL) {
|
||||
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
cd->cert_context->cbCertEncoded);
|
||||
if (cert == NULL)
|
||||
{
|
||||
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* set up stuff to use the private key */
|
||||
if (!CryptAcquireCertificatePrivateKey(cd->cert_context, CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
|
||||
NULL, &cd->crypt_prov, &cd->key_spec, &cd->free_crypt_prov)) {
|
||||
/* if we don't have a smart card reader here, and we try to access a
|
||||
* smart card certificate, we get:
|
||||
* "Error 1223: The operation was canceled by the user." */
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY);
|
||||
goto err;
|
||||
NULL, &cd->crypt_prov, &cd->key_spec, &cd->free_crypt_prov))
|
||||
{
|
||||
/* if we don't have a smart card reader here, and we try to access a
|
||||
* smart card certificate, we get:
|
||||
* "Error 1223: The operation was canceled by the user." */
|
||||
CRYPTOAPIerr(CRYPTOAPI_F_CRYPT_ACQUIRE_CERTIFICATE_PRIVATE_KEY);
|
||||
goto err;
|
||||
}
|
||||
/* here we don't need to do CryptGetUserKey() or anything; all necessary key
|
||||
* info is in cd->cert_context, and then, in cd->crypt_prov. */
|
||||
|
|
@ -412,15 +476,18 @@ int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
|
|||
my_rsa_method->app_data = (char *) cd;
|
||||
|
||||
rsa = RSA_new();
|
||||
if (rsa == NULL) {
|
||||
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
if (rsa == NULL)
|
||||
{
|
||||
SSLerr(SSL_F_SSL_CTX_USE_CERTIFICATE_FILE, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(),
|
||||
* so we do it here then... */
|
||||
if (!SSL_CTX_use_certificate(ssl_ctx, cert))
|
||||
goto err;
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
/* the public key */
|
||||
pub_rsa = cert->cert_info->key->pkey->pkey.rsa;
|
||||
/* SSL_CTX_use_certificate() increased the reference count in 'cert', so
|
||||
|
|
@ -433,36 +500,54 @@ int SSL_CTX_use_CryptoAPI_certificate(SSL_CTX *ssl_ctx, const char *cert_prop)
|
|||
rsa->n = BN_dup(pub_rsa->n);
|
||||
rsa->flags |= RSA_FLAG_EXT_PKEY;
|
||||
if (!RSA_set_method(rsa, my_rsa_method))
|
||||
goto err;
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!SSL_CTX_use_RSAPrivateKey(ssl_ctx, rsa))
|
||||
goto err;
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
/* SSL_CTX_use_RSAPrivateKey() increased the reference count in 'rsa', so
|
||||
* we decrease it here with RSA_free(), or it will never be cleaned up. */
|
||||
* we decrease it here with RSA_free(), or it will never be cleaned up. */
|
||||
RSA_free(rsa);
|
||||
return 1;
|
||||
|
||||
err:
|
||||
err:
|
||||
if (cert)
|
||||
X509_free(cert);
|
||||
{
|
||||
X509_free(cert);
|
||||
}
|
||||
if (rsa)
|
||||
RSA_free(rsa);
|
||||
else {
|
||||
if (my_rsa_method)
|
||||
free(my_rsa_method);
|
||||
if (cd) {
|
||||
if (cd->free_crypt_prov && cd->crypt_prov)
|
||||
CryptReleaseContext(cd->crypt_prov, 0);
|
||||
if (cd->cert_context)
|
||||
CertFreeCertificateContext(cd->cert_context);
|
||||
free(cd);
|
||||
}
|
||||
{
|
||||
RSA_free(rsa);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (my_rsa_method)
|
||||
{
|
||||
free(my_rsa_method);
|
||||
}
|
||||
if (cd)
|
||||
{
|
||||
if (cd->free_crypt_prov && cd->crypt_prov)
|
||||
{
|
||||
CryptReleaseContext(cd->crypt_prov, 0);
|
||||
}
|
||||
if (cd->cert_context)
|
||||
{
|
||||
CertFreeCertificateContext(cd->cert_context);
|
||||
}
|
||||
free(cd);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* ifdef ENABLE_CRYPTOAPI */
|
||||
#ifdef _MSC_VER /* Dummy function needed to avoid empty file compiler warning in Microsoft VC */
|
||||
static void dummy (void) {}
|
||||
static void
|
||||
dummy(void) {
|
||||
}
|
||||
#endif
|
||||
#endif /* _WIN32 */
|
||||
#endif /* _WIN32 */
|
||||
|
|
|
|||
|
|
@ -37,176 +37,193 @@
|
|||
#include "memdbg.h"
|
||||
|
||||
static int
|
||||
get_dhcp_message_type (const struct dhcp *dhcp, const int optlen)
|
||||
get_dhcp_message_type(const struct dhcp *dhcp, const int optlen)
|
||||
{
|
||||
const uint8_t *p = (uint8_t *) (dhcp + 1);
|
||||
int i;
|
||||
const uint8_t *p = (uint8_t *) (dhcp + 1);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < optlen; ++i)
|
||||
for (i = 0; i < optlen; ++i)
|
||||
{
|
||||
const uint8_t type = p[i];
|
||||
const int room = optlen - i;
|
||||
if (type == DHCP_END) /* didn't find what we were looking for */
|
||||
return -1;
|
||||
else if (type == DHCP_PAD) /* no-operation */
|
||||
;
|
||||
else if (type == DHCP_MSG_TYPE) /* what we are looking for */
|
||||
{
|
||||
if (room >= 3)
|
||||
{
|
||||
if (p[i+1] == 1) /* option length should be 1 */
|
||||
return p[i+2]; /* return message type */
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else /* some other option */
|
||||
{
|
||||
if (room >= 2)
|
||||
{
|
||||
const int len = p[i+1]; /* get option length */
|
||||
i += (len + 1); /* advance to next option */
|
||||
}
|
||||
}
|
||||
const uint8_t type = p[i];
|
||||
const int room = optlen - i;
|
||||
if (type == DHCP_END) /* didn't find what we were looking for */
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (type == DHCP_PAD) /* no-operation */
|
||||
{
|
||||
}
|
||||
else if (type == DHCP_MSG_TYPE) /* what we are looking for */
|
||||
{
|
||||
if (room >= 3)
|
||||
{
|
||||
if (p[i+1] == 1) /* option length should be 1 */
|
||||
{
|
||||
return p[i+2]; /* return message type */
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else /* some other option */
|
||||
{
|
||||
if (room >= 2)
|
||||
{
|
||||
const int len = p[i+1]; /* get option length */
|
||||
i += (len + 1); /* advance to next option */
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static in_addr_t
|
||||
do_extract (struct dhcp *dhcp, int optlen)
|
||||
do_extract(struct dhcp *dhcp, int optlen)
|
||||
{
|
||||
uint8_t *p = (uint8_t *) (dhcp + 1);
|
||||
int i;
|
||||
in_addr_t ret = 0;
|
||||
uint8_t *p = (uint8_t *) (dhcp + 1);
|
||||
int i;
|
||||
in_addr_t ret = 0;
|
||||
|
||||
for (i = 0; i < optlen; )
|
||||
for (i = 0; i < optlen; )
|
||||
{
|
||||
const uint8_t type = p[i];
|
||||
const int room = optlen - i;
|
||||
if (type == DHCP_END)
|
||||
break;
|
||||
else if (type == DHCP_PAD)
|
||||
++i;
|
||||
else if (type == DHCP_ROUTER)
|
||||
{
|
||||
if (room >= 2)
|
||||
{
|
||||
const int len = p[i+1]; /* get option length */
|
||||
if (len <= (room-2))
|
||||
{
|
||||
/* get router IP address */
|
||||
if (!ret && len >= 4 && (len & 3) == 0)
|
||||
{
|
||||
memcpy (&ret, p+i+2, 4);
|
||||
ret = ntohl (ret);
|
||||
}
|
||||
{
|
||||
/* delete the router option */
|
||||
uint8_t *dest = p + i;
|
||||
const int owlen = len + 2; /* len of data to overwrite */
|
||||
uint8_t *src = dest + owlen;
|
||||
uint8_t *end = p + optlen;
|
||||
const int movlen = end - src;
|
||||
if (movlen > 0)
|
||||
memmove(dest, src, movlen); /* overwrite router option */
|
||||
memset(end - owlen, DHCP_PAD, owlen); /* pad tail */
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else /* some other option */
|
||||
{
|
||||
if (room >= 2)
|
||||
{
|
||||
const int len = p[i+1]; /* get option length */
|
||||
i += (len + 2); /* advance to next option */
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
const uint8_t type = p[i];
|
||||
const int room = optlen - i;
|
||||
if (type == DHCP_END)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (type == DHCP_PAD)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
else if (type == DHCP_ROUTER)
|
||||
{
|
||||
if (room >= 2)
|
||||
{
|
||||
const int len = p[i+1]; /* get option length */
|
||||
if (len <= (room-2))
|
||||
{
|
||||
/* get router IP address */
|
||||
if (!ret && len >= 4 && (len & 3) == 0)
|
||||
{
|
||||
memcpy(&ret, p+i+2, 4);
|
||||
ret = ntohl(ret);
|
||||
}
|
||||
{
|
||||
/* delete the router option */
|
||||
uint8_t *dest = p + i;
|
||||
const int owlen = len + 2; /* len of data to overwrite */
|
||||
uint8_t *src = dest + owlen;
|
||||
uint8_t *end = p + optlen;
|
||||
const int movlen = end - src;
|
||||
if (movlen > 0)
|
||||
{
|
||||
memmove(dest, src, movlen); /* overwrite router option */
|
||||
}
|
||||
memset(end - owlen, DHCP_PAD, owlen); /* pad tail */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* some other option */
|
||||
{
|
||||
if (room >= 2)
|
||||
{
|
||||
const int len = p[i+1]; /* get option length */
|
||||
i += (len + 2); /* advance to next option */
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
udp_checksum (const uint8_t *buf,
|
||||
const int len_udp,
|
||||
const uint8_t *src_addr,
|
||||
const uint8_t *dest_addr)
|
||||
udp_checksum(const uint8_t *buf,
|
||||
const int len_udp,
|
||||
const uint8_t *src_addr,
|
||||
const uint8_t *dest_addr)
|
||||
{
|
||||
uint16_t word16;
|
||||
uint32_t sum = 0;
|
||||
int i;
|
||||
|
||||
/* make 16 bit words out of every two adjacent 8 bit words and */
|
||||
/* calculate the sum of all 16 bit words */
|
||||
for (i = 0; i < len_udp; i += 2){
|
||||
word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_udp) ? (buf[i+1] & 0xFF) : 0);
|
||||
sum += word16;
|
||||
}
|
||||
uint16_t word16;
|
||||
uint32_t sum = 0;
|
||||
int i;
|
||||
|
||||
/* add the UDP pseudo header which contains the IP source and destination addresses */
|
||||
for (i = 0; i < 4; i += 2){
|
||||
word16 =((src_addr[i] << 8) & 0xFF00) + (src_addr[i+1] & 0xFF);
|
||||
sum += word16;
|
||||
}
|
||||
for (i = 0; i < 4; i += 2){
|
||||
word16 =((dest_addr[i] << 8) & 0xFF00) + (dest_addr[i+1] & 0xFF);
|
||||
sum += word16;
|
||||
}
|
||||
/* make 16 bit words out of every two adjacent 8 bit words and */
|
||||
/* calculate the sum of all 16 bit words */
|
||||
for (i = 0; i < len_udp; i += 2) {
|
||||
word16 = ((buf[i] << 8) & 0xFF00) + ((i + 1 < len_udp) ? (buf[i+1] & 0xFF) : 0);
|
||||
sum += word16;
|
||||
}
|
||||
|
||||
/* the protocol number and the length of the UDP packet */
|
||||
sum += (uint16_t) OPENVPN_IPPROTO_UDP + (uint16_t) len_udp;
|
||||
/* add the UDP pseudo header which contains the IP source and destination addresses */
|
||||
for (i = 0; i < 4; i += 2) {
|
||||
word16 = ((src_addr[i] << 8) & 0xFF00) + (src_addr[i+1] & 0xFF);
|
||||
sum += word16;
|
||||
}
|
||||
for (i = 0; i < 4; i += 2) {
|
||||
word16 = ((dest_addr[i] << 8) & 0xFF00) + (dest_addr[i+1] & 0xFF);
|
||||
sum += word16;
|
||||
}
|
||||
|
||||
/* keep only the last 16 bits of the 32 bit calculated sum and add the carries */
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
|
||||
/* Take the one's complement of sum */
|
||||
return ((uint16_t) ~sum);
|
||||
/* the protocol number and the length of the UDP packet */
|
||||
sum += (uint16_t) OPENVPN_IPPROTO_UDP + (uint16_t) len_udp;
|
||||
|
||||
/* keep only the last 16 bits of the 32 bit calculated sum and add the carries */
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
|
||||
/* Take the one's complement of sum */
|
||||
return ((uint16_t) ~sum);
|
||||
}
|
||||
|
||||
in_addr_t
|
||||
dhcp_extract_router_msg (struct buffer *ipbuf)
|
||||
dhcp_extract_router_msg(struct buffer *ipbuf)
|
||||
{
|
||||
struct dhcp_full *df = (struct dhcp_full *) BPTR (ipbuf);
|
||||
const int optlen = BLEN (ipbuf) - (sizeof (struct openvpn_iphdr) + sizeof (struct openvpn_udphdr) + sizeof (struct dhcp));
|
||||
struct dhcp_full *df = (struct dhcp_full *) BPTR(ipbuf);
|
||||
const int optlen = BLEN(ipbuf) - (sizeof(struct openvpn_iphdr) + sizeof(struct openvpn_udphdr) + sizeof(struct dhcp));
|
||||
|
||||
if (optlen >= 0
|
||||
&& df->ip.protocol == OPENVPN_IPPROTO_UDP
|
||||
&& df->udp.source == htons (BOOTPS_PORT)
|
||||
&& df->udp.dest == htons (BOOTPC_PORT)
|
||||
&& df->dhcp.op == BOOTREPLY)
|
||||
if (optlen >= 0
|
||||
&& df->ip.protocol == OPENVPN_IPPROTO_UDP
|
||||
&& df->udp.source == htons(BOOTPS_PORT)
|
||||
&& df->udp.dest == htons(BOOTPC_PORT)
|
||||
&& df->dhcp.op == BOOTREPLY)
|
||||
{
|
||||
const int message_type = get_dhcp_message_type (&df->dhcp, optlen);
|
||||
if (message_type == DHCPACK || message_type == DHCPOFFER)
|
||||
{
|
||||
/* get the router IP address while padding out all DHCP router options */
|
||||
const in_addr_t ret = do_extract (&df->dhcp, optlen);
|
||||
const int message_type = get_dhcp_message_type(&df->dhcp, optlen);
|
||||
if (message_type == DHCPACK || message_type == DHCPOFFER)
|
||||
{
|
||||
/* get the router IP address while padding out all DHCP router options */
|
||||
const in_addr_t ret = do_extract(&df->dhcp, optlen);
|
||||
|
||||
/* recompute the UDP checksum */
|
||||
df->udp.check = 0;
|
||||
df->udp.check = htons (udp_checksum ((uint8_t *) &df->udp,
|
||||
sizeof (struct openvpn_udphdr) + sizeof (struct dhcp) + optlen,
|
||||
(uint8_t *)&df->ip.saddr,
|
||||
(uint8_t *)&df->ip.daddr));
|
||||
/* recompute the UDP checksum */
|
||||
df->udp.check = 0;
|
||||
df->udp.check = htons(udp_checksum((uint8_t *) &df->udp,
|
||||
sizeof(struct openvpn_udphdr) + sizeof(struct dhcp) + optlen,
|
||||
(uint8_t *)&df->ip.saddr,
|
||||
(uint8_t *)&df->ip.daddr));
|
||||
|
||||
/* only return the extracted Router address if DHCPACK */
|
||||
if (message_type == DHCPACK)
|
||||
{
|
||||
if (ret)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
msg (D_ROUTE, "Extracted DHCP router address: %s", print_in_addr_t (ret, 0, &gc));
|
||||
gc_free (&gc);
|
||||
}
|
||||
/* only return the extracted Router address if DHCPACK */
|
||||
if (message_type == DHCPACK)
|
||||
{
|
||||
if (ret)
|
||||
{
|
||||
struct gc_arena gc = gc_new();
|
||||
msg(D_ROUTE, "Extracted DHCP router address: %s", print_in_addr_t(ret, 0, &gc));
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,36 +52,36 @@
|
|||
#define BOOTPC_PORT 68
|
||||
|
||||
struct dhcp {
|
||||
# define BOOTREQUEST 1
|
||||
# define BOOTREPLY 2
|
||||
uint8_t op; /* message op */
|
||||
#define BOOTREQUEST 1
|
||||
#define BOOTREPLY 2
|
||||
uint8_t op; /* message op */
|
||||
|
||||
uint8_t htype; /* hardware address type (e.g. '1' = 10Mb Ethernet) */
|
||||
uint8_t hlen; /* hardware address length (e.g. '6' for 10Mb Ethernet) */
|
||||
uint8_t hops; /* client sets to 0, may be used by relay agents */
|
||||
uint32_t xid; /* transaction ID, chosen by client */
|
||||
uint16_t secs; /* seconds since request process began, set by client */
|
||||
uint16_t flags;
|
||||
uint32_t ciaddr; /* client IP address, client sets if known */
|
||||
uint32_t yiaddr; /* 'your' IP address -- server's response to client */
|
||||
uint32_t siaddr; /* server IP address */
|
||||
uint32_t giaddr; /* relay agent IP address */
|
||||
uint8_t chaddr[16]; /* client hardware address */
|
||||
uint8_t sname[64]; /* optional server host name */
|
||||
uint8_t file[128]; /* boot file name */
|
||||
uint32_t magic; /* must be 0x63825363 (network order) */
|
||||
uint8_t htype; /* hardware address type (e.g. '1' = 10Mb Ethernet) */
|
||||
uint8_t hlen; /* hardware address length (e.g. '6' for 10Mb Ethernet) */
|
||||
uint8_t hops; /* client sets to 0, may be used by relay agents */
|
||||
uint32_t xid; /* transaction ID, chosen by client */
|
||||
uint16_t secs; /* seconds since request process began, set by client */
|
||||
uint16_t flags;
|
||||
uint32_t ciaddr; /* client IP address, client sets if known */
|
||||
uint32_t yiaddr; /* 'your' IP address -- server's response to client */
|
||||
uint32_t siaddr; /* server IP address */
|
||||
uint32_t giaddr; /* relay agent IP address */
|
||||
uint8_t chaddr[16]; /* client hardware address */
|
||||
uint8_t sname[64]; /* optional server host name */
|
||||
uint8_t file[128]; /* boot file name */
|
||||
uint32_t magic; /* must be 0x63825363 (network order) */
|
||||
};
|
||||
|
||||
struct dhcp_full {
|
||||
struct openvpn_iphdr ip;
|
||||
struct openvpn_udphdr udp;
|
||||
struct dhcp dhcp;
|
||||
# define DHCP_OPTIONS_BUFFER_SIZE 256
|
||||
uint8_t options[DHCP_OPTIONS_BUFFER_SIZE];
|
||||
struct openvpn_iphdr ip;
|
||||
struct openvpn_udphdr udp;
|
||||
struct dhcp dhcp;
|
||||
#define DHCP_OPTIONS_BUFFER_SIZE 256
|
||||
uint8_t options[DHCP_OPTIONS_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
in_addr_t dhcp_extract_router_msg (struct buffer *ipbuf);
|
||||
in_addr_t dhcp_extract_router_msg(struct buffer *ipbuf);
|
||||
|
||||
#endif
|
||||
#endif /* ifndef DHCP_H */
|
||||
|
|
|
|||
|
|
@ -176,4 +176,4 @@
|
|||
|
||||
/*#define D_THREAD_DEBUG LOGLEV(4, 70, M_DEBUG)*/ /* show pthread debug information */
|
||||
|
||||
#endif
|
||||
#endif /* ifndef ERRLEVEL_H */
|
||||
|
|
|
|||
1172
src/openvpn/error.c
1172
src/openvpn/error.c
File diff suppressed because it is too large
Load diff
|
|
@ -72,12 +72,13 @@ struct gc_arena;
|
|||
/* String and Error functions */
|
||||
|
||||
#ifdef _WIN32
|
||||
# define openvpn_errno() GetLastError()
|
||||
# define openvpn_strerror(e, gc) strerror_win32(e, gc)
|
||||
const char *strerror_win32 (DWORD errnum, struct gc_arena *gc);
|
||||
#define openvpn_errno() GetLastError()
|
||||
#define openvpn_strerror(e, gc) strerror_win32(e, gc)
|
||||
const char *strerror_win32(DWORD errnum, struct gc_arena *gc);
|
||||
|
||||
#else
|
||||
# define openvpn_errno() errno
|
||||
# define openvpn_strerror(x, gc) strerror(x)
|
||||
#define openvpn_errno() errno
|
||||
#define openvpn_strerror(x, gc) strerror(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -89,14 +90,14 @@ extern int x_msg_line_num;
|
|||
|
||||
/* msg() flags */
|
||||
|
||||
#define M_DEBUG_LEVEL (0x0F) /* debug level mask */
|
||||
#define M_DEBUG_LEVEL (0x0F) /* debug level mask */
|
||||
|
||||
#define M_FATAL (1<<4) /* exit program */
|
||||
#define M_NONFATAL (1<<5) /* non-fatal error */
|
||||
#define M_WARN (1<<6) /* call syslog with LOG_WARNING */
|
||||
#define M_FATAL (1<<4) /* exit program */
|
||||
#define M_NONFATAL (1<<5) /* non-fatal error */
|
||||
#define M_WARN (1<<6) /* call syslog with LOG_WARNING */
|
||||
#define M_DEBUG (1<<7)
|
||||
|
||||
#define M_ERRNO (1<<8) /* show errno description */
|
||||
#define M_ERRNO (1<<8) /* show errno description */
|
||||
|
||||
#define M_NOMUTE (1<<11) /* don't do mute processing */
|
||||
#define M_NOPREFIX (1<<12) /* don't show date/time prefix */
|
||||
|
|
@ -141,73 +142,75 @@ extern int x_msg_line_num;
|
|||
*/
|
||||
|
||||
/** Check muting filter */
|
||||
bool dont_mute (unsigned int flags);
|
||||
bool dont_mute(unsigned int flags);
|
||||
|
||||
/* Macro to ensure (and teach static analysis tools) we exit on fatal errors */
|
||||
#define EXIT_FATAL(flags) do { if ((flags) & M_FATAL) _exit(1); } while (false)
|
||||
#define EXIT_FATAL(flags) do { if ((flags) & M_FATAL) {_exit(1);}} while (false)
|
||||
|
||||
#if defined(HAVE_CPP_VARARG_MACRO_ISO) && !defined(__LCLINT__)
|
||||
# define HAVE_VARARG_MACROS
|
||||
# define msg(flags, ...) do { if (msg_test(flags)) x_msg((flags), __VA_ARGS__); EXIT_FATAL(flags); } while (false)
|
||||
# ifdef ENABLE_DEBUG
|
||||
# define dmsg(flags, ...) do { if (msg_test(flags)) x_msg((flags), __VA_ARGS__); EXIT_FATAL(flags); } while (false)
|
||||
# else
|
||||
# define dmsg(flags, ...)
|
||||
# endif
|
||||
#elif defined(HAVE_CPP_VARARG_MACRO_GCC) && !defined(__LCLINT__)
|
||||
# define HAVE_VARARG_MACROS
|
||||
# define msg(flags, args...) do { if (msg_test(flags)) x_msg((flags), args); EXIT_FATAL(flags); } while (false)
|
||||
# ifdef ENABLE_DEBUG
|
||||
# define dmsg(flags, args...) do { if (msg_test(flags)) x_msg((flags), args); EXIT_FATAL(flags); } while (false)
|
||||
# else
|
||||
# define dmsg(flags, args...)
|
||||
# endif
|
||||
#define HAVE_VARARG_MACROS
|
||||
#define msg(flags, ...) do { if (msg_test(flags)) {x_msg((flags), __VA_ARGS__);} EXIT_FATAL(flags); } while (false)
|
||||
#ifdef ENABLE_DEBUG
|
||||
#define dmsg(flags, ...) do { if (msg_test(flags)) {x_msg((flags), __VA_ARGS__);} EXIT_FATAL(flags); } while (false)
|
||||
#else
|
||||
# if !PEDANTIC
|
||||
# ifdef _MSC_VER
|
||||
# pragma message("this compiler appears to lack vararg macros which will cause a significant degradation in efficiency")
|
||||
# else
|
||||
# warning this compiler appears to lack vararg macros which will cause a significant degradation in efficiency (you can ignore this warning if you are using LCLINT)
|
||||
# endif
|
||||
# endif
|
||||
# define msg x_msg
|
||||
# define dmsg x_msg
|
||||
#define dmsg(flags, ...)
|
||||
#endif
|
||||
#elif defined(HAVE_CPP_VARARG_MACRO_GCC) && !defined(__LCLINT__)
|
||||
#define HAVE_VARARG_MACROS
|
||||
#define msg(flags, args ...) do { if (msg_test(flags)) {x_msg((flags), args);} EXIT_FATAL(flags); } while (false)
|
||||
#ifdef ENABLE_DEBUG
|
||||
#define dmsg(flags, args ...) do { if (msg_test(flags)) {x_msg((flags), args);} EXIT_FATAL(flags); } while (false)
|
||||
#else
|
||||
#define dmsg(flags, args ...)
|
||||
#endif
|
||||
#else /* if defined(HAVE_CPP_VARARG_MACRO_ISO) && !defined(__LCLINT__) */
|
||||
#if !PEDANTIC
|
||||
#ifdef _MSC_VER
|
||||
#pragma message("this compiler appears to lack vararg macros which will cause a significant degradation in efficiency")
|
||||
#else
|
||||
#warning this compiler appears to lack vararg macros which will cause a significant degradation in efficiency (you can ignore this warning if you are using LCLINT)
|
||||
#endif
|
||||
#endif
|
||||
#define msg x_msg
|
||||
#define dmsg x_msg
|
||||
#endif /* if defined(HAVE_CPP_VARARG_MACRO_ISO) && !defined(__LCLINT__) */
|
||||
|
||||
void x_msg (const unsigned int flags, const char *format, ...)
|
||||
void x_msg(const unsigned int flags, const char *format, ...)
|
||||
#ifdef __GNUC__
|
||||
#if __USE_MINGW_ANSI_STDIO
|
||||
__attribute__ ((format (gnu_printf, 2, 3)))
|
||||
__attribute__ ((format(gnu_printf, 2, 3)))
|
||||
#else
|
||||
__attribute__ ((format (__printf__, 2, 3)))
|
||||
__attribute__ ((format(__printf__, 2, 3)))
|
||||
#endif
|
||||
#endif
|
||||
; /* should be called via msg above */
|
||||
; /* should be called via msg above */
|
||||
|
||||
void x_msg_va (const unsigned int flags, const char *format, va_list arglist);
|
||||
void x_msg_va(const unsigned int flags, const char *format, va_list arglist);
|
||||
|
||||
/*
|
||||
* Function prototypes
|
||||
*/
|
||||
|
||||
void error_reset (void);
|
||||
void error_reset(void);
|
||||
|
||||
/* route errors to stderr that would normally go to stdout */
|
||||
void errors_to_stderr (void);
|
||||
void errors_to_stderr(void);
|
||||
|
||||
void set_suppress_timestamps (bool suppressed);
|
||||
void set_machine_readable_output (bool parsable);
|
||||
void set_suppress_timestamps(bool suppressed);
|
||||
|
||||
void set_machine_readable_output(bool parsable);
|
||||
|
||||
|
||||
#define SDL_CONSTRAIN (1<<0)
|
||||
bool set_debug_level (const int level, const unsigned int flags);
|
||||
bool set_debug_level(const int level, const unsigned int flags);
|
||||
|
||||
bool set_mute_cutoff (const int cutoff);
|
||||
bool set_mute_cutoff(const int cutoff);
|
||||
|
||||
int get_debug_level (void);
|
||||
int get_mute_cutoff (void);
|
||||
int get_debug_level(void);
|
||||
|
||||
const char *msg_flags_string (const unsigned int flags, struct gc_arena *gc);
|
||||
int get_mute_cutoff(void);
|
||||
|
||||
const char *msg_flags_string(const unsigned int flags, struct gc_arena *gc);
|
||||
|
||||
/*
|
||||
* File to print messages to before syslog is opened.
|
||||
|
|
@ -216,61 +219,65 @@ FILE *msg_fp(const unsigned int flags);
|
|||
|
||||
/* Fatal logic errors */
|
||||
#ifndef ENABLE_SMALL
|
||||
#define ASSERT(x) do { if (!(x)) assert_failed(__FILE__, __LINE__, #x); } while (false)
|
||||
#define ASSERT(x) do { if (!(x)) {assert_failed(__FILE__, __LINE__, #x);}} while (false)
|
||||
#else
|
||||
#define ASSERT(x) do { if (!(x)) assert_failed(__FILE__, __LINE__, NULL); } while (false)
|
||||
#define ASSERT(x) do { if (!(x)) {assert_failed(__FILE__, __LINE__, NULL);}} while (false)
|
||||
#endif
|
||||
|
||||
void assert_failed (const char *filename, int line, const char *condition)
|
||||
__attribute__((__noreturn__));
|
||||
void assert_failed(const char *filename, int line, const char *condition)
|
||||
__attribute__((__noreturn__));
|
||||
|
||||
/* Poor-man's static_assert() for when not supplied by assert.h, taken from
|
||||
* Linux's sys/cdefs.h under GPLv2 */
|
||||
#ifndef static_assert
|
||||
#define static_assert(expr, diagnostic) \
|
||||
extern int (*__OpenVPN_static_assert_function (void)) \
|
||||
[!!sizeof (struct { int __error_if_negative: (expr) ? 2 : -1; })]
|
||||
extern int (*__OpenVPN_static_assert_function(void)) \
|
||||
[!!sizeof(struct { int __error_if_negative : (expr) ? 2 : -1; })]
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
void crash (void); /* force a segfault (debugging only) */
|
||||
void crash(void); /* force a segfault (debugging only) */
|
||||
|
||||
#endif
|
||||
|
||||
/* Inline functions */
|
||||
|
||||
static inline bool
|
||||
check_debug_level (unsigned int level)
|
||||
check_debug_level(unsigned int level)
|
||||
{
|
||||
return (level & M_DEBUG_LEVEL) <= x_debug_level;
|
||||
return (level & M_DEBUG_LEVEL) <= x_debug_level;
|
||||
}
|
||||
|
||||
/** Return true if flags represent an enabled, not muted log level */
|
||||
static inline bool msg_test (unsigned int flags)
|
||||
static inline bool
|
||||
msg_test(unsigned int flags)
|
||||
{
|
||||
return check_debug_level (flags) && dont_mute (flags);
|
||||
return check_debug_level(flags) && dont_mute(flags);
|
||||
}
|
||||
|
||||
/* Call if we forked */
|
||||
void msg_forked (void);
|
||||
void msg_forked(void);
|
||||
|
||||
/* syslog output */
|
||||
|
||||
void open_syslog (const char *pgmname, bool stdio_to_null);
|
||||
void close_syslog ();
|
||||
void open_syslog(const char *pgmname, bool stdio_to_null);
|
||||
|
||||
void close_syslog();
|
||||
|
||||
/* log file output */
|
||||
void redirect_stdout_stderr (const char *file, bool append);
|
||||
void redirect_stdout_stderr(const char *file, bool append);
|
||||
|
||||
#ifdef _WIN32
|
||||
/* get original stderr handle, even if redirected by --log/--log-append */
|
||||
HANDLE get_orig_stderr (void);
|
||||
HANDLE get_orig_stderr(void);
|
||||
|
||||
#endif
|
||||
|
||||
/* exit program */
|
||||
void openvpn_exit (const int status);
|
||||
void openvpn_exit(const int status);
|
||||
|
||||
/* exit program on out of memory error */
|
||||
void out_of_memory (void);
|
||||
void out_of_memory(void);
|
||||
|
||||
/*
|
||||
* Check the return status of read/write routines.
|
||||
|
|
@ -283,25 +290,28 @@ extern unsigned int x_cs_info_level;
|
|||
extern unsigned int x_cs_verbose_level;
|
||||
extern unsigned int x_cs_err_delay_ms;
|
||||
|
||||
void reset_check_status (void);
|
||||
void set_check_status (unsigned int info_level, unsigned int verbose_level);
|
||||
void reset_check_status(void);
|
||||
|
||||
void x_check_status (int status,
|
||||
const char *description,
|
||||
struct link_socket *sock,
|
||||
struct tuntap *tt);
|
||||
void set_check_status(unsigned int info_level, unsigned int verbose_level);
|
||||
|
||||
void x_check_status(int status,
|
||||
const char *description,
|
||||
struct link_socket *sock,
|
||||
struct tuntap *tt);
|
||||
|
||||
static inline void
|
||||
check_status (int status, const char *description, struct link_socket *sock, struct tuntap *tt)
|
||||
check_status(int status, const char *description, struct link_socket *sock, struct tuntap *tt)
|
||||
{
|
||||
if (status < 0 || check_debug_level (x_cs_verbose_level))
|
||||
x_check_status (status, description, sock, tt);
|
||||
if (status < 0 || check_debug_level(x_cs_verbose_level))
|
||||
{
|
||||
x_check_status(status, description, sock, tt);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_check_status_error_delay (unsigned int milliseconds)
|
||||
set_check_status_error_delay(unsigned int milliseconds)
|
||||
{
|
||||
x_cs_err_delay_ms = milliseconds;
|
||||
x_cs_err_delay_ms = milliseconds;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -313,17 +323,18 @@ set_check_status_error_delay (unsigned int milliseconds)
|
|||
|
||||
extern const char *x_msg_prefix;
|
||||
|
||||
void msg_thread_init (void);
|
||||
void msg_thread_uninit (void);
|
||||
void msg_thread_init(void);
|
||||
|
||||
void msg_thread_uninit(void);
|
||||
|
||||
static inline void
|
||||
msg_set_prefix (const char *prefix)
|
||||
msg_set_prefix(const char *prefix)
|
||||
{
|
||||
x_msg_prefix = prefix;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
msg_get_prefix (void)
|
||||
msg_get_prefix(void)
|
||||
{
|
||||
return x_msg_prefix;
|
||||
}
|
||||
|
|
@ -337,15 +348,15 @@ struct virtual_output;
|
|||
extern const struct virtual_output *x_msg_virtual_output;
|
||||
|
||||
static inline void
|
||||
msg_set_virtual_output (const struct virtual_output *vo)
|
||||
msg_set_virtual_output(const struct virtual_output *vo)
|
||||
{
|
||||
x_msg_virtual_output = vo;
|
||||
x_msg_virtual_output = vo;
|
||||
}
|
||||
|
||||
static inline const struct virtual_output *
|
||||
msg_get_virtual_output (void)
|
||||
msg_get_virtual_output(void)
|
||||
{
|
||||
return x_msg_virtual_output;
|
||||
return x_msg_virtual_output;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -353,34 +364,40 @@ msg_get_virtual_output (void)
|
|||
* which can be safely ignored.
|
||||
*/
|
||||
static inline bool
|
||||
ignore_sys_error (const int err)
|
||||
ignore_sys_error(const int err)
|
||||
{
|
||||
/* I/O operation pending */
|
||||
/* I/O operation pending */
|
||||
#ifdef _WIN32
|
||||
if (err == WSAEWOULDBLOCK || err == WSAEINVAL)
|
||||
return true;
|
||||
if (err == WSAEWOULDBLOCK || err == WSAEINVAL)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (err == EAGAIN)
|
||||
return true;
|
||||
if (err == EAGAIN)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0 /* if enabled, suppress ENOBUFS errors */
|
||||
#ifdef ENOBUFS
|
||||
/* No buffer space available */
|
||||
if (err == ENOBUFS)
|
||||
return true;
|
||||
/* No buffer space available */
|
||||
if (err == ENOBUFS)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Convert fatal errors to nonfatal, don't touch other errors */
|
||||
static inline unsigned int
|
||||
nonfatal(const unsigned int err) {
|
||||
return err & M_FATAL ? (err ^ M_FATAL) | M_NONFATAL : err;
|
||||
return err & M_FATAL ? (err ^ M_FATAL) | M_NONFATAL : err;
|
||||
}
|
||||
|
||||
#include "errlevel.h"
|
||||
|
||||
#endif
|
||||
#endif /* ifndef ERROR_H */
|
||||
|
|
|
|||
1503
src/openvpn/event.c
1503
src/openvpn/event.c
File diff suppressed because it is too large
Load diff
|
|
@ -48,7 +48,7 @@ typedef const struct rw_handle *event_t;
|
|||
|
||||
#define UNDEFINED_EVENT (NULL)
|
||||
|
||||
#else
|
||||
#else /* ifdef _WIN32 */
|
||||
|
||||
typedef int event_t;
|
||||
|
||||
|
|
@ -61,29 +61,29 @@ struct event_set_return;
|
|||
|
||||
struct event_set_functions
|
||||
{
|
||||
void (*free)(struct event_set *es);
|
||||
void (*reset)(struct event_set *es);
|
||||
void (*del)(struct event_set *es, event_t event);
|
||||
void (*ctl)(struct event_set *es, event_t event, unsigned int rwflags, void *arg);
|
||||
void (*free)(struct event_set *es);
|
||||
void (*reset)(struct event_set *es);
|
||||
void (*del)(struct event_set *es, event_t event);
|
||||
void (*ctl)(struct event_set *es, event_t event, unsigned int rwflags, void *arg);
|
||||
|
||||
/*
|
||||
* Return status for wait:
|
||||
* -1 on signal or error
|
||||
* 0 on timeout
|
||||
* length of event_set_return if at least 1 event is returned
|
||||
*/
|
||||
int (*wait)(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen);
|
||||
/*
|
||||
* Return status for wait:
|
||||
* -1 on signal or error
|
||||
* 0 on timeout
|
||||
* length of event_set_return if at least 1 event is returned
|
||||
*/
|
||||
int (*wait)(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen);
|
||||
};
|
||||
|
||||
struct event_set_return
|
||||
{
|
||||
unsigned int rwflags;
|
||||
void *arg;
|
||||
unsigned int rwflags;
|
||||
void *arg;
|
||||
};
|
||||
|
||||
struct event_set
|
||||
{
|
||||
struct event_set_functions func;
|
||||
struct event_set_functions func;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -93,66 +93,70 @@ struct event_set
|
|||
* of underlying API
|
||||
* flags: EVENT_METHOD_x flags
|
||||
*/
|
||||
struct event_set *event_set_init (int *maxevents, unsigned int flags);
|
||||
struct event_set *event_set_init(int *maxevents, unsigned int flags);
|
||||
|
||||
static inline void
|
||||
event_free (struct event_set *es)
|
||||
event_free(struct event_set *es)
|
||||
{
|
||||
if (es)
|
||||
(*es->func.free)(es);
|
||||
if (es)
|
||||
{
|
||||
(*es->func.free)(es);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
event_reset (struct event_set *es)
|
||||
event_reset(struct event_set *es)
|
||||
{
|
||||
(*es->func.reset)(es);
|
||||
(*es->func.reset)(es);
|
||||
}
|
||||
|
||||
static inline void
|
||||
event_del (struct event_set *es, event_t event)
|
||||
event_del(struct event_set *es, event_t event)
|
||||
{
|
||||
(*es->func.del)(es, event);
|
||||
(*es->func.del)(es, event);
|
||||
}
|
||||
|
||||
static inline void
|
||||
event_ctl (struct event_set *es, event_t event, unsigned int rwflags, void *arg)
|
||||
event_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
|
||||
{
|
||||
(*es->func.ctl)(es, event, rwflags, arg);
|
||||
(*es->func.ctl)(es, event, rwflags, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
event_wait (struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
|
||||
event_wait(struct event_set *es, const struct timeval *tv, struct event_set_return *out, int outlen)
|
||||
{
|
||||
int ret;
|
||||
perf_push (PERF_IO_WAIT);
|
||||
ret = (*es->func.wait)(es, tv, out, outlen);
|
||||
perf_pop ();
|
||||
return ret;
|
||||
int ret;
|
||||
perf_push(PERF_IO_WAIT);
|
||||
ret = (*es->func.wait)(es, tv, out, outlen);
|
||||
perf_pop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
event_set_return_init (struct event_set_return *esr)
|
||||
event_set_return_init(struct event_set_return *esr)
|
||||
{
|
||||
esr->rwflags = 0;
|
||||
esr->arg = NULL;
|
||||
esr->rwflags = 0;
|
||||
esr->arg = NULL;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static inline void
|
||||
wait_signal (struct event_set *es, void *arg)
|
||||
wait_signal(struct event_set *es, void *arg)
|
||||
{
|
||||
if (HANDLE_DEFINED (win32_signal.in.read))
|
||||
event_ctl (es, &win32_signal.in, EVENT_READ, arg);
|
||||
if (HANDLE_DEFINED(win32_signal.in.read))
|
||||
{
|
||||
event_ctl(es, &win32_signal.in, EVENT_READ, arg);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* ifdef _WIN32 */
|
||||
|
||||
static inline void
|
||||
wait_signal (struct event_set *es, void *arg)
|
||||
wait_signal(struct event_set *es, void *arg)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* ifndef EVENT_H */
|
||||
|
|
|
|||
|
|
@ -37,42 +37,52 @@
|
|||
|
||||
/* Set a file descriptor to non-blocking */
|
||||
bool
|
||||
set_nonblock_action (int fd)
|
||||
set_nonblock_action(int fd)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
u_long arg = 1;
|
||||
if (ioctlsocket (fd, FIONBIO, &arg))
|
||||
return false;
|
||||
#else
|
||||
if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0)
|
||||
return false;
|
||||
u_long arg = 1;
|
||||
if (ioctlsocket(fd, FIONBIO, &arg))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else /* ifdef _WIN32 */
|
||||
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Set a file descriptor to not be passed across execs */
|
||||
bool
|
||||
set_cloexec_action (int fd)
|
||||
set_cloexec_action(int fd)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
if (fcntl (fd, F_SETFD, FD_CLOEXEC) < 0)
|
||||
return false;
|
||||
if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Set a file descriptor to non-blocking */
|
||||
void
|
||||
set_nonblock (int fd)
|
||||
set_nonblock(int fd)
|
||||
{
|
||||
if (!set_nonblock_action (fd))
|
||||
msg (M_ERR, "Set socket to non-blocking mode failed");
|
||||
if (!set_nonblock_action(fd))
|
||||
{
|
||||
msg(M_ERR, "Set socket to non-blocking mode failed");
|
||||
}
|
||||
}
|
||||
|
||||
/* Set a file descriptor to not be passed across execs */
|
||||
void
|
||||
set_cloexec (int fd)
|
||||
set_cloexec(int fd)
|
||||
{
|
||||
if (!set_cloexec_action (fd))
|
||||
msg (M_ERR, "Set FD_CLOEXEC flag on file descriptor failed");
|
||||
if (!set_cloexec_action(fd))
|
||||
{
|
||||
msg(M_ERR, "Set FD_CLOEXEC flag on file descriptor failed");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,18 +29,21 @@
|
|||
#include "error.h"
|
||||
#include "syshead.h"
|
||||
|
||||
bool set_nonblock_action (int fd);
|
||||
bool set_cloexec_action (int fd);
|
||||
bool set_nonblock_action(int fd);
|
||||
|
||||
void set_nonblock (int fd);
|
||||
void set_cloexec (int fd);
|
||||
bool set_cloexec_action(int fd);
|
||||
|
||||
static inline void openvpn_fd_set(int fd, fd_set *setp)
|
||||
void set_nonblock(int fd);
|
||||
|
||||
void set_cloexec(int fd);
|
||||
|
||||
static inline void
|
||||
openvpn_fd_set(int fd, fd_set *setp)
|
||||
{
|
||||
#ifndef _WIN32 /* The Windows FD_SET() implementation does not overflow */
|
||||
ASSERT (fd >= 0 && fd < FD_SETSIZE);
|
||||
ASSERT(fd >= 0 && fd < FD_SETSIZE);
|
||||
#endif
|
||||
FD_SET (fd, setp);
|
||||
FD_SET(fd, setp);
|
||||
}
|
||||
#undef FD_SET /* prevent direct use of FD_SET() */
|
||||
|
||||
|
|
|
|||
|
|
@ -33,12 +33,15 @@
|
|||
* Does TLS session need service?
|
||||
*/
|
||||
static inline void
|
||||
check_tls (struct context *c)
|
||||
check_tls(struct context *c)
|
||||
{
|
||||
#if defined(ENABLE_CRYPTO)
|
||||
void check_tls_dowork (struct context *c);
|
||||
if (c->c2.tls_multi)
|
||||
check_tls_dowork (c);
|
||||
void check_tls_dowork(struct context *c);
|
||||
|
||||
if (c->c2.tls_multi)
|
||||
{
|
||||
check_tls_dowork(c);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -47,25 +50,31 @@ check_tls (struct context *c)
|
|||
* Also check for --tls-exit trigger.
|
||||
*/
|
||||
static inline void
|
||||
check_tls_errors (struct context *c)
|
||||
check_tls_errors(struct context *c)
|
||||
{
|
||||
#if defined(ENABLE_CRYPTO)
|
||||
void check_tls_errors_co (struct context *c);
|
||||
void check_tls_errors_nco (struct context *c);
|
||||
if (c->c2.tls_multi && c->c2.tls_exit_signal)
|
||||
void check_tls_errors_co(struct context *c);
|
||||
|
||||
void check_tls_errors_nco(struct context *c);
|
||||
|
||||
if (c->c2.tls_multi && c->c2.tls_exit_signal)
|
||||
{
|
||||
if (link_socket_connection_oriented (c->c2.link_socket))
|
||||
{
|
||||
if (c->c2.tls_multi->n_soft_errors)
|
||||
check_tls_errors_co (c);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c->c2.tls_multi->n_hard_errors)
|
||||
check_tls_errors_nco (c);
|
||||
}
|
||||
if (link_socket_connection_oriented(c->c2.link_socket))
|
||||
{
|
||||
if (c->c2.tls_multi->n_soft_errors)
|
||||
{
|
||||
check_tls_errors_co(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c->c2.tls_multi->n_hard_errors)
|
||||
{
|
||||
check_tls_errors_nco(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* if defined(ENABLE_CRYPTO) */
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -73,12 +82,15 @@ check_tls_errors (struct context *c)
|
|||
* messages on the control channel.
|
||||
*/
|
||||
static inline void
|
||||
check_incoming_control_channel (struct context *c)
|
||||
check_incoming_control_channel(struct context *c)
|
||||
{
|
||||
#if P2MP
|
||||
void check_incoming_control_channel_dowork (struct context *c);
|
||||
if (tls_test_payload_len (c->c2.tls_multi) > 0)
|
||||
check_incoming_control_channel_dowork (c);
|
||||
void check_incoming_control_channel_dowork(struct context *c);
|
||||
|
||||
if (tls_test_payload_len(c->c2.tls_multi) > 0)
|
||||
{
|
||||
check_incoming_control_channel_dowork(c);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -87,77 +99,91 @@ check_incoming_control_channel (struct context *c)
|
|||
* checks for connection establishment.
|
||||
*/
|
||||
static inline void
|
||||
check_connection_established (struct context *c)
|
||||
check_connection_established(struct context *c)
|
||||
{
|
||||
void check_connection_established_dowork (struct context *c);
|
||||
if (event_timeout_defined (&c->c2.wait_for_connect))
|
||||
check_connection_established_dowork (c);
|
||||
void check_connection_established_dowork(struct context *c);
|
||||
|
||||
if (event_timeout_defined(&c->c2.wait_for_connect))
|
||||
{
|
||||
check_connection_established_dowork(c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Should we add routes?
|
||||
*/
|
||||
static inline void
|
||||
check_add_routes (struct context *c)
|
||||
check_add_routes(struct context *c)
|
||||
{
|
||||
void check_add_routes_dowork (struct context *c);
|
||||
if (event_timeout_trigger (&c->c2.route_wakeup, &c->c2.timeval, ETT_DEFAULT))
|
||||
check_add_routes_dowork (c);
|
||||
void check_add_routes_dowork(struct context *c);
|
||||
|
||||
if (event_timeout_trigger(&c->c2.route_wakeup, &c->c2.timeval, ETT_DEFAULT))
|
||||
{
|
||||
check_add_routes_dowork(c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Should we exit due to inactivity timeout?
|
||||
*/
|
||||
static inline void
|
||||
check_inactivity_timeout (struct context *c)
|
||||
check_inactivity_timeout(struct context *c)
|
||||
{
|
||||
void check_inactivity_timeout_dowork (struct context *c);
|
||||
void check_inactivity_timeout_dowork(struct context *c);
|
||||
|
||||
if (c->options.inactivity_timeout
|
||||
&& event_timeout_trigger (&c->c2.inactivity_interval, &c->c2.timeval, ETT_DEFAULT))
|
||||
check_inactivity_timeout_dowork (c);
|
||||
if (c->options.inactivity_timeout
|
||||
&& event_timeout_trigger(&c->c2.inactivity_interval, &c->c2.timeval, ETT_DEFAULT))
|
||||
{
|
||||
check_inactivity_timeout_dowork(c);
|
||||
}
|
||||
}
|
||||
|
||||
#if P2MP
|
||||
|
||||
static inline void
|
||||
check_server_poll_timeout (struct context *c)
|
||||
check_server_poll_timeout(struct context *c)
|
||||
{
|
||||
void check_server_poll_timeout_dowork (struct context *c);
|
||||
void check_server_poll_timeout_dowork(struct context *c);
|
||||
|
||||
if (c->options.ce.connect_timeout
|
||||
&& event_timeout_trigger (&c->c2.server_poll_interval, &c->c2.timeval, ETT_DEFAULT))
|
||||
check_server_poll_timeout_dowork (c);
|
||||
if (c->options.ce.connect_timeout
|
||||
&& event_timeout_trigger(&c->c2.server_poll_interval, &c->c2.timeval, ETT_DEFAULT))
|
||||
{
|
||||
check_server_poll_timeout_dowork(c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Scheduled exit?
|
||||
*/
|
||||
static inline void
|
||||
check_scheduled_exit (struct context *c)
|
||||
check_scheduled_exit(struct context *c)
|
||||
{
|
||||
void check_scheduled_exit_dowork (struct context *c);
|
||||
void check_scheduled_exit_dowork(struct context *c);
|
||||
|
||||
if (event_timeout_defined (&c->c2.scheduled_exit))
|
||||
if (event_timeout_defined(&c->c2.scheduled_exit))
|
||||
{
|
||||
if (event_timeout_trigger (&c->c2.scheduled_exit, &c->c2.timeval, ETT_DEFAULT))
|
||||
check_scheduled_exit_dowork (c);
|
||||
if (event_timeout_trigger(&c->c2.scheduled_exit, &c->c2.timeval, ETT_DEFAULT))
|
||||
{
|
||||
check_scheduled_exit_dowork(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* if P2MP */
|
||||
|
||||
/*
|
||||
* Should we write timer-triggered status file.
|
||||
*/
|
||||
static inline void
|
||||
check_status_file (struct context *c)
|
||||
check_status_file(struct context *c)
|
||||
{
|
||||
void check_status_file_dowork (struct context *c);
|
||||
void check_status_file_dowork(struct context *c);
|
||||
|
||||
if (c->c1.status_output)
|
||||
if (c->c1.status_output)
|
||||
{
|
||||
if (status_trigger_tv (c->c1.status_output, &c->c2.timeval))
|
||||
check_status_file_dowork (c);
|
||||
if (status_trigger_tv(c->c1.status_output, &c->c2.timeval))
|
||||
{
|
||||
check_status_file_dowork(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -166,11 +192,14 @@ check_status_file (struct context *c)
|
|||
* Should we deliver a datagram fragment to remote?
|
||||
*/
|
||||
static inline void
|
||||
check_fragment (struct context *c)
|
||||
check_fragment(struct context *c)
|
||||
{
|
||||
void check_fragment_dowork (struct context *c);
|
||||
if (c->c2.fragment)
|
||||
check_fragment_dowork (c);
|
||||
void check_fragment_dowork(struct context *c);
|
||||
|
||||
if (c->c2.fragment)
|
||||
{
|
||||
check_fragment_dowork(c);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -180,11 +209,14 @@ check_fragment (struct context *c)
|
|||
* see if we should send a push_request in response to --pull
|
||||
*/
|
||||
static inline void
|
||||
check_push_request (struct context *c)
|
||||
check_push_request(struct context *c)
|
||||
{
|
||||
void check_push_request_dowork (struct context *c);
|
||||
if (event_timeout_trigger (&c->c2.push_request_interval, &c->c2.timeval, ETT_DEFAULT))
|
||||
check_push_request_dowork (c);
|
||||
void check_push_request_dowork(struct context *c);
|
||||
|
||||
if (event_timeout_trigger(&c->c2.push_request_interval, &c->c2.timeval, ETT_DEFAULT))
|
||||
{
|
||||
check_push_request_dowork(c);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -194,11 +226,13 @@ check_push_request (struct context *c)
|
|||
* Should we persist our anti-replay packet ID state to disk?
|
||||
*/
|
||||
static inline void
|
||||
check_packet_id_persist_flush (struct context *c)
|
||||
check_packet_id_persist_flush(struct context *c)
|
||||
{
|
||||
if (packet_id_persist_enabled (&c->c1.pid_persist)
|
||||
&& event_timeout_trigger (&c->c2.packet_id_persist_interval, &c->c2.timeval, ETT_DEFAULT))
|
||||
packet_id_persist_save (&c->c1.pid_persist);
|
||||
if (packet_id_persist_enabled(&c->c1.pid_persist)
|
||||
&& event_timeout_trigger(&c->c2.packet_id_persist_interval, &c->c2.timeval, ETT_DEFAULT))
|
||||
{
|
||||
packet_id_persist_save(&c->c1.pid_persist);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -207,44 +241,50 @@ check_packet_id_persist_flush (struct context *c)
|
|||
* immediately.
|
||||
*/
|
||||
static inline void
|
||||
context_immediate_reschedule (struct context *c)
|
||||
context_immediate_reschedule(struct context *c)
|
||||
{
|
||||
c->c2.timeval.tv_sec = 0; /* ZERO-TIMEOUT */
|
||||
c->c2.timeval.tv_usec = 0;
|
||||
c->c2.timeval.tv_sec = 0; /* ZERO-TIMEOUT */
|
||||
c->c2.timeval.tv_usec = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
context_reschedule_sec (struct context *c, int sec)
|
||||
context_reschedule_sec(struct context *c, int sec)
|
||||
{
|
||||
if (sec < 0)
|
||||
sec = 0;
|
||||
if (sec < c->c2.timeval.tv_sec)
|
||||
if (sec < 0)
|
||||
{
|
||||
c->c2.timeval.tv_sec = sec;
|
||||
c->c2.timeval.tv_usec = 0;
|
||||
sec = 0;
|
||||
}
|
||||
if (sec < c->c2.timeval.tv_sec)
|
||||
{
|
||||
c->c2.timeval.tv_sec = sec;
|
||||
c->c2.timeval.tv_usec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct link_socket_info *
|
||||
get_link_socket_info (struct context *c)
|
||||
get_link_socket_info(struct context *c)
|
||||
{
|
||||
if (c->c2.link_socket_info)
|
||||
return c->c2.link_socket_info;
|
||||
else
|
||||
return &c->c2.link_socket->info;
|
||||
if (c->c2.link_socket_info)
|
||||
{
|
||||
return c->c2.link_socket_info;
|
||||
}
|
||||
else
|
||||
{
|
||||
return &c->c2.link_socket->info;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
register_activity (struct context *c, const int size)
|
||||
register_activity(struct context *c, const int size)
|
||||
{
|
||||
if (c->options.inactivity_timeout)
|
||||
if (c->options.inactivity_timeout)
|
||||
{
|
||||
c->c2.inactivity_bytes += size;
|
||||
if (c->c2.inactivity_bytes >= c->options.inactivity_minimum_bytes)
|
||||
{
|
||||
c->c2.inactivity_bytes = 0;
|
||||
event_timeout_reset (&c->c2.inactivity_interval);
|
||||
}
|
||||
c->c2.inactivity_bytes += size;
|
||||
if (c->c2.inactivity_bytes >= c->options.inactivity_minimum_bytes)
|
||||
{
|
||||
c->c2.inactivity_bytes = 0;
|
||||
event_timeout_reset(&c->c2.inactivity_interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,14 +293,18 @@ register_activity (struct context *c, const int size)
|
|||
* a point-to-point tunnel.
|
||||
*/
|
||||
static inline unsigned int
|
||||
p2p_iow_flags (const struct context *c)
|
||||
p2p_iow_flags(const struct context *c)
|
||||
{
|
||||
unsigned int flags = (IOW_SHAPER|IOW_CHECK_RESIDUAL|IOW_FRAG|IOW_READ|IOW_WAIT_SIGNAL);
|
||||
if (c->c2.to_link.len > 0)
|
||||
flags |= IOW_TO_LINK;
|
||||
if (c->c2.to_tun.len > 0)
|
||||
flags |= IOW_TO_TUN;
|
||||
return flags;
|
||||
unsigned int flags = (IOW_SHAPER|IOW_CHECK_RESIDUAL|IOW_FRAG|IOW_READ|IOW_WAIT_SIGNAL);
|
||||
if (c->c2.to_link.len > 0)
|
||||
{
|
||||
flags |= IOW_TO_LINK;
|
||||
}
|
||||
if (c->c2.to_tun.len > 0)
|
||||
{
|
||||
flags |= IOW_TO_TUN;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -268,24 +312,28 @@ p2p_iow_flags (const struct context *c)
|
|||
* for TCP in server mode.
|
||||
*/
|
||||
static inline void
|
||||
io_wait (struct context *c, const unsigned int flags)
|
||||
io_wait(struct context *c, const unsigned int flags)
|
||||
{
|
||||
void io_wait_dowork (struct context *c, const unsigned int flags);
|
||||
void io_wait_dowork(struct context *c, const unsigned int flags);
|
||||
|
||||
if (c->c2.fast_io && (flags & (IOW_TO_TUN|IOW_TO_LINK|IOW_MBUF)))
|
||||
if (c->c2.fast_io && (flags & (IOW_TO_TUN|IOW_TO_LINK|IOW_MBUF)))
|
||||
{
|
||||
/* fast path -- only for TUN/TAP/UDP writes */
|
||||
unsigned int ret = 0;
|
||||
if (flags & IOW_TO_TUN)
|
||||
ret |= TUN_WRITE;
|
||||
if (flags & (IOW_TO_LINK|IOW_MBUF))
|
||||
ret |= SOCKET_WRITE;
|
||||
c->c2.event_set_status = ret;
|
||||
/* fast path -- only for TUN/TAP/UDP writes */
|
||||
unsigned int ret = 0;
|
||||
if (flags & IOW_TO_TUN)
|
||||
{
|
||||
ret |= TUN_WRITE;
|
||||
}
|
||||
if (flags & (IOW_TO_LINK|IOW_MBUF))
|
||||
{
|
||||
ret |= SOCKET_WRITE;
|
||||
}
|
||||
c->c2.event_set_status = ret;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
/* slow path */
|
||||
io_wait_dowork (c, flags);
|
||||
/* slow path */
|
||||
io_wait_dowork(c, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -41,7 +41,7 @@
|
|||
#define ANY_OUT(c) (TUN_OUT(c) || LINK_OUT(c))
|
||||
|
||||
#ifdef ENABLE_FRAGMENT
|
||||
#define TO_LINK_FRAG(c) ((c)->c2.fragment && fragment_outgoing_defined ((c)->c2.fragment))
|
||||
#define TO_LINK_FRAG(c) ((c)->c2.fragment && fragment_outgoing_defined((c)->c2.fragment))
|
||||
#else
|
||||
#define TO_LINK_FRAG(c) (false)
|
||||
#endif
|
||||
|
|
@ -62,11 +62,13 @@
|
|||
#define IOW_READ (IOW_READ_TUN|IOW_READ_LINK)
|
||||
|
||||
|
||||
void pre_select (struct context *c);
|
||||
void process_io (struct context *c);
|
||||
void pre_select(struct context *c);
|
||||
|
||||
const char *wait_status_string (struct context *c, struct gc_arena *gc);
|
||||
void show_wait_status (struct context *c);
|
||||
void process_io(struct context *c);
|
||||
|
||||
const char *wait_status_string(struct context *c, struct gc_arena *gc);
|
||||
|
||||
void show_wait_status(struct context *c);
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
|
|
@ -102,8 +104,9 @@ void show_wait_status (struct context *c);
|
|||
* the packet then gets fragmented, this function will be called again
|
||||
* once for each remaining fragment with this parameter set to false.
|
||||
*/
|
||||
void encrypt_sign (struct context *c, bool comp_frag);
|
||||
int get_server_poll_remaining_time (struct event_timeout* server_poll_timeout);
|
||||
void encrypt_sign(struct context *c, bool comp_frag);
|
||||
|
||||
int get_server_poll_remaining_time(struct event_timeout *server_poll_timeout);
|
||||
|
||||
/**********************************************************************/
|
||||
/**
|
||||
|
|
@ -125,7 +128,7 @@ int get_server_poll_remaining_time (struct event_timeout* server_poll_timeout);
|
|||
* @param c - The context structure which contains the external
|
||||
* network socket from which to read incoming packets.
|
||||
*/
|
||||
void read_incoming_link (struct context *c);
|
||||
void read_incoming_link(struct context *c);
|
||||
|
||||
/**
|
||||
* Starts processing a packet read from the external network interface.
|
||||
|
|
@ -153,7 +156,7 @@ void read_incoming_link (struct context *c);
|
|||
*
|
||||
* @return true if packet is authenticated, false otherwise.
|
||||
*/
|
||||
bool process_incoming_link_part1 (struct context *c, struct link_socket_info *lsi, bool floated);
|
||||
bool process_incoming_link_part1(struct context *c, struct link_socket_info *lsi, bool floated);
|
||||
|
||||
/**
|
||||
* Continues processing a packet read from the external network interface.
|
||||
|
|
@ -180,7 +183,7 @@ bool process_incoming_link_part1 (struct context *c, struct link_socket_info *ls
|
|||
* @param orig_buf - Pointer to a buffer data.
|
||||
*
|
||||
*/
|
||||
void process_incoming_link_part2 (struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf);
|
||||
void process_incoming_link_part2(struct context *c, struct link_socket_info *lsi, const uint8_t *orig_buf);
|
||||
|
||||
/**
|
||||
* Write a packet to the external network interface.
|
||||
|
|
@ -194,7 +197,7 @@ void process_incoming_link_part2 (struct context *c, struct link_socket_info *ls
|
|||
* @param c - The context structure of the VPN tunnel associated with the
|
||||
* packet.
|
||||
*/
|
||||
void process_outgoing_link (struct context *c);
|
||||
void process_outgoing_link(struct context *c);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
@ -210,7 +213,7 @@ void process_outgoing_link (struct context *c);
|
|||
* @param c - The context structure in which to store the received
|
||||
* packet.
|
||||
*/
|
||||
void read_incoming_tun (struct context *c);
|
||||
void read_incoming_tun(struct context *c);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -225,7 +228,7 @@ void read_incoming_tun (struct context *c);
|
|||
* @param c - The context structure of the VPN tunnel associated with the
|
||||
* packet.
|
||||
*/
|
||||
void process_incoming_tun (struct context *c);
|
||||
void process_incoming_tun(struct context *c);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -240,12 +243,12 @@ void process_incoming_tun (struct context *c);
|
|||
* @param c - The context structure of the VPN tunnel associated with
|
||||
* the packet.
|
||||
*/
|
||||
void process_outgoing_tun (struct context *c);
|
||||
void process_outgoing_tun(struct context *c);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
bool send_control_channel_string (struct context *c, const char *str, int msglevel);
|
||||
bool send_control_channel_string(struct context *c, const char *str, int msglevel);
|
||||
|
||||
#define PIPV4_PASSTOS (1<<0)
|
||||
#define PIP_MSSFIX (1<<1) /* v4 and v6 */
|
||||
|
|
@ -253,10 +256,11 @@ bool send_control_channel_string (struct context *c, const char *str, int msglev
|
|||
#define PIPV4_EXTRACT_DHCP_ROUTER (1<<3)
|
||||
#define PIPV4_CLIENT_NAT (1<<4)
|
||||
|
||||
void process_ip_header (struct context *c, unsigned int flags, struct buffer *buf);
|
||||
void process_ip_header(struct context *c, unsigned int flags, struct buffer *buf);
|
||||
|
||||
#if P2MP
|
||||
void schedule_exit (struct context *c, const int n_seconds, const int signal);
|
||||
void schedule_exit(struct context *c, const int n_seconds, const int signal);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* FORWARD_H */
|
||||
|
|
|
|||
|
|
@ -40,19 +40,19 @@
|
|||
#define FRAG_ERR(s) { errmsg = s; goto error; }
|
||||
|
||||
static void
|
||||
fragment_list_buf_init (struct fragment_list *list, const struct frame *frame)
|
||||
fragment_list_buf_init(struct fragment_list *list, const struct frame *frame)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < N_FRAG_BUF; ++i)
|
||||
list->fragments[i].buf = alloc_buf (BUF_SIZE (frame));
|
||||
int i;
|
||||
for (i = 0; i < N_FRAG_BUF; ++i)
|
||||
list->fragments[i].buf = alloc_buf(BUF_SIZE(frame));
|
||||
}
|
||||
|
||||
static void
|
||||
fragment_list_buf_free (struct fragment_list *list)
|
||||
fragment_list_buf_free(struct fragment_list *list)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < N_FRAG_BUF; ++i)
|
||||
free_buf (&list->fragments[i].buf);
|
||||
int i;
|
||||
for (i = 0; i < N_FRAG_BUF; ++i)
|
||||
free_buf(&list->fragments[i].buf);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -60,69 +60,69 @@ fragment_list_buf_free (struct fragment_list *list)
|
|||
* similar to packet_id code.
|
||||
*/
|
||||
static struct fragment *
|
||||
fragment_list_get_buf (struct fragment_list *list, int seq_id)
|
||||
fragment_list_get_buf(struct fragment_list *list, int seq_id)
|
||||
{
|
||||
int diff;
|
||||
if (abs (diff = modulo_subtract (seq_id, list->seq_id, N_SEQ_ID)) >= N_FRAG_BUF)
|
||||
int diff;
|
||||
if (abs(diff = modulo_subtract(seq_id, list->seq_id, N_SEQ_ID)) >= N_FRAG_BUF)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < N_FRAG_BUF; ++i)
|
||||
list->fragments[i].defined = false;
|
||||
list->index = 0;
|
||||
list->seq_id = seq_id;
|
||||
diff = 0;
|
||||
int i;
|
||||
for (i = 0; i < N_FRAG_BUF; ++i)
|
||||
list->fragments[i].defined = false;
|
||||
list->index = 0;
|
||||
list->seq_id = seq_id;
|
||||
diff = 0;
|
||||
}
|
||||
while (diff > 0)
|
||||
while (diff > 0)
|
||||
{
|
||||
list->fragments[list->index = modulo_add (list->index, 1, N_FRAG_BUF)].defined = false;
|
||||
list->seq_id = modulo_add (list->seq_id, 1, N_SEQ_ID);
|
||||
--diff;
|
||||
list->fragments[list->index = modulo_add(list->index, 1, N_FRAG_BUF)].defined = false;
|
||||
list->seq_id = modulo_add(list->seq_id, 1, N_SEQ_ID);
|
||||
--diff;
|
||||
}
|
||||
return &list->fragments[modulo_add (list->index, diff, N_FRAG_BUF)];
|
||||
return &list->fragments[modulo_add(list->index, diff, N_FRAG_BUF)];
|
||||
}
|
||||
|
||||
struct fragment_master *
|
||||
fragment_init (struct frame *frame)
|
||||
fragment_init(struct frame *frame)
|
||||
{
|
||||
struct fragment_master *ret;
|
||||
struct fragment_master *ret;
|
||||
|
||||
/* code that initializes other parts of
|
||||
fragment_master assume an initial CLEAR */
|
||||
ALLOC_OBJ_CLEAR (ret, struct fragment_master);
|
||||
/* code that initializes other parts of
|
||||
* fragment_master assume an initial CLEAR */
|
||||
ALLOC_OBJ_CLEAR(ret, struct fragment_master);
|
||||
|
||||
/* add in the size of our contribution to the expanded frame size */
|
||||
frame_add_to_extra_frame (frame, sizeof(fragment_header_type));
|
||||
/* add in the size of our contribution to the expanded frame size */
|
||||
frame_add_to_extra_frame(frame, sizeof(fragment_header_type));
|
||||
|
||||
/*
|
||||
* Outgoing sequence ID is randomized to reduce
|
||||
* the probability of sequence number collisions
|
||||
* when openvpn sessions are restarted. This is
|
||||
* not done out of any need for security, as all
|
||||
* fragmentation control information resides
|
||||
* inside of the encrypted/authenticated envelope.
|
||||
*/
|
||||
ret->outgoing_seq_id = (int)get_random() & (N_SEQ_ID - 1);
|
||||
/*
|
||||
* Outgoing sequence ID is randomized to reduce
|
||||
* the probability of sequence number collisions
|
||||
* when openvpn sessions are restarted. This is
|
||||
* not done out of any need for security, as all
|
||||
* fragmentation control information resides
|
||||
* inside of the encrypted/authenticated envelope.
|
||||
*/
|
||||
ret->outgoing_seq_id = (int)get_random() & (N_SEQ_ID - 1);
|
||||
|
||||
event_timeout_init (&ret->wakeup, FRAG_WAKEUP_INTERVAL, now);
|
||||
event_timeout_init(&ret->wakeup, FRAG_WAKEUP_INTERVAL, now);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
fragment_free (struct fragment_master *f)
|
||||
fragment_free(struct fragment_master *f)
|
||||
{
|
||||
fragment_list_buf_free (&f->incoming);
|
||||
free_buf (&f->outgoing);
|
||||
free_buf (&f->outgoing_return);
|
||||
free (f);
|
||||
fragment_list_buf_free(&f->incoming);
|
||||
free_buf(&f->outgoing);
|
||||
free_buf(&f->outgoing_return);
|
||||
free(f);
|
||||
}
|
||||
|
||||
void
|
||||
fragment_frame_init (struct fragment_master *f, const struct frame *frame)
|
||||
fragment_frame_init(struct fragment_master *f, const struct frame *frame)
|
||||
{
|
||||
fragment_list_buf_init (&f->incoming, frame);
|
||||
f->outgoing = alloc_buf (BUF_SIZE (frame));
|
||||
f->outgoing_return = alloc_buf (BUF_SIZE (frame));
|
||||
fragment_list_buf_init(&f->incoming, frame);
|
||||
f->outgoing = alloc_buf(BUF_SIZE(frame));
|
||||
f->outgoing_return = alloc_buf(BUF_SIZE(frame));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -132,154 +132,164 @@ fragment_frame_init (struct fragment_master *f, const struct frame *frame)
|
|||
* If a fragment fully completes the datagram, return the datagram.
|
||||
*/
|
||||
void
|
||||
fragment_incoming (struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame* frame)
|
||||
fragment_incoming(struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame *frame)
|
||||
{
|
||||
const char *errmsg = NULL;
|
||||
fragment_header_type flags = 0;
|
||||
int frag_type = 0;
|
||||
const char *errmsg = NULL;
|
||||
fragment_header_type flags = 0;
|
||||
int frag_type = 0;
|
||||
|
||||
if (buf->len > 0)
|
||||
if (buf->len > 0)
|
||||
{
|
||||
/* get flags from packet head */
|
||||
if (!buf_read (buf, &flags, sizeof (flags)))
|
||||
FRAG_ERR ("flags not found in packet");
|
||||
flags = ntoh_fragment_header_type (flags);
|
||||
/* get flags from packet head */
|
||||
if (!buf_read(buf, &flags, sizeof(flags)))
|
||||
{
|
||||
FRAG_ERR("flags not found in packet");
|
||||
}
|
||||
flags = ntoh_fragment_header_type(flags);
|
||||
|
||||
/* get fragment type from flags */
|
||||
frag_type = ((flags >> FRAG_TYPE_SHIFT) & FRAG_TYPE_MASK);
|
||||
/* get fragment type from flags */
|
||||
frag_type = ((flags >> FRAG_TYPE_SHIFT) & FRAG_TYPE_MASK);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* If you want to extract FRAG_EXTRA_MASK/FRAG_EXTRA_SHIFT bits,
|
||||
* do it here.
|
||||
*/
|
||||
if (frag_type == FRAG_WHOLE || frag_type == FRAG_YES_NOTLAST)
|
||||
{
|
||||
}
|
||||
/*
|
||||
* If you want to extract FRAG_EXTRA_MASK/FRAG_EXTRA_SHIFT bits,
|
||||
* do it here.
|
||||
*/
|
||||
if (frag_type == FRAG_WHOLE || frag_type == FRAG_YES_NOTLAST)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* handle the fragment type */
|
||||
if (frag_type == FRAG_WHOLE)
|
||||
{
|
||||
dmsg (D_FRAG_DEBUG,
|
||||
"FRAG_IN buf->len=%d type=FRAG_WHOLE flags="
|
||||
fragment_header_format,
|
||||
buf->len,
|
||||
flags);
|
||||
/* handle the fragment type */
|
||||
if (frag_type == FRAG_WHOLE)
|
||||
{
|
||||
dmsg(D_FRAG_DEBUG,
|
||||
"FRAG_IN buf->len=%d type=FRAG_WHOLE flags="
|
||||
fragment_header_format,
|
||||
buf->len,
|
||||
flags);
|
||||
|
||||
if (flags & (FRAG_SEQ_ID_MASK | FRAG_ID_MASK))
|
||||
FRAG_ERR ("spurrious FRAG_WHOLE flags");
|
||||
}
|
||||
else if (frag_type == FRAG_YES_NOTLAST || frag_type == FRAG_YES_LAST)
|
||||
{
|
||||
const int seq_id = ((flags >> FRAG_SEQ_ID_SHIFT) & FRAG_SEQ_ID_MASK);
|
||||
const int n = ((flags >> FRAG_ID_SHIFT) & FRAG_ID_MASK);
|
||||
const int size = ((frag_type == FRAG_YES_LAST)
|
||||
? (int)(((flags >> FRAG_SIZE_SHIFT) & FRAG_SIZE_MASK) << FRAG_SIZE_ROUND_SHIFT)
|
||||
: buf->len);
|
||||
if (flags & (FRAG_SEQ_ID_MASK | FRAG_ID_MASK))
|
||||
{
|
||||
FRAG_ERR("spurrious FRAG_WHOLE flags");
|
||||
}
|
||||
}
|
||||
else if (frag_type == FRAG_YES_NOTLAST || frag_type == FRAG_YES_LAST)
|
||||
{
|
||||
const int seq_id = ((flags >> FRAG_SEQ_ID_SHIFT) & FRAG_SEQ_ID_MASK);
|
||||
const int n = ((flags >> FRAG_ID_SHIFT) & FRAG_ID_MASK);
|
||||
const int size = ((frag_type == FRAG_YES_LAST)
|
||||
? (int)(((flags >> FRAG_SIZE_SHIFT) & FRAG_SIZE_MASK) << FRAG_SIZE_ROUND_SHIFT)
|
||||
: buf->len);
|
||||
|
||||
/* get the appropriate fragment buffer based on received seq_id */
|
||||
struct fragment *frag = fragment_list_get_buf (&f->incoming, seq_id);
|
||||
/* get the appropriate fragment buffer based on received seq_id */
|
||||
struct fragment *frag = fragment_list_get_buf(&f->incoming, seq_id);
|
||||
|
||||
dmsg (D_FRAG_DEBUG,
|
||||
"FRAG_IN len=%d type=%d seq_id=%d frag_id=%d size=%d flags="
|
||||
fragment_header_format,
|
||||
buf->len,
|
||||
frag_type,
|
||||
seq_id,
|
||||
n,
|
||||
size,
|
||||
flags);
|
||||
dmsg(D_FRAG_DEBUG,
|
||||
"FRAG_IN len=%d type=%d seq_id=%d frag_id=%d size=%d flags="
|
||||
fragment_header_format,
|
||||
buf->len,
|
||||
frag_type,
|
||||
seq_id,
|
||||
n,
|
||||
size,
|
||||
flags);
|
||||
|
||||
/* make sure that size is an even multiple of 1<<FRAG_SIZE_ROUND_SHIFT */
|
||||
if (size & FRAG_SIZE_ROUND_MASK)
|
||||
FRAG_ERR ("bad fragment size");
|
||||
/* make sure that size is an even multiple of 1<<FRAG_SIZE_ROUND_SHIFT */
|
||||
if (size & FRAG_SIZE_ROUND_MASK)
|
||||
{
|
||||
FRAG_ERR("bad fragment size");
|
||||
}
|
||||
|
||||
/* is this the first fragment for our sequence number? */
|
||||
if (!frag->defined || (frag->defined && frag->max_frag_size != size))
|
||||
{
|
||||
frag->defined = true;
|
||||
frag->max_frag_size = size;
|
||||
frag->map = 0;
|
||||
ASSERT (buf_init (&frag->buf, FRAME_HEADROOM_ADJ (frame, FRAME_HEADROOM_MARKER_FRAGMENT)));
|
||||
}
|
||||
/* is this the first fragment for our sequence number? */
|
||||
if (!frag->defined || (frag->defined && frag->max_frag_size != size))
|
||||
{
|
||||
frag->defined = true;
|
||||
frag->max_frag_size = size;
|
||||
frag->map = 0;
|
||||
ASSERT(buf_init(&frag->buf, FRAME_HEADROOM_ADJ(frame, FRAME_HEADROOM_MARKER_FRAGMENT)));
|
||||
}
|
||||
|
||||
/* copy the data to fragment buffer */
|
||||
if (!buf_copy_range (&frag->buf, n * size, buf, 0, buf->len))
|
||||
FRAG_ERR ("fragment buffer overflow");
|
||||
/* copy the data to fragment buffer */
|
||||
if (!buf_copy_range(&frag->buf, n * size, buf, 0, buf->len))
|
||||
{
|
||||
FRAG_ERR("fragment buffer overflow");
|
||||
}
|
||||
|
||||
/* set elements in bit array to reflect which fragments have been received */
|
||||
frag->map |= (((frag_type == FRAG_YES_LAST) ? FRAG_MAP_MASK : 1) << n);
|
||||
/* set elements in bit array to reflect which fragments have been received */
|
||||
frag->map |= (((frag_type == FRAG_YES_LAST) ? FRAG_MAP_MASK : 1) << n);
|
||||
|
||||
/* update timestamp on partially built datagram */
|
||||
frag->timestamp = now;
|
||||
/* update timestamp on partially built datagram */
|
||||
frag->timestamp = now;
|
||||
|
||||
/* received full datagram? */
|
||||
if ((frag->map & FRAG_MAP_MASK) == FRAG_MAP_MASK)
|
||||
{
|
||||
frag->defined = false;
|
||||
*buf = frag->buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf->len = 0;
|
||||
}
|
||||
}
|
||||
else if (frag_type == FRAG_TEST)
|
||||
{
|
||||
FRAG_ERR ("FRAG_TEST not implemented");
|
||||
}
|
||||
else
|
||||
{
|
||||
FRAG_ERR ("unknown fragment type");
|
||||
}
|
||||
/* received full datagram? */
|
||||
if ((frag->map & FRAG_MAP_MASK) == FRAG_MAP_MASK)
|
||||
{
|
||||
frag->defined = false;
|
||||
*buf = frag->buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf->len = 0;
|
||||
}
|
||||
}
|
||||
else if (frag_type == FRAG_TEST)
|
||||
{
|
||||
FRAG_ERR("FRAG_TEST not implemented");
|
||||
}
|
||||
else
|
||||
{
|
||||
FRAG_ERR("unknown fragment type");
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return;
|
||||
|
||||
error:
|
||||
if (errmsg)
|
||||
msg (D_FRAG_ERRORS, "FRAG_IN error flags=" fragment_header_format ": %s", flags, errmsg);
|
||||
buf->len = 0;
|
||||
return;
|
||||
error:
|
||||
if (errmsg)
|
||||
{
|
||||
msg(D_FRAG_ERRORS, "FRAG_IN error flags=" fragment_header_format ": %s", flags, errmsg);
|
||||
}
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* pack fragment parms into a uint32_t and prepend to buffer */
|
||||
static void
|
||||
fragment_prepend_flags (struct buffer *buf,
|
||||
int type,
|
||||
int seq_id,
|
||||
int frag_id,
|
||||
int frag_size)
|
||||
fragment_prepend_flags(struct buffer *buf,
|
||||
int type,
|
||||
int seq_id,
|
||||
int frag_id,
|
||||
int frag_size)
|
||||
{
|
||||
fragment_header_type flags = ((type & FRAG_TYPE_MASK) << FRAG_TYPE_SHIFT)
|
||||
| ((seq_id & FRAG_SEQ_ID_MASK) << FRAG_SEQ_ID_SHIFT)
|
||||
| ((frag_id & FRAG_ID_MASK) << FRAG_ID_SHIFT);
|
||||
fragment_header_type flags = ((type & FRAG_TYPE_MASK) << FRAG_TYPE_SHIFT)
|
||||
| ((seq_id & FRAG_SEQ_ID_MASK) << FRAG_SEQ_ID_SHIFT)
|
||||
| ((frag_id & FRAG_ID_MASK) << FRAG_ID_SHIFT);
|
||||
|
||||
if (type == FRAG_WHOLE || type == FRAG_YES_NOTLAST)
|
||||
if (type == FRAG_WHOLE || type == FRAG_YES_NOTLAST)
|
||||
{
|
||||
/*
|
||||
* If you want to set FRAG_EXTRA_MASK/FRAG_EXTRA_SHIFT bits,
|
||||
* do it here.
|
||||
*/
|
||||
dmsg (D_FRAG_DEBUG,
|
||||
"FRAG_OUT len=%d type=%d seq_id=%d frag_id=%d frag_size=%d flags="
|
||||
fragment_header_format,
|
||||
buf->len, type, seq_id, frag_id, frag_size, flags);
|
||||
/*
|
||||
* If you want to set FRAG_EXTRA_MASK/FRAG_EXTRA_SHIFT bits,
|
||||
* do it here.
|
||||
*/
|
||||
dmsg(D_FRAG_DEBUG,
|
||||
"FRAG_OUT len=%d type=%d seq_id=%d frag_id=%d frag_size=%d flags="
|
||||
fragment_header_format,
|
||||
buf->len, type, seq_id, frag_id, frag_size, flags);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
flags |= (((frag_size >> FRAG_SIZE_ROUND_SHIFT) & FRAG_SIZE_MASK) << FRAG_SIZE_SHIFT);
|
||||
flags |= (((frag_size >> FRAG_SIZE_ROUND_SHIFT) & FRAG_SIZE_MASK) << FRAG_SIZE_SHIFT);
|
||||
|
||||
dmsg (D_FRAG_DEBUG,
|
||||
"FRAG_OUT len=%d type=%d seq_id=%d frag_id=%d frag_size=%d flags="
|
||||
fragment_header_format,
|
||||
buf->len, type, seq_id, frag_id, frag_size, flags);
|
||||
dmsg(D_FRAG_DEBUG,
|
||||
"FRAG_OUT len=%d type=%d seq_id=%d frag_id=%d frag_size=%d flags="
|
||||
fragment_header_format,
|
||||
buf->len, type, seq_id, frag_id, frag_size, flags);
|
||||
}
|
||||
|
||||
flags = hton_fragment_header_type (flags);
|
||||
ASSERT (buf_write_prepend (buf, &flags, sizeof (flags)));
|
||||
flags = hton_fragment_header_type(flags);
|
||||
ASSERT(buf_write_prepend(buf, &flags, sizeof(flags)));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -288,127 +298,141 @@ fragment_prepend_flags (struct buffer *buf,
|
|||
* similar size as previous fragments.
|
||||
*/
|
||||
static inline int
|
||||
optimal_fragment_size (int len, int max_frag_size)
|
||||
optimal_fragment_size(int len, int max_frag_size)
|
||||
{
|
||||
const int mfs_aligned = (max_frag_size & ~FRAG_SIZE_ROUND_MASK);
|
||||
const int div = len / mfs_aligned;
|
||||
const int mod = len % mfs_aligned;
|
||||
const int mfs_aligned = (max_frag_size & ~FRAG_SIZE_ROUND_MASK);
|
||||
const int div = len / mfs_aligned;
|
||||
const int mod = len % mfs_aligned;
|
||||
|
||||
if (div > 0 && mod > 0 && mod < mfs_aligned * 3 / 4)
|
||||
return min_int (mfs_aligned, (max_frag_size - ((max_frag_size - mod) / (div + 1))
|
||||
+ FRAG_SIZE_ROUND_MASK) & ~FRAG_SIZE_ROUND_MASK);
|
||||
else
|
||||
return mfs_aligned;
|
||||
if (div > 0 && mod > 0 && mod < mfs_aligned * 3 / 4)
|
||||
{
|
||||
return min_int(mfs_aligned, (max_frag_size - ((max_frag_size - mod) / (div + 1))
|
||||
+ FRAG_SIZE_ROUND_MASK) & ~FRAG_SIZE_ROUND_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
return mfs_aligned;
|
||||
}
|
||||
}
|
||||
|
||||
/* process an outgoing datagram, possibly breaking it up into fragments */
|
||||
void
|
||||
fragment_outgoing (struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame* frame)
|
||||
fragment_outgoing(struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame *frame)
|
||||
{
|
||||
const char *errmsg = NULL;
|
||||
if (buf->len > 0)
|
||||
const char *errmsg = NULL;
|
||||
if (buf->len > 0)
|
||||
{
|
||||
/* The outgoing buffer should be empty so we can put new data in it */
|
||||
if (f->outgoing.len)
|
||||
msg (D_FRAG_ERRORS, "FRAG: outgoing buffer is not empty, len=[%d,%d]",
|
||||
buf->len, f->outgoing.len);
|
||||
if (buf->len > PAYLOAD_SIZE_DYNAMIC(frame)) /* should we fragment? */
|
||||
{
|
||||
/*
|
||||
* Send the datagram as a series of 2 or more fragments.
|
||||
*/
|
||||
f->outgoing_frag_size = optimal_fragment_size (buf->len, PAYLOAD_SIZE_DYNAMIC(frame));
|
||||
if (buf->len > f->outgoing_frag_size * MAX_FRAGS)
|
||||
FRAG_ERR ("too many fragments would be required to send datagram");
|
||||
ASSERT (buf_init (&f->outgoing, FRAME_HEADROOM (frame)));
|
||||
ASSERT (buf_copy (&f->outgoing, buf));
|
||||
f->outgoing_seq_id = modulo_add (f->outgoing_seq_id, 1, N_SEQ_ID);
|
||||
f->outgoing_frag_id = 0;
|
||||
buf->len = 0;
|
||||
ASSERT (fragment_ready_to_send (f, buf, frame));
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Send the datagram whole.
|
||||
*/
|
||||
fragment_prepend_flags (buf,
|
||||
FRAG_WHOLE,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
/* The outgoing buffer should be empty so we can put new data in it */
|
||||
if (f->outgoing.len)
|
||||
{
|
||||
msg(D_FRAG_ERRORS, "FRAG: outgoing buffer is not empty, len=[%d,%d]",
|
||||
buf->len, f->outgoing.len);
|
||||
}
|
||||
if (buf->len > PAYLOAD_SIZE_DYNAMIC(frame)) /* should we fragment? */
|
||||
{
|
||||
/*
|
||||
* Send the datagram as a series of 2 or more fragments.
|
||||
*/
|
||||
f->outgoing_frag_size = optimal_fragment_size(buf->len, PAYLOAD_SIZE_DYNAMIC(frame));
|
||||
if (buf->len > f->outgoing_frag_size * MAX_FRAGS)
|
||||
{
|
||||
FRAG_ERR("too many fragments would be required to send datagram");
|
||||
}
|
||||
ASSERT(buf_init(&f->outgoing, FRAME_HEADROOM(frame)));
|
||||
ASSERT(buf_copy(&f->outgoing, buf));
|
||||
f->outgoing_seq_id = modulo_add(f->outgoing_seq_id, 1, N_SEQ_ID);
|
||||
f->outgoing_frag_id = 0;
|
||||
buf->len = 0;
|
||||
ASSERT(fragment_ready_to_send(f, buf, frame));
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Send the datagram whole.
|
||||
*/
|
||||
fragment_prepend_flags(buf,
|
||||
FRAG_WHOLE,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
}
|
||||
}
|
||||
return;
|
||||
return;
|
||||
|
||||
error:
|
||||
if (errmsg)
|
||||
msg (D_FRAG_ERRORS, "FRAG_OUT error, len=%d frag_size=%d MAX_FRAGS=%d: %s",
|
||||
buf->len, f->outgoing_frag_size, MAX_FRAGS, errmsg);
|
||||
buf->len = 0;
|
||||
return;
|
||||
error:
|
||||
if (errmsg)
|
||||
{
|
||||
msg(D_FRAG_ERRORS, "FRAG_OUT error, len=%d frag_size=%d MAX_FRAGS=%d: %s",
|
||||
buf->len, f->outgoing_frag_size, MAX_FRAGS, errmsg);
|
||||
}
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* return true (and set buf) if we have an outgoing fragment which is ready to send */
|
||||
bool
|
||||
fragment_ready_to_send (struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame* frame)
|
||||
fragment_ready_to_send(struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame *frame)
|
||||
{
|
||||
if (fragment_outgoing_defined (f))
|
||||
if (fragment_outgoing_defined(f))
|
||||
{
|
||||
/* get fragment size, and determine if it is the last fragment */
|
||||
int size = f->outgoing_frag_size;
|
||||
int last = false;
|
||||
if (f->outgoing.len <= size)
|
||||
{
|
||||
size = f->outgoing.len;
|
||||
last = true;
|
||||
}
|
||||
/* get fragment size, and determine if it is the last fragment */
|
||||
int size = f->outgoing_frag_size;
|
||||
int last = false;
|
||||
if (f->outgoing.len <= size)
|
||||
{
|
||||
size = f->outgoing.len;
|
||||
last = true;
|
||||
}
|
||||
|
||||
/* initialize return buffer */
|
||||
*buf = f->outgoing_return;
|
||||
ASSERT (buf_init (buf, FRAME_HEADROOM (frame)));
|
||||
ASSERT (buf_copy_n (buf, &f->outgoing, size));
|
||||
/* initialize return buffer */
|
||||
*buf = f->outgoing_return;
|
||||
ASSERT(buf_init(buf, FRAME_HEADROOM(frame)));
|
||||
ASSERT(buf_copy_n(buf, &f->outgoing, size));
|
||||
|
||||
/* fragment flags differ based on whether or not we are sending the last fragment */
|
||||
fragment_prepend_flags (buf,
|
||||
last ? FRAG_YES_LAST : FRAG_YES_NOTLAST,
|
||||
f->outgoing_seq_id,
|
||||
f->outgoing_frag_id++,
|
||||
f->outgoing_frag_size);
|
||||
/* fragment flags differ based on whether or not we are sending the last fragment */
|
||||
fragment_prepend_flags(buf,
|
||||
last ? FRAG_YES_LAST : FRAG_YES_NOTLAST,
|
||||
f->outgoing_seq_id,
|
||||
f->outgoing_frag_id++,
|
||||
f->outgoing_frag_size);
|
||||
|
||||
ASSERT (!last || !f->outgoing.len); /* outgoing buffer length should be zero after last fragment sent */
|
||||
ASSERT(!last || !f->outgoing.len); /* outgoing buffer length should be zero after last fragment sent */
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
fragment_ttl_reap (struct fragment_master *f)
|
||||
fragment_ttl_reap(struct fragment_master *f)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < N_FRAG_BUF; ++i)
|
||||
int i;
|
||||
for (i = 0; i < N_FRAG_BUF; ++i)
|
||||
{
|
||||
struct fragment *frag = &f->incoming.fragments[i];
|
||||
if (frag->defined && frag->timestamp + FRAG_TTL_SEC <= now)
|
||||
{
|
||||
msg (D_FRAG_ERRORS, "FRAG TTL expired i=%d", i);
|
||||
frag->defined = false;
|
||||
}
|
||||
struct fragment *frag = &f->incoming.fragments[i];
|
||||
if (frag->defined && frag->timestamp + FRAG_TTL_SEC <= now)
|
||||
{
|
||||
msg(D_FRAG_ERRORS, "FRAG TTL expired i=%d", i);
|
||||
frag->defined = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* called every FRAG_WAKEUP_INTERVAL seconds */
|
||||
void
|
||||
fragment_wakeup (struct fragment_master *f, struct frame *frame)
|
||||
fragment_wakeup(struct fragment_master *f, struct frame *frame)
|
||||
{
|
||||
/* delete fragments with expired TTLs */
|
||||
fragment_ttl_reap (f);
|
||||
/* delete fragments with expired TTLs */
|
||||
fragment_ttl_reap(f);
|
||||
}
|
||||
|
||||
#else
|
||||
static void dummy(void) {}
|
||||
#endif
|
||||
#else /* ifdef ENABLE_FRAGMENT */
|
||||
static void
|
||||
dummy(void) {
|
||||
}
|
||||
#endif /* ifdef ENABLE_FRAGMENT */
|
||||
|
|
|
|||
|
|
@ -48,43 +48,43 @@
|
|||
|
||||
|
||||
#define N_FRAG_BUF 25
|
||||
/**< Number of packet buffers for
|
||||
* reassembling incoming fragmented
|
||||
* packets. */
|
||||
/**< Number of packet buffers for
|
||||
* reassembling incoming fragmented
|
||||
* packets. */
|
||||
|
||||
#define FRAG_TTL_SEC 10
|
||||
/**< Time-to-live in seconds for a %fragment. */
|
||||
/**< Time-to-live in seconds for a %fragment. */
|
||||
|
||||
#define FRAG_WAKEUP_INTERVAL 5
|
||||
/**< Interval in seconds between calls to
|
||||
* wakeup code. */
|
||||
/**< Interval in seconds between calls to
|
||||
* wakeup code. */
|
||||
|
||||
/**************************************************************************/
|
||||
/**
|
||||
* Structure for reassembling one incoming fragmented packet.
|
||||
*/
|
||||
struct fragment {
|
||||
bool defined; /**< Whether reassembly is currently
|
||||
bool defined; /**< Whether reassembly is currently
|
||||
* taking place in this structure. */
|
||||
|
||||
int max_frag_size; /**< Maximum size of each %fragment. */
|
||||
int max_frag_size; /**< Maximum size of each %fragment. */
|
||||
|
||||
# define FRAG_MAP_MASK 0xFFFFFFFF
|
||||
/**< Mask for reassembly map. */
|
||||
# define MAX_FRAGS 32 /**< Maximum number of fragments per packet. */
|
||||
unsigned int map;
|
||||
/**< Reassembly map for recording which
|
||||
* fragments have been received.
|
||||
*
|
||||
* A bit array where each bit
|
||||
* corresponds to a %fragment. A 1 bit
|
||||
* in element n means that the %fragment
|
||||
* n has been received. Needs to have
|
||||
* at least \c MAX_FRAGS bits. */
|
||||
#define FRAG_MAP_MASK 0xFFFFFFFF
|
||||
/**< Mask for reassembly map. */
|
||||
#define MAX_FRAGS 32 /**< Maximum number of fragments per packet. */
|
||||
unsigned int map;
|
||||
/**< Reassembly map for recording which
|
||||
* fragments have been received.
|
||||
*
|
||||
* A bit array where each bit
|
||||
* corresponds to a %fragment. A 1 bit
|
||||
* in element n means that the %fragment
|
||||
* n has been received. Needs to have
|
||||
* at least \c MAX_FRAGS bits. */
|
||||
|
||||
time_t timestamp; /**< Timestamp for time-to-live purposes. */
|
||||
time_t timestamp; /**< Timestamp for time-to-live purposes. */
|
||||
|
||||
struct buffer buf; /**< Buffer in which received datagrams
|
||||
struct buffer buf; /**< Buffer in which received datagrams
|
||||
* are reassembled. */
|
||||
};
|
||||
|
||||
|
|
@ -94,10 +94,10 @@ struct fragment {
|
|||
* concurrently.
|
||||
*/
|
||||
struct fragment_list {
|
||||
int seq_id; /**< Highest fragmentation sequence ID of
|
||||
int seq_id; /**< Highest fragmentation sequence ID of
|
||||
* the packets currently being
|
||||
* reassembled. */
|
||||
int index; /**< Index of the packet being reassembled
|
||||
int index; /**< Index of the packet being reassembled
|
||||
* with the highest fragmentation
|
||||
* sequence ID into the \c
|
||||
* fragment_list.fragments array. */
|
||||
|
|
@ -112,7 +112,7 @@ struct fragment_list {
|
|||
* 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];
|
||||
struct fragment fragments[N_FRAG_BUF];
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -135,16 +135,16 @@ struct fragment_list {
|
|||
* and returns the whole packets once reassembly is complete.
|
||||
*/
|
||||
struct fragment_master {
|
||||
struct event_timeout wakeup; /**< Timeout structure used by the main
|
||||
* event loop to know when to do
|
||||
* fragmentation housekeeping. */
|
||||
bool received_os_mtu_hint; /**< Whether the operating system has
|
||||
struct event_timeout wakeup; /**< Timeout structure used by the main
|
||||
* event loop to know when to do
|
||||
* fragmentation housekeeping. */
|
||||
bool received_os_mtu_hint; /**< Whether the operating system has
|
||||
* explicitly recommended an MTU value. */
|
||||
# define N_SEQ_ID 256
|
||||
/**< One more than the maximum fragment
|
||||
* sequence ID, above which the IDs wrap
|
||||
* to zero. Should be a power of 2. */
|
||||
int outgoing_seq_id; /**< Fragment sequence ID of the current
|
||||
#define N_SEQ_ID 256
|
||||
/**< One more than the maximum fragment
|
||||
* sequence ID, above which the IDs wrap
|
||||
* to zero. Should be a power of 2. */
|
||||
int outgoing_seq_id; /**< Fragment sequence ID of the current
|
||||
* fragmented packet waiting to be sent.
|
||||
*
|
||||
* All parts of a fragmented packet
|
||||
|
|
@ -152,10 +152,10 @@ struct fragment_master {
|
|||
* 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. */
|
||||
int outgoing_frag_size; /**< Size in bytes of each part to be
|
||||
#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.
|
||||
*
|
||||
|
|
@ -167,19 +167,19 @@ struct fragment_master {
|
|||
* FRAG_YES_LAST) using the \c
|
||||
* FRAG_SIZE_MASK and \c FRAG_SIZE_SHIFT
|
||||
* bits. */
|
||||
int outgoing_frag_id; /**< The fragment ID of the next part to
|
||||
int outgoing_frag_id; /**< The fragment ID of the next part to
|
||||
* be sent. Must have a value between 0
|
||||
* and \c MAX_FRAGS-1. */
|
||||
struct buffer outgoing; /**< Buffer containing the remaining parts
|
||||
struct buffer outgoing; /**< Buffer containing the remaining parts
|
||||
* of the fragmented packet being sent. */
|
||||
struct buffer outgoing_return;
|
||||
/**< Buffer used by \c
|
||||
* fragment_ready_to_send() to return a
|
||||
* part to send. */
|
||||
struct buffer outgoing_return;
|
||||
/**< Buffer used by \c
|
||||
* fragment_ready_to_send() to return a
|
||||
* part to send. */
|
||||
|
||||
struct fragment_list incoming;
|
||||
/**< List of structures for reassembling
|
||||
* incoming packets. */
|
||||
struct fragment_list incoming;
|
||||
/**< List of structures for reassembling
|
||||
* incoming packets. */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -189,19 +189,19 @@ struct fragment_master {
|
|||
*//** @{ *//*************************************/
|
||||
|
||||
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. */
|
||||
/**< 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
|
||||
|
|
@ -218,13 +218,13 @@ typedef uint32_t fragment_header_type;
|
|||
* size. */
|
||||
|
||||
#define FRAG_SEQ_ID_MASK 0x000000ff
|
||||
/**< Bit mask for %fragment sequence ID. */
|
||||
/**< 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. */
|
||||
/**< Bit mask for %fragment ID. */
|
||||
#define FRAG_ID_SHIFT 10
|
||||
/**< Bit shift for %fragment ID. */
|
||||
/**< Bit shift for %fragment ID. */
|
||||
|
||||
/*
|
||||
* FRAG_SIZE 14 bits
|
||||
|
|
@ -236,12 +236,12 @@ typedef uint32_t fragment_header_type;
|
|||
* to be the actual %fragment size received.
|
||||
*/
|
||||
#define FRAG_SIZE_MASK 0x00003fff
|
||||
/**< Bit mask for %fragment size. */
|
||||
/**< Bit mask for %fragment size. */
|
||||
#define FRAG_SIZE_SHIFT 15
|
||||
/**< Bit shift for %fragment size. */
|
||||
/**< 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. */
|
||||
/**< Bit mask for %fragment size rounding. */
|
||||
|
||||
/*
|
||||
* FRAG_EXTRA 16 bits
|
||||
|
|
@ -249,9 +249,9 @@ typedef uint32_t fragment_header_type;
|
|||
* 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. */
|
||||
/**< Bit mask for extra bits. */
|
||||
#define FRAG_EXTRA_SHIFT 15
|
||||
/**< Bit shift for extra bits. */
|
||||
/**< Bit shift for extra bits. */
|
||||
|
||||
/** @} name Fragment header *//********************************************/
|
||||
|
||||
|
|
@ -271,7 +271,7 @@ typedef uint32_t fragment_header_type;
|
|||
*
|
||||
* @return A pointer to the new \c fragment_master structure.
|
||||
*/
|
||||
struct fragment_master *fragment_init (struct frame *frame);
|
||||
struct fragment_master *fragment_init(struct frame *frame);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -283,7 +283,7 @@ struct fragment_master *fragment_init (struct frame *frame);
|
|||
* tunnel, used to determine how much memory to
|
||||
* allocate for each packet buffer.
|
||||
*/
|
||||
void fragment_frame_init (struct fragment_master *f, const struct frame *frame);
|
||||
void fragment_frame_init(struct fragment_master *f, const struct frame *frame);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -291,7 +291,7 @@ void fragment_frame_init (struct fragment_master *f, const struct frame *frame);
|
|||
*
|
||||
* @param f - The \c fragment_master structure to free.
|
||||
*/
|
||||
void fragment_free (struct fragment_master *f);
|
||||
void fragment_free(struct fragment_master *f);
|
||||
|
||||
/** @} name Functions for initialization and cleanup *//*******************/
|
||||
|
||||
|
|
@ -340,8 +340,8 @@ void fragment_free (struct fragment_master *f);
|
|||
* complete. If an error occurs during processing, the buffer length
|
||||
* is also set to zero.
|
||||
*/
|
||||
void fragment_incoming (struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame* frame);
|
||||
void fragment_incoming(struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame *frame);
|
||||
|
||||
/** @} name Functions for processing packets received from a VPN tunnel */
|
||||
|
||||
|
|
@ -391,8 +391,8 @@ void fragment_incoming (struct fragment_master *f, struct buffer *buf,
|
|||
* cases a fragmentation header will have been prepended to inform the
|
||||
* remote peer how to handle the packet.
|
||||
*/
|
||||
void fragment_outgoing (struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame* frame);
|
||||
void fragment_outgoing(struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame *frame);
|
||||
|
||||
/**
|
||||
* Check whether outgoing fragments are ready to be send, and if so make
|
||||
|
|
@ -421,8 +421,8 @@ void fragment_outgoing (struct fragment_master *f, struct buffer *buf,
|
|||
* @li False, if there are no outgoing fragmented parts waiting to be
|
||||
* sent.
|
||||
*/
|
||||
bool fragment_ready_to_send (struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame* frame);
|
||||
bool fragment_ready_to_send(struct fragment_master *f, struct buffer *buf,
|
||||
const struct frame *frame);
|
||||
|
||||
/**
|
||||
* Check whether a \c fragment_master structure contains fragments ready
|
||||
|
|
@ -436,15 +436,15 @@ bool fragment_ready_to_send (struct fragment_master *f, struct buffer *buf,
|
|||
* @li False, otherwise.
|
||||
*/
|
||||
static inline bool
|
||||
fragment_outgoing_defined (struct fragment_master *f)
|
||||
fragment_outgoing_defined(struct fragment_master *f)
|
||||
{
|
||||
return f->outgoing.len > 0;
|
||||
return f->outgoing.len > 0;
|
||||
}
|
||||
|
||||
/** @} name Functions for processing packets going out through a VPN tunnel */
|
||||
|
||||
|
||||
void fragment_wakeup (struct fragment_master *f, struct frame *frame);
|
||||
void fragment_wakeup(struct fragment_master *f, struct frame *frame);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
@ -463,10 +463,12 @@ void fragment_wakeup (struct fragment_master *f, struct frame *frame);
|
|||
* tunnel.
|
||||
*/
|
||||
static inline void
|
||||
fragment_housekeeping (struct fragment_master *f, struct frame *frame, struct timeval *tv)
|
||||
fragment_housekeeping(struct fragment_master *f, struct frame *frame, struct timeval *tv)
|
||||
{
|
||||
if (event_timeout_trigger (&f->wakeup, tv, ETT_DEFAULT))
|
||||
fragment_wakeup (f, frame);
|
||||
if (event_timeout_trigger(&f->wakeup, tv, ETT_DEFAULT))
|
||||
{
|
||||
fragment_wakeup(f, frame);
|
||||
}
|
||||
}
|
||||
|
||||
/** @} name Functions for regular housekeeping *//*************************/
|
||||
|
|
@ -475,5 +477,5 @@ fragment_housekeeping (struct fragment_master *f, struct frame *frame, struct ti
|
|||
/** @} addtogroup fragmentation *//****************************************/
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif /* ifdef ENABLE_FRAGMENT */
|
||||
#endif /* ifndef FRAGMENT_H */
|
||||
|
|
|
|||
|
|
@ -82,32 +82,34 @@ static const int down_high[] = { 10, 60, 120 };
|
|||
* { number of packets, packet size }
|
||||
*/
|
||||
static const struct packet_flood_parms packet_flood_data[] =
|
||||
{{10, 100}, {10, 1500}, {100, 1500}};
|
||||
{{10, 100}, {10, 1500}, {100, 1500}};
|
||||
|
||||
struct packet_flood_parms
|
||||
get_packet_flood_parms (int level)
|
||||
get_packet_flood_parms(int level)
|
||||
{
|
||||
ASSERT (level > 0 && level < 4);
|
||||
return packet_flood_data [level - 1];
|
||||
ASSERT(level > 0 && level < 4);
|
||||
return packet_flood_data [level - 1];
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true with probability 1/n
|
||||
*/
|
||||
static bool flip(int n) {
|
||||
return (get_random() % n) == 0;
|
||||
static bool
|
||||
flip(int n) {
|
||||
return (get_random() % n) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return uniformly distributed random number between
|
||||
* low and high.
|
||||
*/
|
||||
static int roll(int low, int high) {
|
||||
int ret;
|
||||
ASSERT (low <= high);
|
||||
ret = low + (get_random() % (high - low + 1));
|
||||
ASSERT (ret >= low && ret <= high);
|
||||
return ret;
|
||||
static int
|
||||
roll(int low, int high) {
|
||||
int ret;
|
||||
ASSERT(low <= high);
|
||||
ret = low + (get_random() % (high - low + 1));
|
||||
ASSERT(ret >= low && ret <= high);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool initialized; /* GLOBAL */
|
||||
|
|
@ -118,104 +120,118 @@ static time_t next; /* GLOBAL */
|
|||
* Return false if we should drop a packet.
|
||||
*/
|
||||
bool
|
||||
ask_gremlin (int flags)
|
||||
ask_gremlin(int flags)
|
||||
{
|
||||
const int up_down_level = GREMLIN_UP_DOWN_LEVEL (flags);
|
||||
const int drop_level = GREMLIN_DROP_LEVEL (flags);
|
||||
const int up_down_level = GREMLIN_UP_DOWN_LEVEL(flags);
|
||||
const int drop_level = GREMLIN_DROP_LEVEL(flags);
|
||||
|
||||
if (!initialized)
|
||||
if (!initialized)
|
||||
{
|
||||
initialized = true;
|
||||
initialized = true;
|
||||
|
||||
if (up_down_level)
|
||||
up = false;
|
||||
else
|
||||
up = true;
|
||||
if (up_down_level)
|
||||
{
|
||||
up = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
up = true;
|
||||
}
|
||||
|
||||
next = now;
|
||||
next = now;
|
||||
}
|
||||
|
||||
if (up_down_level) /* change up/down state? */
|
||||
if (up_down_level) /* change up/down state? */
|
||||
{
|
||||
if (now >= next)
|
||||
{
|
||||
int delta;
|
||||
if (up)
|
||||
{
|
||||
delta = roll (down_low[up_down_level-1], down_high[up_down_level-1]);
|
||||
up = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = roll (up_low[up_down_level-1], up_high[up_down_level-1]);
|
||||
up = true;
|
||||
}
|
||||
|
||||
msg (D_GREMLIN,
|
||||
"GREMLIN: CONNECTION GOING %s FOR %d SECONDS",
|
||||
(up ? "UP" : "DOWN"),
|
||||
delta);
|
||||
next = now + delta;
|
||||
}
|
||||
if (now >= next)
|
||||
{
|
||||
int delta;
|
||||
if (up)
|
||||
{
|
||||
delta = roll(down_low[up_down_level-1], down_high[up_down_level-1]);
|
||||
up = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = roll(up_low[up_down_level-1], up_high[up_down_level-1]);
|
||||
up = true;
|
||||
}
|
||||
|
||||
msg(D_GREMLIN,
|
||||
"GREMLIN: CONNECTION GOING %s FOR %d SECONDS",
|
||||
(up ? "UP" : "DOWN"),
|
||||
delta);
|
||||
next = now + delta;
|
||||
}
|
||||
}
|
||||
|
||||
if (drop_level)
|
||||
if (drop_level)
|
||||
{
|
||||
if (up && flip (drop_freq[drop_level-1]))
|
||||
{
|
||||
dmsg (D_GREMLIN_VERBOSE, "GREMLIN: Random packet drop");
|
||||
return false;
|
||||
}
|
||||
if (up && flip(drop_freq[drop_level-1]))
|
||||
{
|
||||
dmsg(D_GREMLIN_VERBOSE, "GREMLIN: Random packet drop");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return up;
|
||||
return up;
|
||||
}
|
||||
|
||||
/*
|
||||
* Possibly corrupt a packet.
|
||||
*/
|
||||
void corrupt_gremlin (struct buffer *buf, int flags) {
|
||||
const int corrupt_level = GREMLIN_CORRUPT_LEVEL (flags);
|
||||
if (corrupt_level)
|
||||
void
|
||||
corrupt_gremlin(struct buffer *buf, int flags) {
|
||||
const int corrupt_level = GREMLIN_CORRUPT_LEVEL(flags);
|
||||
if (corrupt_level)
|
||||
{
|
||||
if (flip (corrupt_freq[corrupt_level-1]))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (buf->len > 0)
|
||||
{
|
||||
uint8_t r = roll (0, 255);
|
||||
int method = roll (0, 5);
|
||||
if (flip(corrupt_freq[corrupt_level-1]))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (buf->len > 0)
|
||||
{
|
||||
uint8_t r = roll(0, 255);
|
||||
int method = roll(0, 5);
|
||||
|
||||
switch (method) {
|
||||
case 0: /* corrupt the first byte */
|
||||
*BPTR (buf) = r;
|
||||
break;
|
||||
case 1: /* corrupt the last byte */
|
||||
*(BPTR (buf) + buf->len - 1) = r;
|
||||
break;
|
||||
case 2: /* corrupt a random byte */
|
||||
*(BPTR(buf) + roll (0, buf->len - 1)) = r;
|
||||
break;
|
||||
case 3: /* append a random byte */
|
||||
buf_write (buf, &r, 1);
|
||||
break;
|
||||
case 4: /* reduce length by 1 */
|
||||
--buf->len;
|
||||
break;
|
||||
case 5: /* reduce length by a random amount */
|
||||
buf->len -= roll (0, buf->len - 1);
|
||||
break;
|
||||
}
|
||||
dmsg (D_GREMLIN_VERBOSE, "GREMLIN: Packet Corruption, method=%d", method);
|
||||
}
|
||||
else
|
||||
break;
|
||||
} while (flip (2)); /* a 50% chance we will corrupt again */
|
||||
}
|
||||
switch (method) {
|
||||
case 0: /* corrupt the first byte */
|
||||
*BPTR(buf) = r;
|
||||
break;
|
||||
|
||||
case 1: /* corrupt the last byte */
|
||||
*(BPTR(buf) + buf->len - 1) = r;
|
||||
break;
|
||||
|
||||
case 2: /* corrupt a random byte */
|
||||
*(BPTR(buf) + roll(0, buf->len - 1)) = r;
|
||||
break;
|
||||
|
||||
case 3: /* append a random byte */
|
||||
buf_write(buf, &r, 1);
|
||||
break;
|
||||
|
||||
case 4: /* reduce length by 1 */
|
||||
--buf->len;
|
||||
break;
|
||||
|
||||
case 5: /* reduce length by a random amount */
|
||||
buf->len -= roll(0, buf->len - 1);
|
||||
break;
|
||||
}
|
||||
dmsg(D_GREMLIN_VERBOSE, "GREMLIN: Packet Corruption, method=%d", method);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (flip(2)); /* a 50% chance we will corrupt again */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static void dummy(void) {}
|
||||
#endif
|
||||
#else /* ifdef ENABLE_DEBUG */
|
||||
static void
|
||||
dummy(void) {
|
||||
}
|
||||
#endif /* ifdef ENABLE_DEBUG */
|
||||
|
|
|
|||
|
|
@ -60,13 +60,15 @@
|
|||
|
||||
struct packet_flood_parms
|
||||
{
|
||||
int n_packets;
|
||||
int packet_size;
|
||||
int n_packets;
|
||||
int packet_size;
|
||||
};
|
||||
|
||||
bool ask_gremlin (int flags);
|
||||
void corrupt_gremlin (struct buffer* buf, int flags);
|
||||
struct packet_flood_parms get_packet_flood_parms (int level);
|
||||
bool ask_gremlin(int flags);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
void corrupt_gremlin(struct buffer *buf, int flags);
|
||||
|
||||
struct packet_flood_parms get_packet_flood_parms(int level);
|
||||
|
||||
#endif /* ifdef ENABLE_DEBUG */
|
||||
#endif /* ifndef GREMLIN_H */
|
||||
|
|
|
|||
|
|
@ -40,101 +40,107 @@
|
|||
#if P2MP_SERVER
|
||||
|
||||
static const char *
|
||||
print_netmask (int netbits, struct gc_arena *gc)
|
||||
print_netmask(int netbits, struct gc_arena *gc)
|
||||
{
|
||||
struct buffer out = alloc_buf_gc (128, gc);
|
||||
const in_addr_t netmask = netbits_to_netmask (netbits);
|
||||
struct buffer out = alloc_buf_gc(128, gc);
|
||||
const in_addr_t netmask = netbits_to_netmask(netbits);
|
||||
|
||||
buf_printf (&out, "%s (/%d)", print_in_addr_t (netmask, 0, gc), netbits);
|
||||
buf_printf(&out, "%s (/%d)", print_in_addr_t(netmask, 0, gc), netbits);
|
||||
|
||||
return BSTR (&out);
|
||||
return BSTR(&out);
|
||||
}
|
||||
|
||||
static const char *
|
||||
print_opt_route_gateway (const in_addr_t route_gateway, struct gc_arena *gc)
|
||||
print_opt_route_gateway(const in_addr_t route_gateway, struct gc_arena *gc)
|
||||
{
|
||||
struct buffer out = alloc_buf_gc (128, gc);
|
||||
ASSERT (route_gateway);
|
||||
buf_printf (&out, "route-gateway %s", print_in_addr_t (route_gateway, 0, gc));
|
||||
return BSTR (&out);
|
||||
struct buffer out = alloc_buf_gc(128, gc);
|
||||
ASSERT(route_gateway);
|
||||
buf_printf(&out, "route-gateway %s", print_in_addr_t(route_gateway, 0, gc));
|
||||
return BSTR(&out);
|
||||
}
|
||||
|
||||
static const char *
|
||||
print_opt_route_gateway_dhcp (struct gc_arena *gc)
|
||||
print_opt_route_gateway_dhcp(struct gc_arena *gc)
|
||||
{
|
||||
struct buffer out = alloc_buf_gc (32, gc);
|
||||
buf_printf (&out, "route-gateway dhcp");
|
||||
return BSTR (&out);
|
||||
struct buffer out = alloc_buf_gc(32, gc);
|
||||
buf_printf(&out, "route-gateway dhcp");
|
||||
return BSTR(&out);
|
||||
}
|
||||
|
||||
static const char *
|
||||
print_opt_route (const in_addr_t network, const in_addr_t netmask, struct gc_arena *gc)
|
||||
print_opt_route(const in_addr_t network, const in_addr_t netmask, struct gc_arena *gc)
|
||||
{
|
||||
struct buffer out = alloc_buf_gc (128, gc);
|
||||
ASSERT (network);
|
||||
struct buffer out = alloc_buf_gc(128, gc);
|
||||
ASSERT(network);
|
||||
|
||||
if (netmask)
|
||||
buf_printf (&out, "route %s %s",
|
||||
print_in_addr_t (network, 0, gc),
|
||||
print_in_addr_t (netmask, 0, gc));
|
||||
else
|
||||
buf_printf (&out, "route %s",
|
||||
print_in_addr_t (network, 0, gc));
|
||||
if (netmask)
|
||||
{
|
||||
buf_printf(&out, "route %s %s",
|
||||
print_in_addr_t(network, 0, gc),
|
||||
print_in_addr_t(netmask, 0, gc));
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_printf(&out, "route %s",
|
||||
print_in_addr_t(network, 0, gc));
|
||||
}
|
||||
|
||||
return BSTR (&out);
|
||||
return BSTR(&out);
|
||||
}
|
||||
|
||||
static const char *
|
||||
print_opt_topology (const int topology, struct gc_arena *gc)
|
||||
print_opt_topology(const int topology, struct gc_arena *gc)
|
||||
{
|
||||
struct buffer out = alloc_buf_gc (128, gc);
|
||||
struct buffer out = alloc_buf_gc(128, gc);
|
||||
|
||||
buf_printf (&out, "topology %s", print_topology (topology));
|
||||
buf_printf(&out, "topology %s", print_topology(topology));
|
||||
|
||||
return BSTR (&out);
|
||||
return BSTR(&out);
|
||||
}
|
||||
|
||||
static const char *
|
||||
print_str_int (const char *str, const int i, struct gc_arena *gc)
|
||||
print_str_int(const char *str, const int i, struct gc_arena *gc)
|
||||
{
|
||||
struct buffer out = alloc_buf_gc (128, gc);
|
||||
buf_printf (&out, "%s %d", str, i);
|
||||
return BSTR (&out);
|
||||
struct buffer out = alloc_buf_gc(128, gc);
|
||||
buf_printf(&out, "%s %d", str, i);
|
||||
return BSTR(&out);
|
||||
}
|
||||
|
||||
static const char *
|
||||
print_str (const char *str, struct gc_arena *gc)
|
||||
print_str(const char *str, struct gc_arena *gc)
|
||||
{
|
||||
struct buffer out = alloc_buf_gc (128, gc);
|
||||
buf_printf (&out, "%s", str);
|
||||
return BSTR (&out);
|
||||
struct buffer out = alloc_buf_gc(128, gc);
|
||||
buf_printf(&out, "%s", str);
|
||||
return BSTR(&out);
|
||||
}
|
||||
|
||||
static void
|
||||
helper_add_route (const in_addr_t network, const in_addr_t netmask, struct options *o)
|
||||
helper_add_route(const in_addr_t network, const in_addr_t netmask, struct options *o)
|
||||
{
|
||||
rol_check_alloc (o);
|
||||
add_route_to_option_list (o->routes,
|
||||
print_in_addr_t (network, 0, &o->gc),
|
||||
print_in_addr_t (netmask, 0, &o->gc),
|
||||
NULL,
|
||||
NULL);
|
||||
rol_check_alloc(o);
|
||||
add_route_to_option_list(o->routes,
|
||||
print_in_addr_t(network, 0, &o->gc),
|
||||
print_in_addr_t(netmask, 0, &o->gc),
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
verify_common_subnet (const char *opt, const in_addr_t a, const in_addr_t b, const in_addr_t subnet)
|
||||
verify_common_subnet(const char *opt, const in_addr_t a, const in_addr_t b, const in_addr_t subnet)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
if ((a & subnet) != (b & subnet))
|
||||
msg (M_USAGE, "%s IP addresses %s and %s are not in the same %s subnet",
|
||||
opt,
|
||||
print_in_addr_t (a, 0, &gc),
|
||||
print_in_addr_t (b, 0, &gc),
|
||||
print_in_addr_t (subnet, 0, &gc));
|
||||
gc_free (&gc);
|
||||
struct gc_arena gc = gc_new();
|
||||
if ((a & subnet) != (b & subnet))
|
||||
{
|
||||
msg(M_USAGE, "%s IP addresses %s and %s are not in the same %s subnet",
|
||||
opt,
|
||||
print_in_addr_t(a, 0, &gc),
|
||||
print_in_addr_t(b, 0, &gc),
|
||||
print_in_addr_t(subnet, 0, &gc));
|
||||
}
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* if P2MP_SERVER */
|
||||
|
||||
/*
|
||||
* Process server, server-bridge, and client helper
|
||||
|
|
@ -142,309 +148,349 @@ verify_common_subnet (const char *opt, const in_addr_t a, const in_addr_t b, con
|
|||
* parsed and placed in struct options.
|
||||
*/
|
||||
void
|
||||
helper_client_server (struct options *o)
|
||||
helper_client_server(struct options *o)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct gc_arena gc = gc_new();
|
||||
|
||||
#if P2MP
|
||||
#if P2MP_SERVER
|
||||
|
||||
/*
|
||||
* Get tun/tap/null device type
|
||||
*/
|
||||
const int dev = dev_type_enum (o->dev, o->dev_type);
|
||||
const int topology = o->topology;
|
||||
* Get tun/tap/null device type
|
||||
*/
|
||||
const int dev = dev_type_enum(o->dev, o->dev_type);
|
||||
const int topology = o->topology;
|
||||
|
||||
/*
|
||||
*
|
||||
* HELPER DIRECTIVE for IPv6
|
||||
*
|
||||
* server-ipv6 2001:db8::/64
|
||||
*
|
||||
* EXPANDS TO:
|
||||
*
|
||||
* tun-ipv6
|
||||
* push "tun-ipv6"
|
||||
* ifconfig-ipv6 2001:db8::1 2001:db8::2
|
||||
* if !nopool:
|
||||
* ifconfig-ipv6-pool 2001:db8::1000/64
|
||||
*
|
||||
*/
|
||||
if ( o->server_ipv6_defined )
|
||||
{
|
||||
if ( ! o->server_defined )
|
||||
{
|
||||
msg (M_USAGE, "--server-ipv6 must be used together with --server");
|
||||
}
|
||||
if ( o->server_flags & SF_NOPOOL )
|
||||
{
|
||||
msg( M_USAGE, "--server-ipv6 is incompatible with 'nopool' option" );
|
||||
}
|
||||
if ( o->ifconfig_ipv6_pool_defined )
|
||||
{
|
||||
msg( M_USAGE, "--server-ipv6 already defines an ifconfig-ipv6-pool, so you can't also specify --ifconfig-pool explicitly");
|
||||
}
|
||||
/*
|
||||
*
|
||||
* HELPER DIRECTIVE for IPv6
|
||||
*
|
||||
* server-ipv6 2001:db8::/64
|
||||
*
|
||||
* EXPANDS TO:
|
||||
*
|
||||
* tun-ipv6
|
||||
* push "tun-ipv6"
|
||||
* ifconfig-ipv6 2001:db8::1 2001:db8::2
|
||||
* if !nopool:
|
||||
* ifconfig-ipv6-pool 2001:db8::1000/64
|
||||
*
|
||||
*/
|
||||
if (o->server_ipv6_defined)
|
||||
{
|
||||
if (!o->server_defined)
|
||||
{
|
||||
msg(M_USAGE, "--server-ipv6 must be used together with --server");
|
||||
}
|
||||
if (o->server_flags & SF_NOPOOL)
|
||||
{
|
||||
msg( M_USAGE, "--server-ipv6 is incompatible with 'nopool' option" );
|
||||
}
|
||||
if (o->ifconfig_ipv6_pool_defined)
|
||||
{
|
||||
msg( M_USAGE, "--server-ipv6 already defines an ifconfig-ipv6-pool, so you can't also specify --ifconfig-pool explicitly");
|
||||
}
|
||||
|
||||
/* local ifconfig is "base address + 1" and "+2" */
|
||||
o->ifconfig_ipv6_local =
|
||||
print_in6_addr( add_in6_addr( o->server_network_ipv6, 1), 0, &o->gc );
|
||||
o->ifconfig_ipv6_remote =
|
||||
print_in6_addr( add_in6_addr( o->server_network_ipv6, 2), 0, &o->gc );
|
||||
o->ifconfig_ipv6_netbits = o->server_netbits_ipv6;
|
||||
o->ifconfig_ipv6_local =
|
||||
print_in6_addr( add_in6_addr( o->server_network_ipv6, 1), 0, &o->gc );
|
||||
o->ifconfig_ipv6_remote =
|
||||
print_in6_addr( add_in6_addr( o->server_network_ipv6, 2), 0, &o->gc );
|
||||
o->ifconfig_ipv6_netbits = o->server_netbits_ipv6;
|
||||
|
||||
/* pool starts at "base address + 0x1000" - leave enough room */
|
||||
ASSERT( o->server_netbits_ipv6 <= 112 ); /* want 16 bits */
|
||||
/* pool starts at "base address + 0x1000" - leave enough room */
|
||||
ASSERT( o->server_netbits_ipv6 <= 112 ); /* want 16 bits */
|
||||
|
||||
o->ifconfig_ipv6_pool_defined = true;
|
||||
o->ifconfig_ipv6_pool_base =
|
||||
add_in6_addr( o->server_network_ipv6, 0x1000 );
|
||||
o->ifconfig_ipv6_pool_netbits = o->server_netbits_ipv6;
|
||||
o->ifconfig_ipv6_pool_defined = true;
|
||||
o->ifconfig_ipv6_pool_base =
|
||||
add_in6_addr( o->server_network_ipv6, 0x1000 );
|
||||
o->ifconfig_ipv6_pool_netbits = o->server_netbits_ipv6;
|
||||
|
||||
push_option( o, "tun-ipv6", M_USAGE );
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* HELPER DIRECTIVE:
|
||||
*
|
||||
* server 10.8.0.0 255.255.255.0
|
||||
*
|
||||
* EXPANDS TO:
|
||||
*
|
||||
* mode server
|
||||
* tls-server
|
||||
* push "topology [topology]"
|
||||
*
|
||||
* if tun AND (topology == net30 OR topology == p2p):
|
||||
* ifconfig 10.8.0.1 10.8.0.2
|
||||
* if !nopool:
|
||||
* ifconfig-pool 10.8.0.4 10.8.0.251
|
||||
* route 10.8.0.0 255.255.255.0
|
||||
* if client-to-client:
|
||||
* push "route 10.8.0.0 255.255.255.0"
|
||||
* else if topology == net30:
|
||||
* push "route 10.8.0.1"
|
||||
*
|
||||
* if tap OR (tun AND topology == subnet):
|
||||
* ifconfig 10.8.0.1 255.255.255.0
|
||||
* if !nopool:
|
||||
* ifconfig-pool 10.8.0.2 10.8.0.253 255.255.255.0
|
||||
* push "route-gateway 10.8.0.1"
|
||||
* if route-gateway unset:
|
||||
* route-gateway 10.8.0.2
|
||||
*/
|
||||
|
||||
if (o->server_defined)
|
||||
{
|
||||
int netbits = -2;
|
||||
bool status = false;
|
||||
|
||||
if (o->client)
|
||||
msg (M_USAGE, "--server and --client cannot be used together");
|
||||
|
||||
if (o->server_bridge_defined || o->server_bridge_proxy_dhcp)
|
||||
msg (M_USAGE, "--server and --server-bridge cannot be used together");
|
||||
|
||||
if (o->shared_secret_file)
|
||||
msg (M_USAGE, "--server and --secret cannot be used together (you must use SSL/TLS keys)");
|
||||
|
||||
if (!(o->server_flags & SF_NOPOOL) && o->ifconfig_pool_defined)
|
||||
msg (M_USAGE, "--server already defines an ifconfig-pool, so you can't also specify --ifconfig-pool explicitly");
|
||||
|
||||
if (!(dev == DEV_TYPE_TAP || dev == DEV_TYPE_TUN))
|
||||
msg (M_USAGE, "--server directive only makes sense with --dev tun or --dev tap");
|
||||
|
||||
status = netmask_to_netbits (o->server_network, o->server_netmask, &netbits);
|
||||
if (!status)
|
||||
msg (M_USAGE, "--server directive network/netmask combination is invalid");
|
||||
|
||||
if (netbits < 0)
|
||||
msg (M_USAGE, "--server directive netmask is invalid");
|
||||
|
||||
if (netbits < IFCONFIG_POOL_MIN_NETBITS)
|
||||
msg (M_USAGE, "--server directive netmask allows for too many host addresses (subnet must be %s or higher)",
|
||||
print_netmask (IFCONFIG_POOL_MIN_NETBITS, &gc));
|
||||
|
||||
if (dev == DEV_TYPE_TUN)
|
||||
{
|
||||
int pool_end_reserve = 4;
|
||||
|
||||
if (netbits > 29)
|
||||
msg (M_USAGE, "--server directive when used with --dev tun must define a subnet of %s or lower",
|
||||
print_netmask (29, &gc));
|
||||
|
||||
if (netbits == 29)
|
||||
pool_end_reserve = 0;
|
||||
|
||||
o->mode = MODE_SERVER;
|
||||
o->tls_server = true;
|
||||
|
||||
if (topology == TOP_NET30 || topology == TOP_P2P)
|
||||
{
|
||||
o->ifconfig_local = print_in_addr_t (o->server_network + 1, 0, &o->gc);
|
||||
o->ifconfig_remote_netmask = print_in_addr_t (o->server_network + 2, 0, &o->gc);
|
||||
|
||||
if (!(o->server_flags & SF_NOPOOL))
|
||||
{
|
||||
o->ifconfig_pool_defined = true;
|
||||
o->ifconfig_pool_start = o->server_network + 4;
|
||||
o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - pool_end_reserve;
|
||||
ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
|
||||
}
|
||||
|
||||
helper_add_route (o->server_network, o->server_netmask, o);
|
||||
if (o->enable_c2c)
|
||||
push_option (o, print_opt_route (o->server_network, o->server_netmask, &o->gc), M_USAGE);
|
||||
else if (topology == TOP_NET30)
|
||||
push_option (o, print_opt_route (o->server_network + 1, 0, &o->gc), M_USAGE);
|
||||
}
|
||||
else if (topology == TOP_SUBNET)
|
||||
{
|
||||
o->ifconfig_local = print_in_addr_t (o->server_network + 1, 0, &o->gc);
|
||||
o->ifconfig_remote_netmask = print_in_addr_t (o->server_netmask, 0, &o->gc);
|
||||
|
||||
if (!(o->server_flags & SF_NOPOOL))
|
||||
{
|
||||
o->ifconfig_pool_defined = true;
|
||||
o->ifconfig_pool_start = o->server_network + 2;
|
||||
o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - 2;
|
||||
ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
|
||||
}
|
||||
o->ifconfig_pool_netmask = o->server_netmask;
|
||||
|
||||
push_option (o, print_opt_route_gateway (o->server_network + 1, &o->gc), M_USAGE);
|
||||
if (!o->route_default_gateway)
|
||||
o->route_default_gateway = print_in_addr_t (o->server_network + 2, 0, &o->gc);
|
||||
}
|
||||
else
|
||||
ASSERT (0);
|
||||
|
||||
push_option (o, print_opt_topology (topology, &o->gc), M_USAGE);
|
||||
}
|
||||
else if (dev == DEV_TYPE_TAP)
|
||||
{
|
||||
if (netbits > 30)
|
||||
msg (M_USAGE, "--server directive when used with --dev tap must define a subnet of %s or lower",
|
||||
print_netmask (30, &gc));
|
||||
|
||||
o->mode = MODE_SERVER;
|
||||
o->tls_server = true;
|
||||
o->ifconfig_local = print_in_addr_t (o->server_network + 1, 0, &o->gc);
|
||||
o->ifconfig_remote_netmask = print_in_addr_t (o->server_netmask, 0, &o->gc);
|
||||
|
||||
if (!(o->server_flags & SF_NOPOOL))
|
||||
{
|
||||
o->ifconfig_pool_defined = true;
|
||||
o->ifconfig_pool_start = o->server_network + 2;
|
||||
o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - 1;
|
||||
ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
|
||||
}
|
||||
o->ifconfig_pool_netmask = o->server_netmask;
|
||||
|
||||
push_option (o, print_opt_route_gateway (o->server_network + 1, &o->gc), M_USAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT (0);
|
||||
}
|
||||
|
||||
/* set push-ifconfig-constraint directive */
|
||||
if ((dev == DEV_TYPE_TAP || topology == TOP_SUBNET))
|
||||
{
|
||||
o->push_ifconfig_constraint_defined = true;
|
||||
o->push_ifconfig_constraint_network = o->server_network;
|
||||
o->push_ifconfig_constraint_netmask = o->server_netmask;
|
||||
}
|
||||
push_option( o, "tun-ipv6", M_USAGE );
|
||||
}
|
||||
|
||||
/*
|
||||
* HELPER DIRECTIVE:
|
||||
*
|
||||
* server-bridge 10.8.0.4 255.255.255.0 10.8.0.128 10.8.0.254
|
||||
*
|
||||
* EXPANDS TO:
|
||||
*
|
||||
* mode server
|
||||
* tls-server
|
||||
*
|
||||
* ifconfig-pool 10.8.0.128 10.8.0.254 255.255.255.0
|
||||
* push "route-gateway 10.8.0.4"
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* server-bridge
|
||||
*
|
||||
* EXPANDS TO:
|
||||
*
|
||||
* mode server
|
||||
* tls-server
|
||||
*
|
||||
* if !nogw:
|
||||
* push "route-gateway dhcp"
|
||||
*/
|
||||
else if (o->server_bridge_defined | o->server_bridge_proxy_dhcp)
|
||||
/*
|
||||
*
|
||||
* HELPER DIRECTIVE:
|
||||
*
|
||||
* server 10.8.0.0 255.255.255.0
|
||||
*
|
||||
* EXPANDS TO:
|
||||
*
|
||||
* mode server
|
||||
* tls-server
|
||||
* push "topology [topology]"
|
||||
*
|
||||
* if tun AND (topology == net30 OR topology == p2p):
|
||||
* ifconfig 10.8.0.1 10.8.0.2
|
||||
* if !nopool:
|
||||
* ifconfig-pool 10.8.0.4 10.8.0.251
|
||||
* route 10.8.0.0 255.255.255.0
|
||||
* if client-to-client:
|
||||
* push "route 10.8.0.0 255.255.255.0"
|
||||
* else if topology == net30:
|
||||
* push "route 10.8.0.1"
|
||||
*
|
||||
* if tap OR (tun AND topology == subnet):
|
||||
* ifconfig 10.8.0.1 255.255.255.0
|
||||
* if !nopool:
|
||||
* ifconfig-pool 10.8.0.2 10.8.0.253 255.255.255.0
|
||||
* push "route-gateway 10.8.0.1"
|
||||
* if route-gateway unset:
|
||||
* route-gateway 10.8.0.2
|
||||
*/
|
||||
|
||||
if (o->server_defined)
|
||||
{
|
||||
if (o->client)
|
||||
msg (M_USAGE, "--server-bridge and --client cannot be used together");
|
||||
int netbits = -2;
|
||||
bool status = false;
|
||||
|
||||
if (!(o->server_flags & SF_NOPOOL) && o->ifconfig_pool_defined)
|
||||
msg (M_USAGE, "--server-bridge already defines an ifconfig-pool, so you can't also specify --ifconfig-pool explicitly");
|
||||
if (o->client)
|
||||
{
|
||||
msg(M_USAGE, "--server and --client cannot be used together");
|
||||
}
|
||||
|
||||
if (o->shared_secret_file)
|
||||
msg (M_USAGE, "--server-bridge and --secret cannot be used together (you must use SSL/TLS keys)");
|
||||
if (o->server_bridge_defined || o->server_bridge_proxy_dhcp)
|
||||
{
|
||||
msg(M_USAGE, "--server and --server-bridge cannot be used together");
|
||||
}
|
||||
|
||||
if (dev != DEV_TYPE_TAP)
|
||||
msg (M_USAGE, "--server-bridge directive only makes sense with --dev tap");
|
||||
if (o->shared_secret_file)
|
||||
{
|
||||
msg(M_USAGE, "--server and --secret cannot be used together (you must use SSL/TLS keys)");
|
||||
}
|
||||
|
||||
if (o->server_bridge_defined)
|
||||
{
|
||||
verify_common_subnet ("--server-bridge", o->server_bridge_ip, o->server_bridge_pool_start, o->server_bridge_netmask);
|
||||
verify_common_subnet ("--server-bridge", o->server_bridge_pool_start, o->server_bridge_pool_end, o->server_bridge_netmask);
|
||||
verify_common_subnet ("--server-bridge", o->server_bridge_ip, o->server_bridge_pool_end, o->server_bridge_netmask);
|
||||
}
|
||||
if (!(o->server_flags & SF_NOPOOL) && o->ifconfig_pool_defined)
|
||||
{
|
||||
msg(M_USAGE, "--server already defines an ifconfig-pool, so you can't also specify --ifconfig-pool explicitly");
|
||||
}
|
||||
|
||||
o->mode = MODE_SERVER;
|
||||
o->tls_server = true;
|
||||
if (!(dev == DEV_TYPE_TAP || dev == DEV_TYPE_TUN))
|
||||
{
|
||||
msg(M_USAGE, "--server directive only makes sense with --dev tun or --dev tap");
|
||||
}
|
||||
|
||||
if (o->server_bridge_defined)
|
||||
{
|
||||
o->ifconfig_pool_defined = true;
|
||||
o->ifconfig_pool_start = o->server_bridge_pool_start;
|
||||
o->ifconfig_pool_end = o->server_bridge_pool_end;
|
||||
ifconfig_pool_verify_range (M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
|
||||
o->ifconfig_pool_netmask = o->server_bridge_netmask;
|
||||
push_option (o, print_opt_route_gateway (o->server_bridge_ip, &o->gc), M_USAGE);
|
||||
}
|
||||
else if (o->server_bridge_proxy_dhcp && !(o->server_flags & SF_NO_PUSH_ROUTE_GATEWAY))
|
||||
{
|
||||
push_option (o, print_opt_route_gateway_dhcp (&o->gc), M_USAGE);
|
||||
}
|
||||
status = netmask_to_netbits(o->server_network, o->server_netmask, &netbits);
|
||||
if (!status)
|
||||
{
|
||||
msg(M_USAGE, "--server directive network/netmask combination is invalid");
|
||||
}
|
||||
|
||||
if (netbits < 0)
|
||||
{
|
||||
msg(M_USAGE, "--server directive netmask is invalid");
|
||||
}
|
||||
|
||||
if (netbits < IFCONFIG_POOL_MIN_NETBITS)
|
||||
{
|
||||
msg(M_USAGE, "--server directive netmask allows for too many host addresses (subnet must be %s or higher)",
|
||||
print_netmask(IFCONFIG_POOL_MIN_NETBITS, &gc));
|
||||
}
|
||||
|
||||
if (dev == DEV_TYPE_TUN)
|
||||
{
|
||||
int pool_end_reserve = 4;
|
||||
|
||||
if (netbits > 29)
|
||||
{
|
||||
msg(M_USAGE, "--server directive when used with --dev tun must define a subnet of %s or lower",
|
||||
print_netmask(29, &gc));
|
||||
}
|
||||
|
||||
if (netbits == 29)
|
||||
{
|
||||
pool_end_reserve = 0;
|
||||
}
|
||||
|
||||
o->mode = MODE_SERVER;
|
||||
o->tls_server = true;
|
||||
|
||||
if (topology == TOP_NET30 || topology == TOP_P2P)
|
||||
{
|
||||
o->ifconfig_local = print_in_addr_t(o->server_network + 1, 0, &o->gc);
|
||||
o->ifconfig_remote_netmask = print_in_addr_t(o->server_network + 2, 0, &o->gc);
|
||||
|
||||
if (!(o->server_flags & SF_NOPOOL))
|
||||
{
|
||||
o->ifconfig_pool_defined = true;
|
||||
o->ifconfig_pool_start = o->server_network + 4;
|
||||
o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - pool_end_reserve;
|
||||
ifconfig_pool_verify_range(M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
|
||||
}
|
||||
|
||||
helper_add_route(o->server_network, o->server_netmask, o);
|
||||
if (o->enable_c2c)
|
||||
{
|
||||
push_option(o, print_opt_route(o->server_network, o->server_netmask, &o->gc), M_USAGE);
|
||||
}
|
||||
else if (topology == TOP_NET30)
|
||||
{
|
||||
push_option(o, print_opt_route(o->server_network + 1, 0, &o->gc), M_USAGE);
|
||||
}
|
||||
}
|
||||
else if (topology == TOP_SUBNET)
|
||||
{
|
||||
o->ifconfig_local = print_in_addr_t(o->server_network + 1, 0, &o->gc);
|
||||
o->ifconfig_remote_netmask = print_in_addr_t(o->server_netmask, 0, &o->gc);
|
||||
|
||||
if (!(o->server_flags & SF_NOPOOL))
|
||||
{
|
||||
o->ifconfig_pool_defined = true;
|
||||
o->ifconfig_pool_start = o->server_network + 2;
|
||||
o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - 2;
|
||||
ifconfig_pool_verify_range(M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
|
||||
}
|
||||
o->ifconfig_pool_netmask = o->server_netmask;
|
||||
|
||||
push_option(o, print_opt_route_gateway(o->server_network + 1, &o->gc), M_USAGE);
|
||||
if (!o->route_default_gateway)
|
||||
{
|
||||
o->route_default_gateway = print_in_addr_t(o->server_network + 2, 0, &o->gc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
push_option(o, print_opt_topology(topology, &o->gc), M_USAGE);
|
||||
}
|
||||
else if (dev == DEV_TYPE_TAP)
|
||||
{
|
||||
if (netbits > 30)
|
||||
{
|
||||
msg(M_USAGE, "--server directive when used with --dev tap must define a subnet of %s or lower",
|
||||
print_netmask(30, &gc));
|
||||
}
|
||||
|
||||
o->mode = MODE_SERVER;
|
||||
o->tls_server = true;
|
||||
o->ifconfig_local = print_in_addr_t(o->server_network + 1, 0, &o->gc);
|
||||
o->ifconfig_remote_netmask = print_in_addr_t(o->server_netmask, 0, &o->gc);
|
||||
|
||||
if (!(o->server_flags & SF_NOPOOL))
|
||||
{
|
||||
o->ifconfig_pool_defined = true;
|
||||
o->ifconfig_pool_start = o->server_network + 2;
|
||||
o->ifconfig_pool_end = (o->server_network | ~o->server_netmask) - 1;
|
||||
ifconfig_pool_verify_range(M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
|
||||
}
|
||||
o->ifconfig_pool_netmask = o->server_netmask;
|
||||
|
||||
push_option(o, print_opt_route_gateway(o->server_network + 1, &o->gc), M_USAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
/* set push-ifconfig-constraint directive */
|
||||
if ((dev == DEV_TYPE_TAP || topology == TOP_SUBNET))
|
||||
{
|
||||
o->push_ifconfig_constraint_defined = true;
|
||||
o->push_ifconfig_constraint_network = o->server_network;
|
||||
o->push_ifconfig_constraint_netmask = o->server_netmask;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
/*
|
||||
* HELPER DIRECTIVE:
|
||||
*
|
||||
* server-bridge 10.8.0.4 255.255.255.0 10.8.0.128 10.8.0.254
|
||||
*
|
||||
* EXPANDS TO:
|
||||
*
|
||||
* mode server
|
||||
* tls-server
|
||||
*
|
||||
* ifconfig-pool 10.8.0.128 10.8.0.254 255.255.255.0
|
||||
* push "route-gateway 10.8.0.4"
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* server-bridge
|
||||
*
|
||||
* EXPANDS TO:
|
||||
*
|
||||
* mode server
|
||||
* tls-server
|
||||
*
|
||||
* if !nogw:
|
||||
* push "route-gateway dhcp"
|
||||
*/
|
||||
else if (o->server_bridge_defined | o->server_bridge_proxy_dhcp)
|
||||
{
|
||||
if (o->client)
|
||||
{
|
||||
msg(M_USAGE, "--server-bridge and --client cannot be used together");
|
||||
}
|
||||
|
||||
if (!(o->server_flags & SF_NOPOOL) && o->ifconfig_pool_defined)
|
||||
{
|
||||
msg(M_USAGE, "--server-bridge already defines an ifconfig-pool, so you can't also specify --ifconfig-pool explicitly");
|
||||
}
|
||||
|
||||
if (o->shared_secret_file)
|
||||
{
|
||||
msg(M_USAGE, "--server-bridge and --secret cannot be used together (you must use SSL/TLS keys)");
|
||||
}
|
||||
|
||||
if (dev != DEV_TYPE_TAP)
|
||||
{
|
||||
msg(M_USAGE, "--server-bridge directive only makes sense with --dev tap");
|
||||
}
|
||||
|
||||
if (o->server_bridge_defined)
|
||||
{
|
||||
verify_common_subnet("--server-bridge", o->server_bridge_ip, o->server_bridge_pool_start, o->server_bridge_netmask);
|
||||
verify_common_subnet("--server-bridge", o->server_bridge_pool_start, o->server_bridge_pool_end, o->server_bridge_netmask);
|
||||
verify_common_subnet("--server-bridge", o->server_bridge_ip, o->server_bridge_pool_end, o->server_bridge_netmask);
|
||||
}
|
||||
|
||||
o->mode = MODE_SERVER;
|
||||
o->tls_server = true;
|
||||
|
||||
if (o->server_bridge_defined)
|
||||
{
|
||||
o->ifconfig_pool_defined = true;
|
||||
o->ifconfig_pool_start = o->server_bridge_pool_start;
|
||||
o->ifconfig_pool_end = o->server_bridge_pool_end;
|
||||
ifconfig_pool_verify_range(M_USAGE, o->ifconfig_pool_start, o->ifconfig_pool_end);
|
||||
o->ifconfig_pool_netmask = o->server_bridge_netmask;
|
||||
push_option(o, print_opt_route_gateway(o->server_bridge_ip, &o->gc), M_USAGE);
|
||||
}
|
||||
else if (o->server_bridge_proxy_dhcp && !(o->server_flags & SF_NO_PUSH_ROUTE_GATEWAY))
|
||||
{
|
||||
push_option(o, print_opt_route_gateway_dhcp(&o->gc), M_USAGE);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* P2MP_SERVER */
|
||||
|
||||
/*
|
||||
* HELPER DIRECTIVE:
|
||||
*
|
||||
* client
|
||||
*
|
||||
* EXPANDS TO:
|
||||
*
|
||||
* pull
|
||||
* tls-client
|
||||
*/
|
||||
if (o->client)
|
||||
/*
|
||||
* HELPER DIRECTIVE:
|
||||
*
|
||||
* client
|
||||
*
|
||||
* EXPANDS TO:
|
||||
*
|
||||
* pull
|
||||
* tls-client
|
||||
*/
|
||||
if (o->client)
|
||||
{
|
||||
if (o->key_method != 2)
|
||||
msg (M_USAGE, "--client requires --key-method 2");
|
||||
if (o->key_method != 2)
|
||||
{
|
||||
msg(M_USAGE, "--client requires --key-method 2");
|
||||
}
|
||||
|
||||
o->pull = true;
|
||||
o->tls_client = true;
|
||||
o->pull = true;
|
||||
o->tls_client = true;
|
||||
}
|
||||
|
||||
#endif /* P2MP */
|
||||
|
||||
gc_free (&gc);
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -465,45 +511,51 @@ helper_client_server (struct options *o)
|
|||
* ping-restart 60
|
||||
*/
|
||||
void
|
||||
helper_keepalive (struct options *o)
|
||||
helper_keepalive(struct options *o)
|
||||
{
|
||||
if (o->keepalive_ping || o->keepalive_timeout)
|
||||
if (o->keepalive_ping || o->keepalive_timeout)
|
||||
{
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
if (o->keepalive_ping <= 0 || o->keepalive_timeout <= 0)
|
||||
msg (M_USAGE, "--keepalive parameters must be > 0");
|
||||
if (o->keepalive_ping * 2 > o->keepalive_timeout)
|
||||
msg (M_USAGE, "the second parameter to --keepalive (restart timeout=%d) must be at least twice the value of the first parameter (ping interval=%d). A ratio of 1:5 or 1:6 would be even better. Recommended setting is --keepalive 10 60.",
|
||||
o->keepalive_timeout,
|
||||
o->keepalive_ping);
|
||||
if (o->ping_send_timeout || o->ping_rec_timeout)
|
||||
msg (M_USAGE, "--keepalive conflicts with --ping, --ping-exit, or --ping-restart. If you use --keepalive, you don't need any of the other --ping directives.");
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
if (o->keepalive_ping <= 0 || o->keepalive_timeout <= 0)
|
||||
{
|
||||
msg(M_USAGE, "--keepalive parameters must be > 0");
|
||||
}
|
||||
if (o->keepalive_ping * 2 > o->keepalive_timeout)
|
||||
{
|
||||
msg(M_USAGE, "the second parameter to --keepalive (restart timeout=%d) must be at least twice the value of the first parameter (ping interval=%d). A ratio of 1:5 or 1:6 would be even better. Recommended setting is --keepalive 10 60.",
|
||||
o->keepalive_timeout,
|
||||
o->keepalive_ping);
|
||||
}
|
||||
if (o->ping_send_timeout || o->ping_rec_timeout)
|
||||
{
|
||||
msg(M_USAGE, "--keepalive conflicts with --ping, --ping-exit, or --ping-restart. If you use --keepalive, you don't need any of the other --ping directives.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand.
|
||||
*/
|
||||
if (o->mode == MODE_POINT_TO_POINT)
|
||||
{
|
||||
o->ping_rec_timeout_action = PING_RESTART;
|
||||
o->ping_send_timeout = o->keepalive_ping;
|
||||
o->ping_rec_timeout = o->keepalive_timeout;
|
||||
}
|
||||
/*
|
||||
* Expand.
|
||||
*/
|
||||
if (o->mode == MODE_POINT_TO_POINT)
|
||||
{
|
||||
o->ping_rec_timeout_action = PING_RESTART;
|
||||
o->ping_send_timeout = o->keepalive_ping;
|
||||
o->ping_rec_timeout = o->keepalive_timeout;
|
||||
}
|
||||
#if P2MP_SERVER
|
||||
else if (o->mode == MODE_SERVER)
|
||||
{
|
||||
o->ping_rec_timeout_action = PING_RESTART;
|
||||
o->ping_send_timeout = o->keepalive_ping;
|
||||
o->ping_rec_timeout = o->keepalive_timeout * 2;
|
||||
push_option (o, print_str_int ("ping", o->keepalive_ping, &o->gc), M_USAGE);
|
||||
push_option (o, print_str_int ("ping-restart", o->keepalive_timeout, &o->gc), M_USAGE);
|
||||
}
|
||||
else if (o->mode == MODE_SERVER)
|
||||
{
|
||||
o->ping_rec_timeout_action = PING_RESTART;
|
||||
o->ping_send_timeout = o->keepalive_ping;
|
||||
o->ping_rec_timeout = o->keepalive_timeout * 2;
|
||||
push_option(o, print_str_int("ping", o->keepalive_ping, &o->gc), M_USAGE);
|
||||
push_option(o, print_str_int("ping-restart", o->keepalive_timeout, &o->gc), M_USAGE);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
ASSERT (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -520,20 +572,20 @@ helper_keepalive (struct options *o)
|
|||
* push "socket-flags TCP_NODELAY"
|
||||
*/
|
||||
void
|
||||
helper_tcp_nodelay (struct options *o)
|
||||
helper_tcp_nodelay(struct options *o)
|
||||
{
|
||||
#if P2MP_SERVER
|
||||
if (o->server_flags & SF_TCP_NODELAY_HELPER)
|
||||
if (o->server_flags & SF_TCP_NODELAY_HELPER)
|
||||
{
|
||||
if (o->mode == MODE_SERVER)
|
||||
{
|
||||
o->sockflags |= SF_TCP_NODELAY;
|
||||
push_option (o, print_str ("socket-flags TCP_NODELAY", &o->gc), M_USAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
o->sockflags |= SF_TCP_NODELAY;
|
||||
}
|
||||
if (o->mode == MODE_SERVER)
|
||||
{
|
||||
o->sockflags |= SF_TCP_NODELAY;
|
||||
push_option(o, print_str("socket-flags TCP_NODELAY", &o->gc), M_USAGE);
|
||||
}
|
||||
else
|
||||
{
|
||||
o->sockflags |= SF_TCP_NODELAY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,10 @@
|
|||
|
||||
#include "options.h"
|
||||
|
||||
void helper_keepalive (struct options *o);
|
||||
void helper_client_server (struct options *o);
|
||||
void helper_tcp_nodelay (struct options *o);
|
||||
void helper_keepalive(struct options *o);
|
||||
|
||||
void helper_client_server(struct options *o);
|
||||
|
||||
void helper_tcp_nodelay(struct options *o);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -37,118 +37,126 @@
|
|||
|
||||
static void
|
||||
CvtHex(
|
||||
IN HASH Bin,
|
||||
OUT HASHHEX Hex
|
||||
)
|
||||
IN HASH Bin,
|
||||
OUT HASHHEX Hex
|
||||
)
|
||||
{
|
||||
unsigned short i;
|
||||
unsigned char j;
|
||||
unsigned short i;
|
||||
unsigned char j;
|
||||
|
||||
for (i = 0; i < HASHLEN; i++) {
|
||||
j = (Bin[i] >> 4) & 0xf;
|
||||
if (j <= 9)
|
||||
Hex[i*2] = (j + '0');
|
||||
else
|
||||
Hex[i*2] = (j + 'a' - 10);
|
||||
j = Bin[i] & 0xf;
|
||||
if (j <= 9)
|
||||
Hex[i*2+1] = (j + '0');
|
||||
else
|
||||
Hex[i*2+1] = (j + 'a' - 10);
|
||||
};
|
||||
Hex[HASHHEXLEN] = '\0';
|
||||
};
|
||||
for (i = 0; i < HASHLEN; i++) {
|
||||
j = (Bin[i] >> 4) & 0xf;
|
||||
if (j <= 9)
|
||||
{
|
||||
Hex[i*2] = (j + '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
Hex[i*2] = (j + 'a' - 10);
|
||||
}
|
||||
j = Bin[i] & 0xf;
|
||||
if (j <= 9)
|
||||
{
|
||||
Hex[i*2+1] = (j + '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
Hex[i*2+1] = (j + 'a' - 10);
|
||||
}
|
||||
}
|
||||
Hex[HASHHEXLEN] = '\0';
|
||||
}
|
||||
|
||||
/* calculate H(A1) as per spec */
|
||||
void
|
||||
DigestCalcHA1(
|
||||
IN char * pszAlg,
|
||||
IN char * pszUserName,
|
||||
IN char * pszRealm,
|
||||
IN char * pszPassword,
|
||||
IN char * pszNonce,
|
||||
IN char * pszCNonce,
|
||||
OUT HASHHEX SessionKey
|
||||
)
|
||||
IN char *pszAlg,
|
||||
IN char *pszUserName,
|
||||
IN char *pszRealm,
|
||||
IN char *pszPassword,
|
||||
IN char *pszNonce,
|
||||
IN char *pszCNonce,
|
||||
OUT HASHHEX SessionKey
|
||||
)
|
||||
{
|
||||
HASH HA1;
|
||||
md_ctx_t md5_ctx;
|
||||
const md_kt_t *md5_kt = md_kt_get("MD5");
|
||||
HASH HA1;
|
||||
md_ctx_t md5_ctx;
|
||||
const md_kt_t *md5_kt = md_kt_get("MD5");
|
||||
|
||||
md_ctx_init(&md5_ctx, md5_kt);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword));
|
||||
md_ctx_final(&md5_ctx, HA1);
|
||||
if (pszAlg && strcasecmp(pszAlg, "md5-sess") == 0)
|
||||
md_ctx_init(&md5_ctx, md5_kt);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszUserName, strlen(pszUserName));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszRealm, strlen(pszRealm));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszPassword, strlen(pszPassword));
|
||||
md_ctx_final(&md5_ctx, HA1);
|
||||
if (pszAlg && strcasecmp(pszAlg, "md5-sess") == 0)
|
||||
{
|
||||
md_ctx_init(&md5_ctx, md5_kt);
|
||||
md_ctx_update(&md5_ctx, HA1, HASHLEN);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
|
||||
md_ctx_final(&md5_ctx, HA1);
|
||||
};
|
||||
md_ctx_cleanup(&md5_ctx);
|
||||
CvtHex(HA1, SessionKey);
|
||||
md_ctx_init(&md5_ctx, md5_kt);
|
||||
md_ctx_update(&md5_ctx, HA1, HASHLEN);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
|
||||
md_ctx_final(&md5_ctx, HA1);
|
||||
}
|
||||
md_ctx_cleanup(&md5_ctx);
|
||||
CvtHex(HA1, SessionKey);
|
||||
}
|
||||
|
||||
/* calculate request-digest/response-digest as per HTTP Digest spec */
|
||||
void
|
||||
DigestCalcResponse(
|
||||
IN HASHHEX HA1, /* H(A1) */
|
||||
IN char * pszNonce, /* nonce from server */
|
||||
IN char * pszNonceCount, /* 8 hex digits */
|
||||
IN char * pszCNonce, /* client nonce */
|
||||
IN char * pszQop, /* qop-value: "", "auth", "auth-int" */
|
||||
IN char * pszMethod, /* method from the request */
|
||||
IN char * pszDigestUri, /* requested URL */
|
||||
IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */
|
||||
OUT HASHHEX Response /* request-digest or response-digest */
|
||||
)
|
||||
IN HASHHEX HA1, /* H(A1) */
|
||||
IN char *pszNonce, /* nonce from server */
|
||||
IN char *pszNonceCount, /* 8 hex digits */
|
||||
IN char *pszCNonce, /* client nonce */
|
||||
IN char *pszQop, /* qop-value: "", "auth", "auth-int" */
|
||||
IN char *pszMethod, /* method from the request */
|
||||
IN char *pszDigestUri, /* requested URL */
|
||||
IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */
|
||||
OUT HASHHEX Response /* request-digest or response-digest */
|
||||
)
|
||||
{
|
||||
HASH HA2;
|
||||
HASH RespHash;
|
||||
HASHHEX HA2Hex;
|
||||
HASH HA2;
|
||||
HASH RespHash;
|
||||
HASHHEX HA2Hex;
|
||||
|
||||
md_ctx_t md5_ctx;
|
||||
const md_kt_t *md5_kt = md_kt_get("MD5");
|
||||
md_ctx_t md5_ctx;
|
||||
const md_kt_t *md5_kt = md_kt_get("MD5");
|
||||
|
||||
/* calculate H(A2) */
|
||||
md_ctx_init(&md5_ctx, md5_kt);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri));
|
||||
if (strcasecmp(pszQop, "auth-int") == 0)
|
||||
/* calculate H(A2) */
|
||||
md_ctx_init(&md5_ctx, md5_kt);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszMethod, strlen(pszMethod));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszDigestUri, strlen(pszDigestUri));
|
||||
if (strcasecmp(pszQop, "auth-int") == 0)
|
||||
{
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, HEntity, HASHHEXLEN);
|
||||
};
|
||||
md_ctx_final(&md5_ctx, HA2);
|
||||
CvtHex(HA2, HA2Hex);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, HEntity, HASHHEXLEN);
|
||||
}
|
||||
md_ctx_final(&md5_ctx, HA2);
|
||||
CvtHex(HA2, HA2Hex);
|
||||
|
||||
/* calculate response */
|
||||
md_ctx_init(&md5_ctx, md5_kt);
|
||||
md_ctx_update(&md5_ctx, HA1, HASHHEXLEN);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
if (*pszQop)
|
||||
/* calculate response */
|
||||
md_ctx_init(&md5_ctx, md5_kt);
|
||||
md_ctx_update(&md5_ctx, HA1, HASHHEXLEN);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszNonce, strlen(pszNonce));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
if (*pszQop)
|
||||
{
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszQop, strlen(pszQop));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
};
|
||||
md_ctx_update(&md5_ctx, HA2Hex, HASHHEXLEN);
|
||||
md_ctx_final(&md5_ctx, RespHash);
|
||||
md_ctx_cleanup(&md5_ctx);
|
||||
CvtHex(RespHash, Response);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszNonceCount, strlen(pszNonceCount));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszCNonce, strlen(pszCNonce));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) pszQop, strlen(pszQop));
|
||||
md_ctx_update(&md5_ctx, (const uint8_t *) ":", 1);
|
||||
}
|
||||
md_ctx_update(&md5_ctx, HA2Hex, HASHHEXLEN);
|
||||
md_ctx_final(&md5_ctx, RespHash);
|
||||
md_ctx_cleanup(&md5_ctx);
|
||||
CvtHex(RespHash, Response);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* if PROXY_DIGEST_AUTH */
|
||||
|
|
|
|||
|
|
@ -35,26 +35,26 @@ typedef unsigned char HASHHEX[HASHHEXLEN+1];
|
|||
|
||||
/* calculate H(A1) as per HTTP Digest spec */
|
||||
void DigestCalcHA1(
|
||||
IN char * pszAlg,
|
||||
IN char * pszUserName,
|
||||
IN char * pszRealm,
|
||||
IN char * pszPassword,
|
||||
IN char * pszNonce,
|
||||
IN char * pszCNonce,
|
||||
IN char *pszAlg,
|
||||
IN char *pszUserName,
|
||||
IN char *pszRealm,
|
||||
IN char *pszPassword,
|
||||
IN char *pszNonce,
|
||||
IN char *pszCNonce,
|
||||
OUT HASHHEX SessionKey
|
||||
);
|
||||
|
||||
/* calculate request-digest/response-digest as per HTTP Digest spec */
|
||||
void DigestCalcResponse(
|
||||
IN HASHHEX HA1, /* H(A1) */
|
||||
IN char * pszNonce, /* nonce from server */
|
||||
IN char * pszNonceCount, /* 8 hex digits */
|
||||
IN char * pszCNonce, /* client nonce */
|
||||
IN char * pszQop, /* qop-value: "", "auth", "auth-int" */
|
||||
IN char * pszMethod, /* method from the request */
|
||||
IN char * pszDigestUri, /* requested URL */
|
||||
IN char *pszNonce, /* nonce from server */
|
||||
IN char *pszNonceCount, /* 8 hex digits */
|
||||
IN char *pszCNonce, /* client nonce */
|
||||
IN char *pszQop, /* qop-value: "", "auth", "auth-int" */
|
||||
IN char *pszMethod, /* method from the request */
|
||||
IN char *pszDigestUri, /* requested URL */
|
||||
IN HASHHEX HEntity, /* H(entity body) if qop="auth-int" */
|
||||
OUT HASHHEX Response /* request-digest or response-digest */
|
||||
);
|
||||
|
||||
#endif
|
||||
#endif /* if PROXY_DIGEST_AUTH */
|
||||
|
|
|
|||
5302
src/openvpn/init.c
5302
src/openvpn/init.c
File diff suppressed because it is too large
Load diff
|
|
@ -33,103 +33,112 @@
|
|||
*/
|
||||
#define BASE_N_EVENTS 4
|
||||
|
||||
void context_clear (struct context *c);
|
||||
void context_clear_1 (struct context *c);
|
||||
void context_clear_2 (struct context *c);
|
||||
void context_init_1 (struct context *c);
|
||||
void context_clear_all_except_first_time (struct context *c);
|
||||
void context_clear(struct context *c);
|
||||
|
||||
bool init_static (void);
|
||||
void context_clear_1(struct context *c);
|
||||
|
||||
void uninit_static (void);
|
||||
void context_clear_2(struct context *c);
|
||||
|
||||
#define IVM_LEVEL_1 (1<<0)
|
||||
void context_init_1(struct context *c);
|
||||
|
||||
void context_clear_all_except_first_time(struct context *c);
|
||||
|
||||
bool init_static(void);
|
||||
|
||||
void uninit_static(void);
|
||||
|
||||
#define IVM_LEVEL_1 (1<<0)
|
||||
#define IVM_LEVEL_2 (1<<1)
|
||||
void init_verb_mute (struct context *c, unsigned int flags);
|
||||
void init_verb_mute(struct context *c, unsigned int flags);
|
||||
|
||||
void init_options_dev (struct options *options);
|
||||
void init_options_dev(struct options *options);
|
||||
|
||||
bool print_openssl_info (const struct options *options);
|
||||
bool print_openssl_info(const struct options *options);
|
||||
|
||||
bool do_genkey (const struct options *options);
|
||||
bool do_genkey(const struct options *options);
|
||||
|
||||
bool do_persist_tuntap (const struct options *options);
|
||||
bool do_persist_tuntap(const struct options *options);
|
||||
|
||||
bool possibly_become_daemon (const struct options *options);
|
||||
bool possibly_become_daemon(const struct options *options);
|
||||
|
||||
void pre_setup (const struct options *options);
|
||||
void pre_setup(const struct options *options);
|
||||
|
||||
void init_instance_handle_signals (struct context *c, const struct env_set *env, const unsigned int flags);
|
||||
void init_instance_handle_signals(struct context *c, const struct env_set *env, const unsigned int flags);
|
||||
|
||||
void init_instance (struct context *c, const struct env_set *env, const unsigned int flags);
|
||||
void init_instance(struct context *c, const struct env_set *env, const unsigned int flags);
|
||||
|
||||
/**
|
||||
* Query for private key and auth-user-pass username/passwords.
|
||||
*/
|
||||
void init_query_passwords (const struct context *c);
|
||||
void init_query_passwords(const struct context *c);
|
||||
|
||||
void do_route (const struct options *options,
|
||||
struct route_list *route_list,
|
||||
struct route_ipv6_list *route_ipv6_list,
|
||||
const struct tuntap *tt,
|
||||
const struct plugin_list *plugins,
|
||||
struct env_set *es);
|
||||
void do_route(const struct options *options,
|
||||
struct route_list *route_list,
|
||||
struct route_ipv6_list *route_ipv6_list,
|
||||
const struct tuntap *tt,
|
||||
const struct plugin_list *plugins,
|
||||
struct env_set *es);
|
||||
|
||||
void close_instance (struct context *c);
|
||||
void close_instance(struct context *c);
|
||||
|
||||
bool do_test_crypto (const struct options *o);
|
||||
bool do_test_crypto(const struct options *o);
|
||||
|
||||
void context_gc_free (struct context *c);
|
||||
void context_gc_free(struct context *c);
|
||||
|
||||
bool do_up (struct context *c,
|
||||
bool pulled_options,
|
||||
unsigned int option_types_found);
|
||||
bool do_up(struct context *c,
|
||||
bool pulled_options,
|
||||
unsigned int option_types_found);
|
||||
|
||||
unsigned int pull_permission_mask (const struct context *c);
|
||||
unsigned int pull_permission_mask(const struct context *c);
|
||||
|
||||
const char *format_common_name (struct context *c, struct gc_arena *gc);
|
||||
const char *format_common_name(struct context *c, struct gc_arena *gc);
|
||||
|
||||
void reset_coarse_timers (struct context *c);
|
||||
void reset_coarse_timers(struct context *c);
|
||||
|
||||
bool do_deferred_options (struct context *c, const unsigned int found);
|
||||
bool do_deferred_options(struct context *c, const unsigned int found);
|
||||
|
||||
void inherit_context_child (struct context *dest,
|
||||
const struct context *src);
|
||||
void inherit_context_child(struct context *dest,
|
||||
const struct context *src);
|
||||
|
||||
void inherit_context_top (struct context *dest,
|
||||
const struct context *src);
|
||||
void inherit_context_top(struct context *dest,
|
||||
const struct context *src);
|
||||
|
||||
#define CC_GC_FREE (1<<0)
|
||||
#define CC_USR1_TO_HUP (1<<1)
|
||||
#define CC_HARD_USR1_TO_HUP (1<<2)
|
||||
#define CC_NO_CLOSE (1<<3)
|
||||
|
||||
void close_context (struct context *c, int sig, unsigned int flags);
|
||||
void close_context(struct context *c, int sig, unsigned int flags);
|
||||
|
||||
struct context_buffers *init_context_buffers (const struct frame *frame);
|
||||
struct context_buffers *init_context_buffers(const struct frame *frame);
|
||||
|
||||
void free_context_buffers (struct context_buffers *b);
|
||||
void free_context_buffers(struct context_buffers *b);
|
||||
|
||||
#define ISC_ERRORS (1<<0)
|
||||
#define ISC_SERVER (1<<1)
|
||||
void initialization_sequence_completed (struct context *c, const unsigned int flags);
|
||||
void initialization_sequence_completed(struct context *c, const unsigned int flags);
|
||||
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
|
||||
void init_management (struct context *c);
|
||||
bool open_management (struct context *c);
|
||||
void close_management (void);
|
||||
void init_management(struct context *c);
|
||||
|
||||
void management_show_net_callback (void *arg, const int msglevel);
|
||||
bool open_management(struct context *c);
|
||||
|
||||
void close_management(void);
|
||||
|
||||
void management_show_net_callback(void *arg, const int msglevel);
|
||||
|
||||
#endif
|
||||
|
||||
void init_management_callback_p2p (struct context *c);
|
||||
void uninit_management_callback (void);
|
||||
void init_management_callback_p2p(struct context *c);
|
||||
|
||||
void uninit_management_callback(void);
|
||||
|
||||
#ifdef ENABLE_PLUGIN
|
||||
void init_plugins (struct context *c);
|
||||
void open_plugins (struct context *c, const bool import_options, int init_point);
|
||||
#endif
|
||||
void init_plugins(struct context *c);
|
||||
|
||||
void open_plugins(struct context *c, const bool import_options, int init_point);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* ifndef INIT_H */
|
||||
|
|
|
|||
|
|
@ -32,34 +32,50 @@
|
|||
*/
|
||||
|
||||
static inline int
|
||||
max_int (int x, int y)
|
||||
max_int(int x, int y)
|
||||
{
|
||||
if (x > y)
|
||||
return x;
|
||||
else
|
||||
return y;
|
||||
if (x > y)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
min_int (int x, int y)
|
||||
min_int(int x, int y)
|
||||
{
|
||||
if (x < y)
|
||||
return x;
|
||||
else
|
||||
return y;
|
||||
if (x < y)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
else
|
||||
{
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
constrain_int (int x, int min, int max)
|
||||
constrain_int(int x, int min, int max)
|
||||
{
|
||||
if (min > max)
|
||||
return min;
|
||||
if (x < min)
|
||||
return min;
|
||||
else if (x > max)
|
||||
return max;
|
||||
else
|
||||
return x;
|
||||
if (min > max)
|
||||
{
|
||||
return min;
|
||||
}
|
||||
if (x < min)
|
||||
{
|
||||
return min;
|
||||
}
|
||||
else if (x > max)
|
||||
{
|
||||
return max;
|
||||
}
|
||||
else
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -75,10 +91,10 @@ constrain_int (int x, int min, int max)
|
|||
static inline int
|
||||
modulo_subtract(int x, int y, int mod)
|
||||
{
|
||||
const int d1 = x - y;
|
||||
const int d2 = (x > y ? -mod : mod) + d1;
|
||||
ASSERT (0 <= x && x < mod && 0 <= y && y < mod);
|
||||
return abs(d1) > abs(d2) ? d2 : d1;
|
||||
const int d1 = x - y;
|
||||
const int d2 = (x > y ? -mod : mod) + d1;
|
||||
ASSERT(0 <= x && x < mod && 0 <= y && y < mod);
|
||||
return abs(d1) > abs(d2) ? d2 : d1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -90,25 +106,31 @@ modulo_subtract(int x, int y, int mod)
|
|||
static inline int
|
||||
modulo_add(int x, int y, int mod)
|
||||
{
|
||||
int sum = x + y;
|
||||
ASSERT (0 <= x && x < mod && -mod <= y && y <= mod);
|
||||
if (sum >= mod)
|
||||
sum -= mod;
|
||||
if (sum < 0)
|
||||
sum += mod;
|
||||
return sum;
|
||||
int sum = x + y;
|
||||
ASSERT(0 <= x && x < mod && -mod <= y && y <= mod);
|
||||
if (sum >= mod)
|
||||
{
|
||||
sum -= mod;
|
||||
}
|
||||
if (sum < 0)
|
||||
{
|
||||
sum += mod;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
static inline int
|
||||
index_verify (int index, int size, const char *file, int line)
|
||||
index_verify(int index, int size, const char *file, int line)
|
||||
{
|
||||
if (index < 0 || index >= size)
|
||||
msg (M_FATAL, "Assertion Failed: Array index=%d out of bounds for array size=%d in %s:%d",
|
||||
index,
|
||||
size,
|
||||
file,
|
||||
line);
|
||||
return index;
|
||||
if (index < 0 || index >= size)
|
||||
{
|
||||
msg(M_FATAL, "Assertion Failed: Array index=%d out of bounds for array size=%d in %s:%d",
|
||||
index,
|
||||
size,
|
||||
file,
|
||||
line);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* ifndef INTEGER_H */
|
||||
|
|
|
|||
|
|
@ -35,49 +35,49 @@
|
|||
#include "memdbg.h"
|
||||
|
||||
void
|
||||
interval_init (struct interval *top, int horizon, int refresh)
|
||||
interval_init(struct interval *top, int horizon, int refresh)
|
||||
{
|
||||
CLEAR (*top);
|
||||
top->refresh = refresh;
|
||||
top->horizon = horizon;
|
||||
CLEAR(*top);
|
||||
top->refresh = refresh;
|
||||
top->horizon = horizon;
|
||||
}
|
||||
|
||||
bool
|
||||
event_timeout_trigger (struct event_timeout *et,
|
||||
struct timeval *tv,
|
||||
const int et_const_retry)
|
||||
event_timeout_trigger(struct event_timeout *et,
|
||||
struct timeval *tv,
|
||||
const int et_const_retry)
|
||||
{
|
||||
bool ret = false;
|
||||
const time_t local_now = now;
|
||||
bool ret = false;
|
||||
const time_t local_now = now;
|
||||
|
||||
if (et->defined)
|
||||
if (et->defined)
|
||||
{
|
||||
int wakeup = (int) et->last + et->n - local_now;
|
||||
if (wakeup <= 0)
|
||||
{
|
||||
int wakeup = (int) et->last + et->n - local_now;
|
||||
if (wakeup <= 0)
|
||||
{
|
||||
#if INTERVAL_DEBUG
|
||||
dmsg (D_INTERVAL, "EVENT event_timeout_trigger (%d) etcr=%d", et->n, et_const_retry);
|
||||
dmsg(D_INTERVAL, "EVENT event_timeout_trigger (%d) etcr=%d", et->n, et_const_retry);
|
||||
#endif
|
||||
if (et_const_retry < 0)
|
||||
{
|
||||
et->last = local_now;
|
||||
wakeup = et->n;
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
wakeup = et_const_retry;
|
||||
}
|
||||
}
|
||||
if (et_const_retry < 0)
|
||||
{
|
||||
et->last = local_now;
|
||||
wakeup = et->n;
|
||||
ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
wakeup = et_const_retry;
|
||||
}
|
||||
}
|
||||
|
||||
if (tv && wakeup < tv->tv_sec)
|
||||
{
|
||||
if (tv && wakeup < tv->tv_sec)
|
||||
{
|
||||
#if INTERVAL_DEBUG
|
||||
dmsg (D_INTERVAL, "EVENT event_timeout_wakeup (%d/%d) etcr=%d", wakeup, et->n, et_const_retry);
|
||||
dmsg(D_INTERVAL, "EVENT event_timeout_wakeup (%d/%d) etcr=%d", wakeup, et->n, et_const_retry);
|
||||
#endif
|
||||
tv->tv_sec = wakeup;
|
||||
tv->tv_usec = 0;
|
||||
}
|
||||
tv->tv_sec = wakeup;
|
||||
tv->tv_usec = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,14 +42,14 @@
|
|||
|
||||
struct interval
|
||||
{
|
||||
interval_t refresh;
|
||||
interval_t horizon;
|
||||
time_t future_trigger;
|
||||
time_t last_action;
|
||||
time_t last_test_true;
|
||||
interval_t refresh;
|
||||
interval_t horizon;
|
||||
time_t future_trigger;
|
||||
time_t last_action;
|
||||
time_t last_test_true;
|
||||
};
|
||||
|
||||
void interval_init (struct interval *top, int horizon, int refresh);
|
||||
void interval_init(struct interval *top, int horizon, int refresh);
|
||||
|
||||
/*
|
||||
* IF
|
||||
|
|
@ -64,41 +64,41 @@ void interval_init (struct interval *top, int horizon, int refresh);
|
|||
*/
|
||||
|
||||
static inline bool
|
||||
interval_test (struct interval* top)
|
||||
interval_test(struct interval *top)
|
||||
{
|
||||
bool trigger = false;
|
||||
const time_t local_now = now;
|
||||
bool trigger = false;
|
||||
const time_t local_now = now;
|
||||
|
||||
if (top->future_trigger && local_now >= top->future_trigger)
|
||||
if (top->future_trigger && local_now >= top->future_trigger)
|
||||
{
|
||||
trigger = true;
|
||||
top->future_trigger = 0;
|
||||
trigger = true;
|
||||
top->future_trigger = 0;
|
||||
}
|
||||
|
||||
if (top->last_action + top->horizon > local_now ||
|
||||
top->last_test_true + top->refresh <= local_now ||
|
||||
trigger)
|
||||
if (top->last_action + top->horizon > local_now
|
||||
|| top->last_test_true + top->refresh <= local_now
|
||||
|| trigger)
|
||||
{
|
||||
top->last_test_true = local_now;
|
||||
top->last_test_true = local_now;
|
||||
#if INTERVAL_DEBUG
|
||||
dmsg (D_INTERVAL, "INTERVAL interval_test true");
|
||||
dmsg(D_INTERVAL, "INTERVAL interval_test true");
|
||||
#endif
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
interval_schedule_wakeup (struct interval* top, interval_t *wakeup)
|
||||
interval_schedule_wakeup(struct interval *top, interval_t *wakeup)
|
||||
{
|
||||
const time_t local_now = now;
|
||||
interval_earliest_wakeup (wakeup, top->last_test_true + top->refresh, local_now);
|
||||
interval_earliest_wakeup (wakeup, top->future_trigger, local_now);
|
||||
const time_t local_now = now;
|
||||
interval_earliest_wakeup(wakeup, top->last_test_true + top->refresh, local_now);
|
||||
interval_earliest_wakeup(wakeup, top->future_trigger, local_now);
|
||||
#if INTERVAL_DEBUG
|
||||
dmsg (D_INTERVAL, "INTERVAL interval_schedule wakeup=%d", (int)*wakeup);
|
||||
dmsg(D_INTERVAL, "INTERVAL interval_schedule wakeup=%d", (int)*wakeup);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -106,13 +106,13 @@ interval_schedule_wakeup (struct interval* top, interval_t *wakeup)
|
|||
* In wakeup seconds, interval_test will return true once.
|
||||
*/
|
||||
static inline void
|
||||
interval_future_trigger (struct interval* top, interval_t wakeup) {
|
||||
if (wakeup)
|
||||
interval_future_trigger(struct interval *top, interval_t wakeup) {
|
||||
if (wakeup)
|
||||
{
|
||||
#if INTERVAL_DEBUG
|
||||
dmsg (D_INTERVAL, "INTERVAL interval_future_trigger %d", (int)wakeup);
|
||||
dmsg(D_INTERVAL, "INTERVAL interval_future_trigger %d", (int)wakeup);
|
||||
#endif
|
||||
top->future_trigger = now + wakeup;
|
||||
top->future_trigger = now + wakeup;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,12 +121,12 @@ interval_future_trigger (struct interval* top, interval_t wakeup) {
|
|||
* horizon seconds.
|
||||
*/
|
||||
static inline void
|
||||
interval_action (struct interval* top)
|
||||
interval_action(struct interval *top)
|
||||
{
|
||||
#if INTERVAL_DEBUG
|
||||
dmsg (D_INTERVAL, "INTERVAL action");
|
||||
dmsg(D_INTERVAL, "INTERVAL action");
|
||||
#endif
|
||||
top->last_action = now;
|
||||
top->last_action = now;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -135,63 +135,68 @@ interval_action (struct interval* top)
|
|||
|
||||
struct event_timeout
|
||||
{
|
||||
bool defined;
|
||||
interval_t n;
|
||||
time_t last; /* time of last event */
|
||||
bool defined;
|
||||
interval_t n;
|
||||
time_t last; /* time of last event */
|
||||
};
|
||||
|
||||
static inline bool
|
||||
event_timeout_defined (const struct event_timeout* et)
|
||||
event_timeout_defined(const struct event_timeout *et)
|
||||
{
|
||||
return et->defined;
|
||||
return et->defined;
|
||||
}
|
||||
|
||||
static inline void
|
||||
event_timeout_clear (struct event_timeout* et)
|
||||
event_timeout_clear(struct event_timeout *et)
|
||||
{
|
||||
et->defined = false;
|
||||
et->n = 0;
|
||||
et->last = 0;
|
||||
et->defined = false;
|
||||
et->n = 0;
|
||||
et->last = 0;
|
||||
}
|
||||
|
||||
static inline struct event_timeout
|
||||
event_timeout_clear_ret ()
|
||||
event_timeout_clear_ret()
|
||||
{
|
||||
struct event_timeout ret;
|
||||
event_timeout_clear (&ret);
|
||||
return ret;
|
||||
struct event_timeout ret;
|
||||
event_timeout_clear(&ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void
|
||||
event_timeout_init (struct event_timeout* et, interval_t n, const time_t local_now)
|
||||
event_timeout_init(struct event_timeout *et, interval_t n, const time_t local_now)
|
||||
{
|
||||
et->defined = true;
|
||||
et->n = (n >= 0) ? n : 0;
|
||||
et->last = local_now;
|
||||
}
|
||||
|
||||
static inline void
|
||||
event_timeout_reset (struct event_timeout* et)
|
||||
{
|
||||
if (et->defined)
|
||||
et->last = now;
|
||||
}
|
||||
|
||||
static inline void
|
||||
event_timeout_modify_wakeup (struct event_timeout* et, interval_t n)
|
||||
{
|
||||
/* note that you might need to call reset_coarse_timers after this */
|
||||
if (et->defined)
|
||||
et->defined = true;
|
||||
et->n = (n >= 0) ? n : 0;
|
||||
et->last = local_now;
|
||||
}
|
||||
|
||||
static inline void
|
||||
event_timeout_reset(struct event_timeout *et)
|
||||
{
|
||||
if (et->defined)
|
||||
{
|
||||
et->last = now;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
event_timeout_modify_wakeup(struct event_timeout *et, interval_t n)
|
||||
{
|
||||
/* note that you might need to call reset_coarse_timers after this */
|
||||
if (et->defined)
|
||||
{
|
||||
et->n = (n >= 0) ? n : 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Will return the time left for a timeout, this function does not check
|
||||
* if the timeout is actually valid
|
||||
*/
|
||||
static inline interval_t event_timeout_remaining (struct event_timeout* et)
|
||||
static inline interval_t
|
||||
event_timeout_remaining(struct event_timeout *et)
|
||||
{
|
||||
return (int) et->last + et->n - now;
|
||||
return (int) et->last + et->n - now;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -207,9 +212,9 @@ static inline interval_t event_timeout_remaining (struct event_timeout* et)
|
|||
|
||||
#define ETT_DEFAULT (-1)
|
||||
|
||||
bool event_timeout_trigger (struct event_timeout *et,
|
||||
struct timeval *tv,
|
||||
const int et_const_retry);
|
||||
bool event_timeout_trigger(struct event_timeout *et,
|
||||
struct timeval *tv,
|
||||
const int et_const_retry);
|
||||
|
||||
/*
|
||||
* Measure time intervals in microseconds
|
||||
|
|
@ -220,37 +225,37 @@ bool event_timeout_trigger (struct event_timeout *et,
|
|||
#define USEC_TIMER_MAX_USEC (USEC_TIMER_MAX * 1000000)
|
||||
|
||||
struct usec_timer {
|
||||
struct timeval start;
|
||||
struct timeval end;
|
||||
struct timeval start;
|
||||
struct timeval end;
|
||||
};
|
||||
|
||||
#ifdef HAVE_GETTIMEOFDAY
|
||||
|
||||
static inline void
|
||||
usec_timer_start (struct usec_timer *obj)
|
||||
usec_timer_start(struct usec_timer *obj)
|
||||
{
|
||||
CLEAR (*obj);
|
||||
openvpn_gettimeofday (&obj->start, NULL);
|
||||
CLEAR(*obj);
|
||||
openvpn_gettimeofday(&obj->start, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
usec_timer_end (struct usec_timer *obj)
|
||||
usec_timer_end(struct usec_timer *obj)
|
||||
{
|
||||
openvpn_gettimeofday (&obj->end, NULL);
|
||||
openvpn_gettimeofday(&obj->end, NULL);
|
||||
}
|
||||
|
||||
#endif /* HAVE_GETTIMEOFDAY */
|
||||
|
||||
static inline bool
|
||||
usec_timer_interval_defined (struct usec_timer *obj)
|
||||
usec_timer_interval_defined(struct usec_timer *obj)
|
||||
{
|
||||
return obj->start.tv_sec && obj->end.tv_sec;
|
||||
return obj->start.tv_sec && obj->end.tv_sec;
|
||||
}
|
||||
|
||||
static inline int
|
||||
usec_timer_interval (struct usec_timer *obj)
|
||||
usec_timer_interval(struct usec_timer *obj)
|
||||
{
|
||||
return tv_subtract (&obj->end, &obj->start, USEC_TIMER_MAX);
|
||||
return tv_subtract(&obj->end, &obj->start, USEC_TIMER_MAX);
|
||||
}
|
||||
|
||||
#endif /* INTERVAL_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -47,149 +47,156 @@
|
|||
|
||||
struct hash_element
|
||||
{
|
||||
void *value;
|
||||
const void *key;
|
||||
unsigned int hash_value;
|
||||
struct hash_element *next;
|
||||
void *value;
|
||||
const void *key;
|
||||
unsigned int hash_value;
|
||||
struct hash_element *next;
|
||||
};
|
||||
|
||||
struct hash_bucket
|
||||
{
|
||||
struct hash_element *list;
|
||||
struct hash_element *list;
|
||||
};
|
||||
|
||||
struct hash
|
||||
{
|
||||
int n_buckets;
|
||||
int n_elements;
|
||||
int mask;
|
||||
uint32_t iv;
|
||||
uint32_t (*hash_function)(const void *key, uint32_t iv);
|
||||
bool (*compare_function)(const void *key1, const void *key2); /* return true if equal */
|
||||
struct hash_bucket *buckets;
|
||||
int n_buckets;
|
||||
int n_elements;
|
||||
int mask;
|
||||
uint32_t iv;
|
||||
uint32_t (*hash_function)(const void *key, uint32_t iv);
|
||||
bool (*compare_function)(const void *key1, const void *key2); /* return true if equal */
|
||||
struct hash_bucket *buckets;
|
||||
};
|
||||
|
||||
struct hash *hash_init (const int n_buckets,
|
||||
const uint32_t iv,
|
||||
uint32_t (*hash_function)(const void *key, uint32_t iv),
|
||||
bool (*compare_function)(const void *key1, const void *key2));
|
||||
struct hash *hash_init(const int n_buckets,
|
||||
const uint32_t iv,
|
||||
uint32_t (*hash_function)(const void *key, uint32_t iv),
|
||||
bool (*compare_function)(const void *key1, const void *key2));
|
||||
|
||||
void hash_free (struct hash *hash);
|
||||
void hash_free(struct hash *hash);
|
||||
|
||||
bool hash_add (struct hash *hash, const void *key, void *value, bool replace);
|
||||
bool hash_add(struct hash *hash, const void *key, void *value, bool replace);
|
||||
|
||||
struct hash_element *hash_lookup_fast (struct hash *hash,
|
||||
struct hash_bucket *bucket,
|
||||
const void *key,
|
||||
uint32_t hv);
|
||||
struct hash_element *hash_lookup_fast(struct hash *hash,
|
||||
struct hash_bucket *bucket,
|
||||
const void *key,
|
||||
uint32_t hv);
|
||||
|
||||
bool hash_remove_fast (struct hash *hash,
|
||||
struct hash_bucket *bucket,
|
||||
const void *key,
|
||||
uint32_t hv);
|
||||
bool hash_remove_fast(struct hash *hash,
|
||||
struct hash_bucket *bucket,
|
||||
const void *key,
|
||||
uint32_t hv);
|
||||
|
||||
void hash_remove_by_value (struct hash *hash, void *value);
|
||||
void hash_remove_by_value(struct hash *hash, void *value);
|
||||
|
||||
struct hash_iterator
|
||||
{
|
||||
struct hash *hash;
|
||||
int bucket_index;
|
||||
struct hash_bucket *bucket;
|
||||
struct hash_element *elem;
|
||||
struct hash_element *last;
|
||||
bool bucket_marked;
|
||||
int bucket_index_start;
|
||||
int bucket_index_end;
|
||||
struct hash *hash;
|
||||
int bucket_index;
|
||||
struct hash_bucket *bucket;
|
||||
struct hash_element *elem;
|
||||
struct hash_element *last;
|
||||
bool bucket_marked;
|
||||
int bucket_index_start;
|
||||
int bucket_index_end;
|
||||
};
|
||||
|
||||
void hash_iterator_init_range (struct hash *hash,
|
||||
struct hash_iterator *hi,
|
||||
int start_bucket,
|
||||
int end_bucket);
|
||||
void hash_iterator_init_range(struct hash *hash,
|
||||
struct hash_iterator *hi,
|
||||
int start_bucket,
|
||||
int end_bucket);
|
||||
|
||||
void hash_iterator_init (struct hash *hash, struct hash_iterator *iter);
|
||||
struct hash_element *hash_iterator_next (struct hash_iterator *hi);
|
||||
void hash_iterator_delete_element (struct hash_iterator *hi);
|
||||
void hash_iterator_free (struct hash_iterator *hi);
|
||||
void hash_iterator_init(struct hash *hash, struct hash_iterator *iter);
|
||||
|
||||
uint32_t hash_func (const uint8_t *k, uint32_t length, uint32_t initval);
|
||||
struct hash_element *hash_iterator_next(struct hash_iterator *hi);
|
||||
|
||||
uint32_t void_ptr_hash_function (const void *key, uint32_t iv);
|
||||
bool void_ptr_compare_function (const void *key1, const void *key2);
|
||||
void hash_iterator_delete_element(struct hash_iterator *hi);
|
||||
|
||||
void hash_iterator_free(struct hash_iterator *hi);
|
||||
|
||||
uint32_t hash_func(const uint8_t *k, uint32_t length, uint32_t initval);
|
||||
|
||||
uint32_t void_ptr_hash_function(const void *key, uint32_t iv);
|
||||
|
||||
bool void_ptr_compare_function(const void *key1, const void *key2);
|
||||
|
||||
#ifdef LIST_TEST
|
||||
void list_test (void);
|
||||
void list_test(void);
|
||||
|
||||
#endif
|
||||
|
||||
static inline uint32_t
|
||||
hash_value (const struct hash *hash, const void *key)
|
||||
hash_value(const struct hash *hash, const void *key)
|
||||
{
|
||||
return (*hash->hash_function)(key, hash->iv);
|
||||
return (*hash->hash_function)(key, hash->iv);
|
||||
}
|
||||
|
||||
static inline int
|
||||
hash_n_elements (const struct hash *hash)
|
||||
hash_n_elements(const struct hash *hash)
|
||||
{
|
||||
return hash->n_elements;
|
||||
return hash->n_elements;
|
||||
}
|
||||
|
||||
static inline int
|
||||
hash_n_buckets (const struct hash *hash)
|
||||
hash_n_buckets(const struct hash *hash)
|
||||
{
|
||||
return hash->n_buckets;
|
||||
return hash->n_buckets;
|
||||
}
|
||||
|
||||
static inline struct hash_bucket *
|
||||
hash_bucket (struct hash *hash, uint32_t hv)
|
||||
hash_bucket(struct hash *hash, uint32_t hv)
|
||||
{
|
||||
return &hash->buckets[hv & hash->mask];
|
||||
return &hash->buckets[hv & hash->mask];
|
||||
}
|
||||
|
||||
static inline void *
|
||||
hash_lookup (struct hash *hash, const void *key)
|
||||
hash_lookup(struct hash *hash, const void *key)
|
||||
{
|
||||
void *ret = NULL;
|
||||
struct hash_element *he;
|
||||
uint32_t hv = hash_value (hash, key);
|
||||
struct hash_bucket *bucket = &hash->buckets[hv & hash->mask];
|
||||
void *ret = NULL;
|
||||
struct hash_element *he;
|
||||
uint32_t hv = hash_value(hash, key);
|
||||
struct hash_bucket *bucket = &hash->buckets[hv & hash->mask];
|
||||
|
||||
he = hash_lookup_fast (hash, bucket, key, hv);
|
||||
if (he)
|
||||
ret = he->value;
|
||||
he = hash_lookup_fast(hash, bucket, key, hv);
|
||||
if (he)
|
||||
{
|
||||
ret = he->value;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* NOTE: assumes that key is not a duplicate */
|
||||
static inline void
|
||||
hash_add_fast (struct hash *hash,
|
||||
struct hash_bucket *bucket,
|
||||
const void *key,
|
||||
uint32_t hv,
|
||||
void *value)
|
||||
hash_add_fast(struct hash *hash,
|
||||
struct hash_bucket *bucket,
|
||||
const void *key,
|
||||
uint32_t hv,
|
||||
void *value)
|
||||
{
|
||||
struct hash_element *he;
|
||||
struct hash_element *he;
|
||||
|
||||
ALLOC_OBJ (he, struct hash_element);
|
||||
he->value = value;
|
||||
he->key = key;
|
||||
he->hash_value = hv;
|
||||
he->next = bucket->list;
|
||||
bucket->list = he;
|
||||
++hash->n_elements;
|
||||
ALLOC_OBJ(he, struct hash_element);
|
||||
he->value = value;
|
||||
he->key = key;
|
||||
he->hash_value = hv;
|
||||
he->next = bucket->list;
|
||||
bucket->list = he;
|
||||
++hash->n_elements;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_remove (struct hash *hash, const void *key)
|
||||
hash_remove(struct hash *hash, const void *key)
|
||||
{
|
||||
uint32_t hv;
|
||||
struct hash_bucket *bucket;
|
||||
bool ret;
|
||||
uint32_t hv;
|
||||
struct hash_bucket *bucket;
|
||||
bool ret;
|
||||
|
||||
hv = hash_value (hash, key);
|
||||
bucket = &hash->buckets[hv & hash->mask];
|
||||
ret = hash_remove_fast (hash, bucket, key, hv);
|
||||
return ret;
|
||||
hv = hash_value(hash, key);
|
||||
bucket = &hash->buckets[hv & hash->mask];
|
||||
ret = hash_remove_fast(hash, bucket, key, hv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* P2MP_SERVER */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Support routine for configuring link layer address
|
||||
* Support routine for configuring link layer address
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
|
@ -12,56 +12,61 @@
|
|||
#include "error.h"
|
||||
#include "misc.h"
|
||||
|
||||
int set_lladdr(const char *ifname, const char *lladdr,
|
||||
const struct env_set *es)
|
||||
int
|
||||
set_lladdr(const char *ifname, const char *lladdr,
|
||||
const struct env_set *es)
|
||||
{
|
||||
struct argv argv = argv_new ();
|
||||
int r;
|
||||
struct argv argv = argv_new();
|
||||
int r;
|
||||
|
||||
if (!ifname || !lladdr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!ifname || !lladdr)
|
||||
return -1;
|
||||
|
||||
#if defined(TARGET_LINUX)
|
||||
#ifdef ENABLE_IPROUTE
|
||||
argv_printf (&argv,
|
||||
"%s link set addr %s dev %s",
|
||||
iproute_path, lladdr, ifname);
|
||||
argv_printf(&argv,
|
||||
"%s link set addr %s dev %s",
|
||||
iproute_path, lladdr, ifname);
|
||||
#else
|
||||
argv_printf (&argv,
|
||||
"%s %s hw ether %s",
|
||||
IFCONFIG_PATH,
|
||||
ifname, lladdr);
|
||||
argv_printf(&argv,
|
||||
"%s %s hw ether %s",
|
||||
IFCONFIG_PATH,
|
||||
ifname, lladdr);
|
||||
#endif
|
||||
#elif defined(TARGET_SOLARIS)
|
||||
argv_printf (&argv,
|
||||
"%s %s ether %s",
|
||||
IFCONFIG_PATH,
|
||||
ifname, lladdr);
|
||||
argv_printf(&argv,
|
||||
"%s %s ether %s",
|
||||
IFCONFIG_PATH,
|
||||
ifname, lladdr);
|
||||
#elif defined(TARGET_OPENBSD)
|
||||
argv_printf (&argv,
|
||||
"%s %s lladdr %s",
|
||||
IFCONFIG_PATH,
|
||||
ifname, lladdr);
|
||||
argv_printf(&argv,
|
||||
"%s %s lladdr %s",
|
||||
IFCONFIG_PATH,
|
||||
ifname, lladdr);
|
||||
#elif defined(TARGET_DARWIN)
|
||||
argv_printf (&argv,
|
||||
"%s %s lladdr %s",
|
||||
IFCONFIG_PATH,
|
||||
ifname, lladdr);
|
||||
argv_printf(&argv,
|
||||
"%s %s lladdr %s",
|
||||
IFCONFIG_PATH,
|
||||
ifname, lladdr);
|
||||
#elif defined(TARGET_FREEBSD)
|
||||
argv_printf (&argv,
|
||||
"%s %s ether %s",
|
||||
IFCONFIG_PATH,
|
||||
ifname, lladdr);
|
||||
#else
|
||||
msg (M_WARN, "Sorry, but I don't know how to configure link layer addresses on this operating system.");
|
||||
return -1;
|
||||
#endif
|
||||
argv_printf(&argv,
|
||||
"%s %s ether %s",
|
||||
IFCONFIG_PATH,
|
||||
ifname, lladdr);
|
||||
#else /* if defined(TARGET_LINUX) */
|
||||
msg(M_WARN, "Sorry, but I don't know how to configure link layer addresses on this operating system.");
|
||||
return -1;
|
||||
#endif /* if defined(TARGET_LINUX) */
|
||||
|
||||
argv_msg (M_INFO, &argv);
|
||||
r = openvpn_execve_check (&argv, es, M_WARN, "ERROR: Unable to set link layer address.");
|
||||
if (r)
|
||||
msg (M_INFO, "TUN/TAP link layer address set to %s", lladdr);
|
||||
argv_msg(M_INFO, &argv);
|
||||
r = openvpn_execve_check(&argv, es, M_WARN, "ERROR: Unable to set link layer address.");
|
||||
if (r)
|
||||
{
|
||||
msg(M_INFO, "TUN/TAP link layer address set to %s", lladdr);
|
||||
}
|
||||
|
||||
argv_reset (&argv);
|
||||
return r;
|
||||
argv_reset(&argv);
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* Support routine for configuring link layer address
|
||||
* Support routine for configuring link layer address
|
||||
*/
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
int set_lladdr(const char *ifname, const char *lladdr,
|
||||
const struct env_set *es);
|
||||
const struct env_set *es);
|
||||
|
|
|
|||
|
|
@ -50,206 +50,223 @@
|
|||
* @return
|
||||
*/
|
||||
static bool
|
||||
lzo_adaptive_compress_test (struct lzo_adaptive_compress *ac)
|
||||
lzo_adaptive_compress_test(struct lzo_adaptive_compress *ac)
|
||||
{
|
||||
const bool save = ac->compress_state;
|
||||
const time_t local_now = now;
|
||||
const bool save = ac->compress_state;
|
||||
const time_t local_now = now;
|
||||
|
||||
if (!ac->compress_state)
|
||||
if (!ac->compress_state)
|
||||
{
|
||||
if (local_now >= ac->next)
|
||||
{
|
||||
if (ac->n_total > AC_MIN_BYTES
|
||||
&& (ac->n_total - ac->n_comp) < (ac->n_total / (100 / AC_SAVE_PCT)))
|
||||
{
|
||||
ac->compress_state = true;
|
||||
ac->next = local_now + AC_OFF_SEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
ac->next = local_now + AC_SAMP_SEC;
|
||||
}
|
||||
dmsg (D_COMP, "lzo_adaptive_compress_test: comp=%d total=%d", ac->n_comp, ac->n_total);
|
||||
ac->n_total = ac->n_comp = 0;
|
||||
}
|
||||
if (local_now >= ac->next)
|
||||
{
|
||||
if (ac->n_total > AC_MIN_BYTES
|
||||
&& (ac->n_total - ac->n_comp) < (ac->n_total / (100 / AC_SAVE_PCT)))
|
||||
{
|
||||
ac->compress_state = true;
|
||||
ac->next = local_now + AC_OFF_SEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
ac->next = local_now + AC_SAMP_SEC;
|
||||
}
|
||||
dmsg(D_COMP, "lzo_adaptive_compress_test: comp=%d total=%d", ac->n_comp, ac->n_total);
|
||||
ac->n_total = ac->n_comp = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if (local_now >= ac->next)
|
||||
{
|
||||
ac->next = local_now + AC_SAMP_SEC;
|
||||
ac->n_total = ac->n_comp = 0;
|
||||
ac->compress_state = false;
|
||||
}
|
||||
if (local_now >= ac->next)
|
||||
{
|
||||
ac->next = local_now + AC_SAMP_SEC;
|
||||
ac->n_total = ac->n_comp = 0;
|
||||
ac->compress_state = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ac->compress_state != save)
|
||||
dmsg (D_COMP_LOW, "Adaptive compression state %s", (ac->compress_state ? "OFF" : "ON"));
|
||||
if (ac->compress_state != save)
|
||||
{
|
||||
dmsg(D_COMP_LOW, "Adaptive compression state %s", (ac->compress_state ? "OFF" : "ON"));
|
||||
}
|
||||
|
||||
return !ac->compress_state;
|
||||
return !ac->compress_state;
|
||||
}
|
||||
|
||||
static inline void
|
||||
lzo_adaptive_compress_data (struct lzo_adaptive_compress *ac, int n_total, int n_comp)
|
||||
lzo_adaptive_compress_data(struct lzo_adaptive_compress *ac, int n_total, int n_comp)
|
||||
{
|
||||
ac->n_total += n_total;
|
||||
ac->n_comp += n_comp;
|
||||
ac->n_total += n_total;
|
||||
ac->n_comp += n_comp;
|
||||
}
|
||||
|
||||
static void
|
||||
lzo_compress_init (struct compress_context *compctx)
|
||||
lzo_compress_init(struct compress_context *compctx)
|
||||
{
|
||||
msg (D_INIT_MEDIUM, "LZO compression initializing");
|
||||
ASSERT(!(compctx->flags & COMP_F_SWAP));
|
||||
compctx->wu.lzo.wmem_size = LZO_WORKSPACE;
|
||||
if (lzo_init () != LZO_E_OK)
|
||||
msg (M_FATAL, "Cannot initialize LZO compression library");
|
||||
compctx->wu.lzo.wmem = (lzo_voidp) lzo_malloc (compctx->wu.lzo.wmem_size);
|
||||
check_malloc_return (compctx->wu.lzo.wmem);
|
||||
msg(D_INIT_MEDIUM, "LZO compression initializing");
|
||||
ASSERT(!(compctx->flags & COMP_F_SWAP));
|
||||
compctx->wu.lzo.wmem_size = LZO_WORKSPACE;
|
||||
if (lzo_init() != LZO_E_OK)
|
||||
{
|
||||
msg(M_FATAL, "Cannot initialize LZO compression library");
|
||||
}
|
||||
compctx->wu.lzo.wmem = (lzo_voidp) lzo_malloc(compctx->wu.lzo.wmem_size);
|
||||
check_malloc_return(compctx->wu.lzo.wmem);
|
||||
}
|
||||
|
||||
static void
|
||||
lzo_compress_uninit (struct compress_context *compctx)
|
||||
lzo_compress_uninit(struct compress_context *compctx)
|
||||
{
|
||||
lzo_free (compctx->wu.lzo.wmem);
|
||||
compctx->wu.lzo.wmem = NULL;
|
||||
lzo_free(compctx->wu.lzo.wmem);
|
||||
compctx->wu.lzo.wmem = NULL;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
lzo_compression_enabled (struct compress_context *compctx)
|
||||
lzo_compression_enabled(struct compress_context *compctx)
|
||||
{
|
||||
if (compctx->flags & COMP_F_ASYM)
|
||||
return false;
|
||||
else
|
||||
if (compctx->flags & COMP_F_ASYM)
|
||||
{
|
||||
if (compctx->flags & COMP_F_ADAPTIVE)
|
||||
return lzo_adaptive_compress_test (&compctx->wu.lzo.ac);
|
||||
else
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (compctx->flags & COMP_F_ADAPTIVE)
|
||||
{
|
||||
return lzo_adaptive_compress_test(&compctx->wu.lzo.ac);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lzo_compress (struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
lzo_compress(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
lzo_uint zlen = 0;
|
||||
int err;
|
||||
bool compressed = false;
|
||||
lzo_uint zlen = 0;
|
||||
int err;
|
||||
bool compressed = false;
|
||||
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* In order to attempt compression, length must be at least COMPRESS_THRESHOLD,
|
||||
* and our adaptive level must give the OK.
|
||||
*/
|
||||
if (buf->len >= COMPRESS_THRESHOLD && lzo_compression_enabled (compctx))
|
||||
if (buf->len <= 0)
|
||||
{
|
||||
const size_t ps = PAYLOAD_SIZE (frame);
|
||||
ASSERT (buf_init (&work, FRAME_HEADROOM (frame)));
|
||||
ASSERT (buf_safe (&work, ps + COMP_EXTRA_BUFFER (ps)));
|
||||
|
||||
if (buf->len > ps)
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "LZO compression buffer overflow");
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
err = LZO_COMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen, compctx->wu.lzo.wmem);
|
||||
if (err != LZO_E_OK)
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "LZO compression error: %d", err);
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT (buf_safe (&work, zlen));
|
||||
work.len = zlen;
|
||||
compressed = true;
|
||||
|
||||
dmsg (D_COMP, "LZO compress %d -> %d", buf->len, work.len);
|
||||
compctx->pre_compress += buf->len;
|
||||
compctx->post_compress += work.len;
|
||||
|
||||
/* tell adaptive level about our success or lack thereof in getting any size reduction */
|
||||
if (compctx->flags & COMP_F_ADAPTIVE)
|
||||
lzo_adaptive_compress_data (&compctx->wu.lzo.ac, buf->len, work.len);
|
||||
return;
|
||||
}
|
||||
|
||||
/* did compression save us anything ? */
|
||||
if (compressed && work.len < buf->len)
|
||||
/*
|
||||
* In order to attempt compression, length must be at least COMPRESS_THRESHOLD,
|
||||
* and our adaptive level must give the OK.
|
||||
*/
|
||||
if (buf->len >= COMPRESS_THRESHOLD && lzo_compression_enabled(compctx))
|
||||
{
|
||||
uint8_t *header = buf_prepend (&work, 1);
|
||||
*header = LZO_COMPRESS_BYTE;
|
||||
*buf = work;
|
||||
const size_t ps = PAYLOAD_SIZE(frame);
|
||||
ASSERT(buf_init(&work, FRAME_HEADROOM(frame)));
|
||||
ASSERT(buf_safe(&work, ps + COMP_EXTRA_BUFFER(ps)));
|
||||
|
||||
if (buf->len > ps)
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "LZO compression buffer overflow");
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
err = LZO_COMPRESS(BPTR(buf), BLEN(buf), BPTR(&work), &zlen, compctx->wu.lzo.wmem);
|
||||
if (err != LZO_E_OK)
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "LZO compression error: %d", err);
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(buf_safe(&work, zlen));
|
||||
work.len = zlen;
|
||||
compressed = true;
|
||||
|
||||
dmsg(D_COMP, "LZO compress %d -> %d", buf->len, work.len);
|
||||
compctx->pre_compress += buf->len;
|
||||
compctx->post_compress += work.len;
|
||||
|
||||
/* tell adaptive level about our success or lack thereof in getting any size reduction */
|
||||
if (compctx->flags & COMP_F_ADAPTIVE)
|
||||
{
|
||||
lzo_adaptive_compress_data(&compctx->wu.lzo.ac, buf->len, work.len);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
/* did compression save us anything ? */
|
||||
if (compressed && work.len < buf->len)
|
||||
{
|
||||
uint8_t *header = buf_prepend (buf, 1);
|
||||
*header = NO_COMPRESS_BYTE;
|
||||
uint8_t *header = buf_prepend(&work, 1);
|
||||
*header = LZO_COMPRESS_BYTE;
|
||||
*buf = work;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t *header = buf_prepend(buf, 1);
|
||||
*header = NO_COMPRESS_BYTE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lzo_decompress (struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame* frame)
|
||||
lzo_decompress(struct buffer *buf, struct buffer work,
|
||||
struct compress_context *compctx,
|
||||
const struct frame *frame)
|
||||
{
|
||||
lzo_uint zlen = EXPANDED_SIZE (frame);
|
||||
int err;
|
||||
uint8_t c; /* flag indicating whether or not our peer compressed */
|
||||
lzo_uint zlen = EXPANDED_SIZE(frame);
|
||||
int err;
|
||||
uint8_t c; /* flag indicating whether or not our peer compressed */
|
||||
|
||||
if (buf->len <= 0)
|
||||
return;
|
||||
|
||||
ASSERT (buf_init (&work, FRAME_HEADROOM (frame)));
|
||||
|
||||
c = *BPTR (buf);
|
||||
ASSERT (buf_advance (buf, 1));
|
||||
|
||||
if (c == LZO_COMPRESS_BYTE) /* packet was compressed */
|
||||
if (buf->len <= 0)
|
||||
{
|
||||
ASSERT (buf_safe (&work, zlen));
|
||||
err = LZO_DECOMPRESS (BPTR (buf), BLEN (buf), BPTR (&work), &zlen,
|
||||
compctx->wu.lzo.wmem);
|
||||
if (err != LZO_E_OK)
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "LZO decompression error: %d", err);
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT (buf_safe (&work, zlen));
|
||||
work.len = zlen;
|
||||
|
||||
dmsg (D_COMP, "LZO decompress %d -> %d", buf->len, work.len);
|
||||
compctx->pre_decompress += buf->len;
|
||||
compctx->post_decompress += work.len;
|
||||
|
||||
*buf = work;
|
||||
return;
|
||||
}
|
||||
else if (c == NO_COMPRESS_BYTE) /* packet was not compressed */
|
||||
|
||||
ASSERT(buf_init(&work, FRAME_HEADROOM(frame)));
|
||||
|
||||
c = *BPTR(buf);
|
||||
ASSERT(buf_advance(buf, 1));
|
||||
|
||||
if (c == LZO_COMPRESS_BYTE) /* packet was compressed */
|
||||
{
|
||||
;
|
||||
ASSERT(buf_safe(&work, zlen));
|
||||
err = LZO_DECOMPRESS(BPTR(buf), BLEN(buf), BPTR(&work), &zlen,
|
||||
compctx->wu.lzo.wmem);
|
||||
if (err != LZO_E_OK)
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "LZO decompression error: %d", err);
|
||||
buf->len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(buf_safe(&work, zlen));
|
||||
work.len = zlen;
|
||||
|
||||
dmsg(D_COMP, "LZO decompress %d -> %d", buf->len, work.len);
|
||||
compctx->pre_decompress += buf->len;
|
||||
compctx->post_decompress += work.len;
|
||||
|
||||
*buf = work;
|
||||
}
|
||||
else
|
||||
else if (c == NO_COMPRESS_BYTE) /* packet was not compressed */
|
||||
{
|
||||
dmsg (D_COMP_ERRORS, "Bad LZO decompression header byte: %d", c);
|
||||
buf->len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
dmsg(D_COMP_ERRORS, "Bad LZO decompression header byte: %d", c);
|
||||
buf->len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const struct compress_alg lzo_alg = {
|
||||
"lzo",
|
||||
lzo_compress_init,
|
||||
lzo_compress_uninit,
|
||||
lzo_compress,
|
||||
lzo_decompress
|
||||
"lzo",
|
||||
lzo_compress_init,
|
||||
lzo_compress_uninit,
|
||||
lzo_compress,
|
||||
lzo_decompress
|
||||
};
|
||||
|
||||
#else
|
||||
static void dummy(void) {}
|
||||
#else /* if defined(ENABLE_LZO) */
|
||||
static void
|
||||
dummy(void) {
|
||||
}
|
||||
#endif /* ENABLE_LZO */
|
||||
|
|
|
|||
|
|
@ -60,26 +60,26 @@ extern const struct compress_alg lzo_alg;
|
|||
/**************************************************************************/
|
||||
/** @name LZO library interface defines *//** @{ *//***********************/
|
||||
#define LZO_COMPRESS lzo1x_1_15_compress
|
||||
/**< LZO library compression function.
|
||||
*
|
||||
* Use \c lzo1x_1_15_compress because it
|
||||
* is described as faster than the
|
||||
* standard routine, although it does
|
||||
* need a bit more memory. */
|
||||
#define LZO_WORKSPACE LZO1X_1_15_MEM_COMPRESS
|
||||
/**< The size in bytes of the memory
|
||||
* %buffer required by the LZO library
|
||||
* compression algorithm. */
|
||||
/**< LZO library compression function.
|
||||
*
|
||||
* Use \c lzo1x_1_15_compress because it
|
||||
* is described as faster than the
|
||||
* standard routine, although it does
|
||||
* need a bit more memory. */
|
||||
#define LZO_WORKSPACE LZO1X_1_15_MEM_COMPRESS
|
||||
/**< The size in bytes of the memory
|
||||
* %buffer required by the LZO library
|
||||
* compression algorithm. */
|
||||
#define LZO_DECOMPRESS lzo1x_decompress_safe
|
||||
/**< LZO library decompression function.
|
||||
*
|
||||
* Use safe decompress because it
|
||||
* includes checks for possible %buffer
|
||||
* overflows. If speed is essential and
|
||||
* you will always be using a MAC to
|
||||
* verify the integrity of incoming
|
||||
* packets, you might want to consider
|
||||
* using the non-safe version. */
|
||||
/**< LZO library decompression function.
|
||||
*
|
||||
* Use safe decompress because it
|
||||
* includes checks for possible %buffer
|
||||
* overflows. If speed is essential and
|
||||
* you will always be using a MAC to
|
||||
* verify the integrity of incoming
|
||||
* packets, you might want to consider
|
||||
* using the non-safe version. */
|
||||
/** @} name LZO library interface *//**************************************/
|
||||
|
||||
|
||||
|
|
@ -100,10 +100,10 @@ extern const struct compress_alg lzo_alg;
|
|||
* Adaptive compression state.
|
||||
*/
|
||||
struct lzo_adaptive_compress {
|
||||
bool compress_state;
|
||||
time_t next;
|
||||
int n_total;
|
||||
int n_comp;
|
||||
bool compress_state;
|
||||
time_t next;
|
||||
int n_total;
|
||||
int n_comp;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -119,13 +119,13 @@ struct lzo_adaptive_compress {
|
|||
*/
|
||||
struct lzo_compress_workspace
|
||||
{
|
||||
lzo_voidp wmem;
|
||||
int wmem_size;
|
||||
struct lzo_adaptive_compress ac;
|
||||
lzo_voidp wmem;
|
||||
int wmem_size;
|
||||
struct lzo_adaptive_compress ac;
|
||||
};
|
||||
|
||||
/** @} addtogroup compression */
|
||||
|
||||
|
||||
#endif /* ENABLE_LZO && USE_COMP */
|
||||
#endif
|
||||
#endif /* ifndef OPENVPN_LZO_H */
|
||||
|
|
|
|||
5149
src/openvpn/manage.c
5149
src/openvpn/manage.c
File diff suppressed because it is too large
Load diff
|
|
@ -43,16 +43,16 @@
|
|||
*/
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
struct man_def_auth_context {
|
||||
unsigned long cid;
|
||||
unsigned long cid;
|
||||
|
||||
#define DAF_CONNECTION_ESTABLISHED (1<<0)
|
||||
#define DAF_CONNECTION_CLOSED (1<<1)
|
||||
#define DAF_INITIAL_AUTH (1<<2)
|
||||
unsigned int flags;
|
||||
unsigned int flags;
|
||||
|
||||
unsigned int mda_key_id_counter;
|
||||
unsigned int mda_key_id_counter;
|
||||
|
||||
time_t bytecount_last_update;
|
||||
time_t bytecount_last_update;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
@ -61,37 +61,41 @@ struct man_def_auth_context {
|
|||
*/
|
||||
struct command_line
|
||||
{
|
||||
struct buffer buf;
|
||||
struct buffer residual;
|
||||
struct buffer buf;
|
||||
struct buffer residual;
|
||||
};
|
||||
|
||||
struct command_line *command_line_new (const int buf_len);
|
||||
void command_line_free (struct command_line *cl);
|
||||
struct command_line *command_line_new(const int buf_len);
|
||||
|
||||
void command_line_add (struct command_line *cl, const unsigned char *buf, const int len);
|
||||
const unsigned char *command_line_get (struct command_line *cl);
|
||||
void command_line_reset (struct command_line *cl);
|
||||
void command_line_next (struct command_line *cl);
|
||||
void command_line_free(struct command_line *cl);
|
||||
|
||||
void command_line_add(struct command_line *cl, const unsigned char *buf, const int len);
|
||||
|
||||
const unsigned char *command_line_get(struct command_line *cl);
|
||||
|
||||
void command_line_reset(struct command_line *cl);
|
||||
|
||||
void command_line_next(struct command_line *cl);
|
||||
|
||||
/*
|
||||
* Manage log file history
|
||||
*/
|
||||
|
||||
union log_entry_union {
|
||||
unsigned int msg_flags;
|
||||
int state;
|
||||
int intval;
|
||||
unsigned int msg_flags;
|
||||
int state;
|
||||
int intval;
|
||||
};
|
||||
|
||||
struct log_entry
|
||||
{
|
||||
time_t timestamp;
|
||||
const char *string;
|
||||
in_addr_t local_ip;
|
||||
struct in6_addr local_ip6;
|
||||
struct openvpn_sockaddr local_sock;
|
||||
struct openvpn_sockaddr remote_sock;
|
||||
union log_entry_union u;
|
||||
time_t timestamp;
|
||||
const char *string;
|
||||
in_addr_t local_ip;
|
||||
struct in6_addr local_ip6;
|
||||
struct openvpn_sockaddr local_sock;
|
||||
struct openvpn_sockaddr remote_sock;
|
||||
union log_entry_union u;
|
||||
};
|
||||
|
||||
#define LOG_PRINT_LOG_PREFIX (1<<0)
|
||||
|
|
@ -112,32 +116,36 @@ struct log_entry
|
|||
|
||||
#define LOG_ECHO_TO_LOG (1<<11)
|
||||
|
||||
const char *log_entry_print (const struct log_entry *e, unsigned int flags, struct gc_arena *gc);
|
||||
const char *log_entry_print(const struct log_entry *e, unsigned int flags, struct gc_arena *gc);
|
||||
|
||||
struct log_history
|
||||
{
|
||||
int base;
|
||||
int size;
|
||||
int capacity;
|
||||
struct log_entry *array;
|
||||
int base;
|
||||
int size;
|
||||
int capacity;
|
||||
struct log_entry *array;
|
||||
};
|
||||
|
||||
struct log_history *log_history_init (const int capacity);
|
||||
void log_history_close (struct log_history *h);
|
||||
void log_history_add (struct log_history *h, const struct log_entry *le);
|
||||
void log_history_resize (struct log_history *h, const int capacity);
|
||||
const struct log_entry *log_history_ref (const struct log_history *h, const int index);
|
||||
struct log_history *log_history_init(const int capacity);
|
||||
|
||||
void log_history_close(struct log_history *h);
|
||||
|
||||
void log_history_add(struct log_history *h, const struct log_entry *le);
|
||||
|
||||
void log_history_resize(struct log_history *h, const int capacity);
|
||||
|
||||
const struct log_entry *log_history_ref(const struct log_history *h, const int index);
|
||||
|
||||
static inline int
|
||||
log_history_size (const struct log_history *h)
|
||||
log_history_size(const struct log_history *h)
|
||||
{
|
||||
return h->size;
|
||||
return h->size;
|
||||
}
|
||||
|
||||
static inline int
|
||||
log_history_capacity (const struct log_history *h)
|
||||
log_history_capacity(const struct log_history *h)
|
||||
{
|
||||
return h->capacity;
|
||||
return h->capacity;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -146,37 +154,37 @@ log_history_capacity (const struct log_history *h)
|
|||
*/
|
||||
struct management_callback
|
||||
{
|
||||
void *arg;
|
||||
void *arg;
|
||||
|
||||
# define MCF_SERVER (1<<0) /* is OpenVPN being run as a server? */
|
||||
unsigned int flags;
|
||||
#define MCF_SERVER (1<<0) /* is OpenVPN being run as a server? */
|
||||
unsigned int flags;
|
||||
|
||||
void (*status) (void *arg, const int version, struct status_output *so);
|
||||
void (*show_net) (void *arg, const int msglevel);
|
||||
int (*kill_by_cn) (void *arg, const char *common_name);
|
||||
int (*kill_by_addr) (void *arg, const in_addr_t addr, const int port);
|
||||
void (*delete_event) (void *arg, event_t event);
|
||||
int (*n_clients) (void *arg);
|
||||
void (*status) (void *arg, const int version, struct status_output *so);
|
||||
void (*show_net) (void *arg, const int msglevel);
|
||||
int (*kill_by_cn) (void *arg, const char *common_name);
|
||||
int (*kill_by_addr) (void *arg, const in_addr_t addr, const int port);
|
||||
void (*delete_event) (void *arg, event_t event);
|
||||
int (*n_clients) (void *arg);
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
bool (*kill_by_cid) (void *arg, const unsigned long cid, const char *kill_msg);
|
||||
bool (*client_auth) (void *arg,
|
||||
const unsigned long cid,
|
||||
const unsigned int mda_key_id,
|
||||
const bool auth,
|
||||
const char *reason,
|
||||
const char *client_reason,
|
||||
struct buffer_list *cc_config); /* ownership transferred */
|
||||
char *(*get_peer_info) (void *arg, const unsigned long cid);
|
||||
bool (*kill_by_cid)(void *arg, const unsigned long cid, const char *kill_msg);
|
||||
bool (*client_auth) (void *arg,
|
||||
const unsigned long cid,
|
||||
const unsigned int mda_key_id,
|
||||
const bool auth,
|
||||
const char *reason,
|
||||
const char *client_reason,
|
||||
struct buffer_list *cc_config); /* ownership transferred */
|
||||
char *(*get_peer_info) (void *arg, const unsigned long cid);
|
||||
#endif
|
||||
#ifdef MANAGEMENT_PF
|
||||
bool (*client_pf) (void *arg,
|
||||
const unsigned long cid,
|
||||
struct buffer_list *pf_config); /* ownership transferred */
|
||||
bool (*client_pf)(void *arg,
|
||||
const unsigned long cid,
|
||||
struct buffer_list *pf_config); /* ownership transferred */
|
||||
#endif
|
||||
bool (*proxy_cmd) (void *arg, const char **p);
|
||||
bool (*remote_cmd) (void *arg, const char **p);
|
||||
bool (*proxy_cmd)(void *arg, const char **p);
|
||||
bool (*remote_cmd) (void *arg, const char **p);
|
||||
#ifdef TARGET_ANDROID
|
||||
int (*network_change) (void *arg, bool samenetwork);
|
||||
int (*network_change)(void *arg, bool samenetwork);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -195,46 +203,46 @@ struct management_callback
|
|||
*/
|
||||
|
||||
struct man_persist {
|
||||
bool defined;
|
||||
bool defined;
|
||||
|
||||
struct log_history *log;
|
||||
struct virtual_output vout;
|
||||
struct log_history *log;
|
||||
struct virtual_output vout;
|
||||
|
||||
bool standalone_disabled;
|
||||
struct management_callback callback;
|
||||
bool standalone_disabled;
|
||||
struct management_callback callback;
|
||||
|
||||
struct log_history *echo; /* saved --echo strings */
|
||||
struct log_history *state;
|
||||
struct log_history *echo; /* saved --echo strings */
|
||||
struct log_history *state;
|
||||
|
||||
bool hold_release;
|
||||
bool hold_release;
|
||||
|
||||
const char *special_state_msg;
|
||||
const char *special_state_msg;
|
||||
|
||||
counter_type bytes_in;
|
||||
counter_type bytes_out;
|
||||
counter_type bytes_in;
|
||||
counter_type bytes_out;
|
||||
};
|
||||
|
||||
struct man_settings {
|
||||
bool defined;
|
||||
unsigned int flags; /* MF_x flags */
|
||||
struct addrinfo* local;
|
||||
bool defined;
|
||||
unsigned int flags; /* MF_x flags */
|
||||
struct addrinfo *local;
|
||||
#if UNIX_SOCK_SUPPORT
|
||||
struct sockaddr_un local_unix;
|
||||
struct sockaddr_un local_unix;
|
||||
#endif
|
||||
bool management_over_tunnel;
|
||||
struct user_pass up;
|
||||
int log_history_cache;
|
||||
int echo_buffer_size;
|
||||
int state_buffer_size;
|
||||
char *write_peer_info_file;
|
||||
int client_uid;
|
||||
int client_gid;
|
||||
bool management_over_tunnel;
|
||||
struct user_pass up;
|
||||
int log_history_cache;
|
||||
int echo_buffer_size;
|
||||
int state_buffer_size;
|
||||
char *write_peer_info_file;
|
||||
int client_uid;
|
||||
int client_gid;
|
||||
|
||||
/* flags for handling the management interface "signal" command */
|
||||
# define MANSIG_IGNORE_USR1_HUP (1<<0)
|
||||
# define MANSIG_MAP_USR1_TO_HUP (1<<1)
|
||||
# define MANSIG_MAP_USR1_TO_TERM (1<<2)
|
||||
unsigned int mansig;
|
||||
#define MANSIG_IGNORE_USR1_HUP (1<<0)
|
||||
#define MANSIG_MAP_USR1_TO_HUP (1<<1)
|
||||
#define MANSIG_MAP_USR1_TO_TERM (1<<2)
|
||||
unsigned int mansig;
|
||||
};
|
||||
|
||||
/* up_query modes */
|
||||
|
|
@ -251,225 +259,230 @@ struct man_settings {
|
|||
#define MS_CC_WAIT_WRITE 3 /* client is connected, waiting for ability to write to socket */
|
||||
|
||||
struct man_connection {
|
||||
int state;
|
||||
int state;
|
||||
|
||||
socket_descriptor_t sd_top;
|
||||
socket_descriptor_t sd_cli;
|
||||
struct openvpn_sockaddr remote;
|
||||
socket_descriptor_t sd_top;
|
||||
socket_descriptor_t sd_cli;
|
||||
struct openvpn_sockaddr remote;
|
||||
|
||||
#ifdef _WIN32
|
||||
struct net_event_win32 ne32;
|
||||
struct net_event_win32 ne32;
|
||||
#endif
|
||||
|
||||
bool halt;
|
||||
bool password_verified;
|
||||
int password_tries;
|
||||
bool halt;
|
||||
bool password_verified;
|
||||
int password_tries;
|
||||
|
||||
struct command_line *in;
|
||||
struct buffer_list *out;
|
||||
struct command_line *in;
|
||||
struct buffer_list *out;
|
||||
|
||||
#ifdef MANAGEMENT_IN_EXTRA
|
||||
# define IEC_UNDEF 0
|
||||
# define IEC_CLIENT_AUTH 1
|
||||
# define IEC_CLIENT_PF 2
|
||||
# define IEC_RSA_SIGN 3
|
||||
# define IEC_CERTIFICATE 4
|
||||
int in_extra_cmd;
|
||||
struct buffer_list *in_extra;
|
||||
#define IEC_UNDEF 0
|
||||
#define IEC_CLIENT_AUTH 1
|
||||
#define IEC_CLIENT_PF 2
|
||||
#define IEC_RSA_SIGN 3
|
||||
#define IEC_CERTIFICATE 4
|
||||
int in_extra_cmd;
|
||||
struct buffer_list *in_extra;
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
unsigned long in_extra_cid;
|
||||
unsigned int in_extra_kid;
|
||||
unsigned long in_extra_cid;
|
||||
unsigned int in_extra_kid;
|
||||
#endif
|
||||
#ifdef MANAGMENT_EXTERNAL_KEY
|
||||
# define EKS_UNDEF 0
|
||||
# define EKS_SOLICIT 1
|
||||
# define EKS_INPUT 2
|
||||
# define EKS_READY 3
|
||||
int ext_key_state;
|
||||
struct buffer_list *ext_key_input;
|
||||
int ext_cert_state;
|
||||
struct buffer_list *ext_cert_input;
|
||||
#define EKS_UNDEF 0
|
||||
#define EKS_SOLICIT 1
|
||||
#define EKS_INPUT 2
|
||||
#define EKS_READY 3
|
||||
int ext_key_state;
|
||||
struct buffer_list *ext_key_input;
|
||||
int ext_cert_state;
|
||||
struct buffer_list *ext_cert_input;
|
||||
#endif
|
||||
#endif
|
||||
struct event_set *es;
|
||||
int env_filter_level;
|
||||
#endif /* ifdef MANAGEMENT_IN_EXTRA */
|
||||
struct event_set *es;
|
||||
int env_filter_level;
|
||||
|
||||
bool state_realtime;
|
||||
bool log_realtime;
|
||||
bool echo_realtime;
|
||||
int bytecount_update_seconds;
|
||||
time_t bytecount_last_update;
|
||||
bool state_realtime;
|
||||
bool log_realtime;
|
||||
bool echo_realtime;
|
||||
int bytecount_update_seconds;
|
||||
time_t bytecount_last_update;
|
||||
|
||||
const char *up_query_type;
|
||||
int up_query_mode;
|
||||
struct user_pass up_query;
|
||||
const char *up_query_type;
|
||||
int up_query_mode;
|
||||
struct user_pass up_query;
|
||||
|
||||
#ifdef MANAGMENT_EXTERNAL_KEY
|
||||
struct buffer_list *rsa_sig;
|
||||
struct buffer_list *rsa_sig;
|
||||
#endif
|
||||
#ifdef TARGET_ANDROID
|
||||
int fdtosend;
|
||||
int lastfdreceived;
|
||||
int fdtosend;
|
||||
int lastfdreceived;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct management
|
||||
{
|
||||
struct man_persist persist;
|
||||
struct man_settings settings;
|
||||
struct man_connection connection;
|
||||
struct man_persist persist;
|
||||
struct man_settings settings;
|
||||
struct man_connection connection;
|
||||
};
|
||||
|
||||
extern struct management *management;
|
||||
|
||||
struct user_pass;
|
||||
|
||||
struct management *management_init (void);
|
||||
struct management *management_init(void);
|
||||
|
||||
/* management_open flags */
|
||||
# define MF_SERVER (1<<0)
|
||||
# define MF_QUERY_PASSWORDS (1<<1)
|
||||
# define MF_HOLD (1<<2)
|
||||
# define MF_SIGNAL (1<<3)
|
||||
# define MF_FORGET_DISCONNECT (1<<4)
|
||||
# define MF_CONNECT_AS_CLIENT (1<<5)
|
||||
#define MF_SERVER (1<<0)
|
||||
#define MF_QUERY_PASSWORDS (1<<1)
|
||||
#define MF_HOLD (1<<2)
|
||||
#define MF_SIGNAL (1<<3)
|
||||
#define MF_FORGET_DISCONNECT (1<<4)
|
||||
#define MF_CONNECT_AS_CLIENT (1<<5)
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
# define MF_CLIENT_AUTH (1<<6)
|
||||
#define MF_CLIENT_AUTH (1<<6)
|
||||
#endif
|
||||
#ifdef MANAGEMENT_PF
|
||||
# define MF_CLIENT_PF (1<<7)
|
||||
#define MF_CLIENT_PF (1<<7)
|
||||
#endif
|
||||
# define MF_UNIX_SOCK (1<<8)
|
||||
#define MF_UNIX_SOCK (1<<8)
|
||||
#ifdef MANAGMENT_EXTERNAL_KEY
|
||||
# define MF_EXTERNAL_KEY (1<<9)
|
||||
#define MF_EXTERNAL_KEY (1<<9)
|
||||
#endif
|
||||
#define MF_UP_DOWN (1<<10)
|
||||
#define MF_QUERY_REMOTE (1<<11)
|
||||
#define MF_QUERY_PROXY (1<<12)
|
||||
#define MF_EXTERNAL_CERT (1<<13)
|
||||
|
||||
bool management_open (struct management *man,
|
||||
const char *addr,
|
||||
const char *port,
|
||||
const char *pass_file,
|
||||
const char *client_user,
|
||||
const char *client_group,
|
||||
const int log_history_cache,
|
||||
const int echo_buffer_size,
|
||||
const int state_buffer_size,
|
||||
const char *write_peer_info_file,
|
||||
const int remap_sigusr1,
|
||||
const unsigned int flags);
|
||||
bool management_open(struct management *man,
|
||||
const char *addr,
|
||||
const char *port,
|
||||
const char *pass_file,
|
||||
const char *client_user,
|
||||
const char *client_group,
|
||||
const int log_history_cache,
|
||||
const int echo_buffer_size,
|
||||
const int state_buffer_size,
|
||||
const char *write_peer_info_file,
|
||||
const int remap_sigusr1,
|
||||
const unsigned int flags);
|
||||
|
||||
void management_close (struct management *man);
|
||||
void management_close(struct management *man);
|
||||
|
||||
void management_post_tunnel_open (struct management *man, const in_addr_t tun_local_ip);
|
||||
void management_post_tunnel_open(struct management *man, const in_addr_t tun_local_ip);
|
||||
|
||||
void management_pre_tunnel_close (struct management *man);
|
||||
void management_pre_tunnel_close(struct management *man);
|
||||
|
||||
void management_socket_set (struct management *man,
|
||||
struct event_set *es,
|
||||
void *arg,
|
||||
unsigned int *persistent);
|
||||
void management_socket_set(struct management *man,
|
||||
struct event_set *es,
|
||||
void *arg,
|
||||
unsigned int *persistent);
|
||||
|
||||
void management_io (struct management *man);
|
||||
void management_io(struct management *man);
|
||||
|
||||
void management_set_callback (struct management *man,
|
||||
const struct management_callback *cb);
|
||||
void management_set_callback(struct management *man,
|
||||
const struct management_callback *cb);
|
||||
|
||||
void management_clear_callback (struct management *man);
|
||||
void management_clear_callback(struct management *man);
|
||||
|
||||
bool management_query_user_pass (struct management *man,
|
||||
struct user_pass *up,
|
||||
const char *type,
|
||||
const unsigned int flags,
|
||||
const char *static_challenge);
|
||||
bool management_query_user_pass(struct management *man,
|
||||
struct user_pass *up,
|
||||
const char *type,
|
||||
const unsigned int flags,
|
||||
const char *static_challenge);
|
||||
|
||||
#ifdef TARGET_ANDROID
|
||||
bool management_android_control (struct management *man, const char *command, const char *msg);
|
||||
bool management_android_control(struct management *man, const char *command, const char *msg);
|
||||
|
||||
#define ANDROID_KEEP_OLD_TUN 1
|
||||
#define ANDROID_OPEN_AFTER_CLOSE 2
|
||||
#define ANDROID_OPEN_BEFORE_CLOSE 3
|
||||
int managment_android_persisttun_action (struct management *man);
|
||||
int managment_android_persisttun_action(struct management *man);
|
||||
|
||||
#endif
|
||||
|
||||
bool management_should_daemonize (struct management *man);
|
||||
bool management_would_hold (struct management *man);
|
||||
bool management_hold (struct management *man, int holdtime);
|
||||
bool management_should_daemonize(struct management *man);
|
||||
|
||||
void management_event_loop_n_seconds (struct management *man, int sec);
|
||||
bool management_would_hold(struct management *man);
|
||||
|
||||
bool management_hold(struct management *man, int holdtime);
|
||||
|
||||
void management_event_loop_n_seconds(struct management *man, int sec);
|
||||
|
||||
void management_up_down(struct management *man, const char *updown, const struct env_set *es);
|
||||
|
||||
void management_notify(struct management *man, const char *severity, const char *type, const char *text);
|
||||
|
||||
void management_notify_generic (struct management *man, const char *str);
|
||||
void management_notify_generic(struct management *man, const char *str);
|
||||
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
void management_notify_client_needing_auth (struct management *management,
|
||||
const unsigned int auth_id,
|
||||
struct man_def_auth_context *mdac,
|
||||
const struct env_set *es);
|
||||
void management_notify_client_needing_auth(struct management *management,
|
||||
const unsigned int auth_id,
|
||||
struct man_def_auth_context *mdac,
|
||||
const struct env_set *es);
|
||||
|
||||
void management_connection_established (struct management *management,
|
||||
struct man_def_auth_context *mdac,
|
||||
const struct env_set *es);
|
||||
void management_connection_established(struct management *management,
|
||||
struct man_def_auth_context *mdac,
|
||||
const struct env_set *es);
|
||||
|
||||
void management_notify_client_close (struct management *management,
|
||||
struct man_def_auth_context *mdac,
|
||||
const struct env_set *es);
|
||||
void management_notify_client_close(struct management *management,
|
||||
struct man_def_auth_context *mdac,
|
||||
const struct env_set *es);
|
||||
|
||||
void management_learn_addr(struct management *management,
|
||||
struct man_def_auth_context *mdac,
|
||||
const struct mroute_addr *addr,
|
||||
const bool primary);
|
||||
|
||||
void management_learn_addr (struct management *management,
|
||||
struct man_def_auth_context *mdac,
|
||||
const struct mroute_addr *addr,
|
||||
const bool primary);
|
||||
#endif
|
||||
|
||||
#ifdef MANAGMENT_EXTERNAL_KEY
|
||||
|
||||
char *management_query_rsa_sig (struct management *man, const char *b64_data);
|
||||
char* management_query_cert (struct management *man, const char *cert_name);
|
||||
char *management_query_rsa_sig(struct management *man, const char *b64_data);
|
||||
|
||||
char *management_query_cert(struct management *man, const char *cert_name);
|
||||
|
||||
#endif
|
||||
|
||||
static inline bool
|
||||
management_connected (const struct management *man)
|
||||
management_connected(const struct management *man)
|
||||
{
|
||||
return man->connection.state == MS_CC_WAIT_READ || man->connection.state == MS_CC_WAIT_WRITE;
|
||||
return man->connection.state == MS_CC_WAIT_READ || man->connection.state == MS_CC_WAIT_WRITE;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
management_query_user_pass_enabled (const struct management *man)
|
||||
management_query_user_pass_enabled(const struct management *man)
|
||||
{
|
||||
return BOOL_CAST(man->settings.flags & MF_QUERY_PASSWORDS);
|
||||
return BOOL_CAST(man->settings.flags & MF_QUERY_PASSWORDS);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
management_query_remote_enabled (const struct management *man)
|
||||
management_query_remote_enabled(const struct management *man)
|
||||
{
|
||||
return BOOL_CAST(man->settings.flags & MF_QUERY_REMOTE);
|
||||
return BOOL_CAST(man->settings.flags & MF_QUERY_REMOTE);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
management_query_proxy_enabled (const struct management *man)
|
||||
management_query_proxy_enabled(const struct management *man)
|
||||
{
|
||||
return BOOL_CAST(man->settings.flags & MF_QUERY_PROXY);
|
||||
return BOOL_CAST(man->settings.flags & MF_QUERY_PROXY);
|
||||
}
|
||||
|
||||
#ifdef MANAGEMENT_PF
|
||||
static inline bool
|
||||
management_enable_pf (const struct management *man)
|
||||
management_enable_pf(const struct management *man)
|
||||
{
|
||||
return man && BOOL_CAST(man->settings.flags & MF_CLIENT_PF);
|
||||
return man && BOOL_CAST(man->settings.flags & MF_CLIENT_PF);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
static inline bool
|
||||
management_enable_def_auth (const struct management *man)
|
||||
management_enable_def_auth(const struct management *man)
|
||||
{
|
||||
return man && BOOL_CAST(man->settings.flags & MF_CLIENT_AUTH);
|
||||
return man && BOOL_CAST(man->settings.flags & MF_CLIENT_AUTH);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -495,94 +508,102 @@ management_enable_def_auth (const struct management *man)
|
|||
|
||||
#define OPENVPN_STATE_CLIENT_BASE 7 /* Base index of client-only states */
|
||||
|
||||
void management_set_state (struct management *man,
|
||||
const int state,
|
||||
const char *detail,
|
||||
const in_addr_t *tun_local_ip,
|
||||
const struct in6_addr *tun_local_ip6,
|
||||
const struct openvpn_sockaddr *local_addr,
|
||||
const struct openvpn_sockaddr *remote_addr);
|
||||
void management_set_state(struct management *man,
|
||||
const int state,
|
||||
const char *detail,
|
||||
const in_addr_t *tun_local_ip,
|
||||
const struct in6_addr *tun_local_ip6,
|
||||
const struct openvpn_sockaddr *local_addr,
|
||||
const struct openvpn_sockaddr *remote_addr);
|
||||
|
||||
/*
|
||||
* The management object keeps track of OpenVPN --echo
|
||||
* parameters.
|
||||
*/
|
||||
void management_echo (struct management *man, const char *string, const bool pull);
|
||||
void management_echo(struct management *man, const char *string, const bool pull);
|
||||
|
||||
/*
|
||||
* OpenVPN calls here to indicate a password failure
|
||||
*/
|
||||
|
||||
void management_auth_failure (struct management *man, const char *type, const char *reason);
|
||||
void management_auth_failure(struct management *man, const char *type, const char *reason);
|
||||
|
||||
/*
|
||||
* Echo an authentication token to management interface
|
||||
*/
|
||||
void management_auth_token (struct management *man, const char *token);
|
||||
void management_auth_token(struct management *man, const char *token);
|
||||
|
||||
/*
|
||||
* These functions drive the bytecount in/out counters.
|
||||
*/
|
||||
|
||||
void man_bytecount_output_client (struct management *man);
|
||||
void man_bytecount_output_client(struct management *man);
|
||||
|
||||
static inline void
|
||||
man_bytecount_possible_output_client (struct management *man)
|
||||
man_bytecount_possible_output_client(struct management *man)
|
||||
{
|
||||
if (man->connection.bytecount_update_seconds > 0
|
||||
&& now >= man->connection.bytecount_last_update
|
||||
+ man->connection.bytecount_update_seconds)
|
||||
man_bytecount_output_client (man);
|
||||
if (man->connection.bytecount_update_seconds > 0
|
||||
&& now >= man->connection.bytecount_last_update
|
||||
+ man->connection.bytecount_update_seconds)
|
||||
{
|
||||
man_bytecount_output_client(man);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
management_bytes_out_client (struct management *man, const int size)
|
||||
management_bytes_out_client(struct management *man, const int size)
|
||||
{
|
||||
man->persist.bytes_out += size;
|
||||
man_bytecount_possible_output_client (man);
|
||||
man->persist.bytes_out += size;
|
||||
man_bytecount_possible_output_client(man);
|
||||
}
|
||||
|
||||
static inline void
|
||||
management_bytes_in_client (struct management *man, const int size)
|
||||
management_bytes_in_client(struct management *man, const int size)
|
||||
{
|
||||
man->persist.bytes_in += size;
|
||||
man_bytecount_possible_output_client (man);
|
||||
man->persist.bytes_in += size;
|
||||
man_bytecount_possible_output_client(man);
|
||||
}
|
||||
|
||||
static inline void
|
||||
management_bytes_out (struct management *man, const int size)
|
||||
management_bytes_out(struct management *man, const int size)
|
||||
{
|
||||
if (!(man->persist.callback.flags & MCF_SERVER))
|
||||
management_bytes_out_client (man, size);
|
||||
if (!(man->persist.callback.flags & MCF_SERVER))
|
||||
{
|
||||
management_bytes_out_client(man, size);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
management_bytes_in (struct management *man, const int size)
|
||||
management_bytes_in(struct management *man, const int size)
|
||||
{
|
||||
if (!(man->persist.callback.flags & MCF_SERVER))
|
||||
management_bytes_in_client (man, size);
|
||||
if (!(man->persist.callback.flags & MCF_SERVER))
|
||||
{
|
||||
management_bytes_in_client(man, size);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MANAGEMENT_DEF_AUTH
|
||||
|
||||
static inline void
|
||||
management_bytes_server (struct management *man,
|
||||
const counter_type *bytes_in_total,
|
||||
const counter_type *bytes_out_total,
|
||||
struct man_def_auth_context *mdac)
|
||||
management_bytes_server(struct management *man,
|
||||
const counter_type *bytes_in_total,
|
||||
const counter_type *bytes_out_total,
|
||||
struct man_def_auth_context *mdac)
|
||||
{
|
||||
void man_bytecount_output_server (struct management *man,
|
||||
const counter_type *bytes_in_total,
|
||||
const counter_type *bytes_out_total,
|
||||
struct man_def_auth_context *mdac);
|
||||
void man_bytecount_output_server(struct management *man,
|
||||
const counter_type *bytes_in_total,
|
||||
const counter_type *bytes_out_total,
|
||||
struct man_def_auth_context *mdac);
|
||||
|
||||
if (man->connection.bytecount_update_seconds > 0
|
||||
&& now >= mdac->bytecount_last_update + man->connection.bytecount_update_seconds
|
||||
&& (mdac->flags & (DAF_CONNECTION_ESTABLISHED|DAF_CONNECTION_CLOSED)) == DAF_CONNECTION_ESTABLISHED)
|
||||
man_bytecount_output_server (man, bytes_in_total, bytes_out_total, mdac);
|
||||
if (man->connection.bytecount_update_seconds > 0
|
||||
&& now >= mdac->bytecount_last_update + man->connection.bytecount_update_seconds
|
||||
&& (mdac->flags & (DAF_CONNECTION_ESTABLISHED|DAF_CONNECTION_CLOSED)) == DAF_CONNECTION_ESTABLISHED)
|
||||
{
|
||||
man_bytecount_output_server(man, bytes_in_total, bytes_out_total, mdac);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* MANAGEMENT_DEF_AUTH */
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif /* ifdef ENABLE_MANAGEMENT */
|
||||
#endif /* ifndef MANAGE_H */
|
||||
|
|
|
|||
|
|
@ -40,136 +40,140 @@
|
|||
#include "memdbg.h"
|
||||
|
||||
struct mbuf_set *
|
||||
mbuf_init (unsigned int size)
|
||||
mbuf_init(unsigned int size)
|
||||
{
|
||||
struct mbuf_set *ret;
|
||||
ALLOC_OBJ_CLEAR (ret, struct mbuf_set);
|
||||
ret->capacity = adjust_power_of_2 (size);
|
||||
ALLOC_ARRAY (ret->array, struct mbuf_item, ret->capacity);
|
||||
return ret;
|
||||
struct mbuf_set *ret;
|
||||
ALLOC_OBJ_CLEAR(ret, struct mbuf_set);
|
||||
ret->capacity = adjust_power_of_2(size);
|
||||
ALLOC_ARRAY(ret->array, struct mbuf_item, ret->capacity);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
mbuf_free (struct mbuf_set *ms)
|
||||
mbuf_free(struct mbuf_set *ms)
|
||||
{
|
||||
if (ms)
|
||||
if (ms)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (int) ms->len; ++i)
|
||||
{
|
||||
struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
|
||||
mbuf_free_buf (item->buffer);
|
||||
}
|
||||
free (ms->array);
|
||||
free (ms);
|
||||
int i;
|
||||
for (i = 0; i < (int) ms->len; ++i)
|
||||
{
|
||||
struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
|
||||
mbuf_free_buf(item->buffer);
|
||||
}
|
||||
free(ms->array);
|
||||
free(ms);
|
||||
}
|
||||
}
|
||||
|
||||
struct mbuf_buffer *
|
||||
mbuf_alloc_buf (const struct buffer *buf)
|
||||
mbuf_alloc_buf(const struct buffer *buf)
|
||||
{
|
||||
struct mbuf_buffer *ret;
|
||||
ALLOC_OBJ (ret, struct mbuf_buffer);
|
||||
ret->buf = clone_buf (buf);
|
||||
ret->refcount = 1;
|
||||
ret->flags = 0;
|
||||
return ret;
|
||||
struct mbuf_buffer *ret;
|
||||
ALLOC_OBJ(ret, struct mbuf_buffer);
|
||||
ret->buf = clone_buf(buf);
|
||||
ret->refcount = 1;
|
||||
ret->flags = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
mbuf_free_buf (struct mbuf_buffer *mb)
|
||||
mbuf_free_buf(struct mbuf_buffer *mb)
|
||||
{
|
||||
if (mb)
|
||||
if (mb)
|
||||
{
|
||||
if (--mb->refcount <= 0)
|
||||
{
|
||||
free_buf (&mb->buf);
|
||||
free (mb);
|
||||
}
|
||||
if (--mb->refcount <= 0)
|
||||
{
|
||||
free_buf(&mb->buf);
|
||||
free(mb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mbuf_add_item (struct mbuf_set *ms, const struct mbuf_item *item)
|
||||
mbuf_add_item(struct mbuf_set *ms, const struct mbuf_item *item)
|
||||
{
|
||||
ASSERT (ms);
|
||||
if (ms->len == ms->capacity)
|
||||
ASSERT(ms);
|
||||
if (ms->len == ms->capacity)
|
||||
{
|
||||
struct mbuf_item rm;
|
||||
ASSERT (mbuf_extract_item (ms, &rm));
|
||||
mbuf_free_buf (rm.buffer);
|
||||
msg (D_MULTI_DROPPED, "MBUF: mbuf packet dropped");
|
||||
struct mbuf_item rm;
|
||||
ASSERT(mbuf_extract_item(ms, &rm));
|
||||
mbuf_free_buf(rm.buffer);
|
||||
msg(D_MULTI_DROPPED, "MBUF: mbuf packet dropped");
|
||||
}
|
||||
|
||||
ASSERT (ms->len < ms->capacity);
|
||||
ASSERT(ms->len < ms->capacity);
|
||||
|
||||
ms->array[MBUF_INDEX(ms->head, ms->len, ms->capacity)] = *item;
|
||||
if (++ms->len > ms->max_queued)
|
||||
ms->max_queued = ms->len;
|
||||
++item->buffer->refcount;
|
||||
ms->array[MBUF_INDEX(ms->head, ms->len, ms->capacity)] = *item;
|
||||
if (++ms->len > ms->max_queued)
|
||||
{
|
||||
ms->max_queued = ms->len;
|
||||
}
|
||||
++item->buffer->refcount;
|
||||
}
|
||||
|
||||
bool
|
||||
mbuf_extract_item (struct mbuf_set *ms, struct mbuf_item *item)
|
||||
mbuf_extract_item(struct mbuf_set *ms, struct mbuf_item *item)
|
||||
{
|
||||
bool ret = false;
|
||||
if (ms)
|
||||
bool ret = false;
|
||||
if (ms)
|
||||
{
|
||||
while (ms->len)
|
||||
{
|
||||
*item = ms->array[ms->head];
|
||||
ms->head = MBUF_INDEX(ms->head, 1, ms->capacity);
|
||||
--ms->len;
|
||||
if (item->instance) /* ignore dereferenced instances */
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (ms->len)
|
||||
{
|
||||
*item = ms->array[ms->head];
|
||||
ms->head = MBUF_INDEX(ms->head, 1, ms->capacity);
|
||||
--ms->len;
|
||||
if (item->instance) /* ignore dereferenced instances */
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct multi_instance *
|
||||
mbuf_peek_dowork (struct mbuf_set *ms)
|
||||
mbuf_peek_dowork(struct mbuf_set *ms)
|
||||
{
|
||||
struct multi_instance *ret = NULL;
|
||||
if (ms)
|
||||
struct multi_instance *ret = NULL;
|
||||
if (ms)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (int) ms->len; ++i)
|
||||
{
|
||||
struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
|
||||
if (item->instance)
|
||||
{
|
||||
ret = item->instance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < (int) ms->len; ++i)
|
||||
{
|
||||
struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
|
||||
if (item->instance)
|
||||
{
|
||||
ret = item->instance;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
mbuf_dereference_instance (struct mbuf_set *ms, struct multi_instance *mi)
|
||||
mbuf_dereference_instance(struct mbuf_set *ms, struct multi_instance *mi)
|
||||
{
|
||||
if (ms)
|
||||
if (ms)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < (int) ms->len; ++i)
|
||||
{
|
||||
struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
|
||||
if (item->instance == mi)
|
||||
{
|
||||
mbuf_free_buf (item->buffer);
|
||||
item->buffer = NULL;
|
||||
item->instance = NULL;
|
||||
msg (D_MBUF, "MBUF: dereferenced queued packet");
|
||||
}
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < (int) ms->len; ++i)
|
||||
{
|
||||
struct mbuf_item *item = &ms->array[MBUF_INDEX(ms->head, i, ms->capacity)];
|
||||
if (item->instance == mi)
|
||||
{
|
||||
mbuf_free_buf(item->buffer);
|
||||
item->buffer = NULL;
|
||||
item->instance = NULL;
|
||||
msg(D_MBUF, "MBUF: dereferenced queued packet");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static void dummy(void) {}
|
||||
#else /* if P2MP */
|
||||
static void
|
||||
dummy(void) {
|
||||
}
|
||||
#endif /* P2MP */
|
||||
|
|
|
|||
|
|
@ -43,67 +43,74 @@ struct multi_instance;
|
|||
|
||||
struct mbuf_buffer
|
||||
{
|
||||
struct buffer buf;
|
||||
int refcount;
|
||||
struct buffer buf;
|
||||
int refcount;
|
||||
|
||||
# define MF_UNICAST (1<<0)
|
||||
unsigned int flags;
|
||||
#define MF_UNICAST (1<<0)
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
struct mbuf_item
|
||||
{
|
||||
struct mbuf_buffer *buffer;
|
||||
struct multi_instance *instance;
|
||||
struct mbuf_buffer *buffer;
|
||||
struct multi_instance *instance;
|
||||
};
|
||||
|
||||
struct mbuf_set
|
||||
{
|
||||
unsigned int head;
|
||||
unsigned int len;
|
||||
unsigned int capacity;
|
||||
unsigned int max_queued;
|
||||
struct mbuf_item *array;
|
||||
unsigned int head;
|
||||
unsigned int len;
|
||||
unsigned int capacity;
|
||||
unsigned int max_queued;
|
||||
struct mbuf_item *array;
|
||||
};
|
||||
|
||||
struct mbuf_set *mbuf_init (unsigned int size);
|
||||
void mbuf_free (struct mbuf_set *ms);
|
||||
struct mbuf_set *mbuf_init(unsigned int size);
|
||||
|
||||
struct mbuf_buffer *mbuf_alloc_buf (const struct buffer *buf);
|
||||
void mbuf_free_buf (struct mbuf_buffer *mb);
|
||||
void mbuf_free(struct mbuf_set *ms);
|
||||
|
||||
void mbuf_add_item (struct mbuf_set *ms, const struct mbuf_item *item);
|
||||
struct mbuf_buffer *mbuf_alloc_buf(const struct buffer *buf);
|
||||
|
||||
bool mbuf_extract_item (struct mbuf_set *ms, struct mbuf_item *item);
|
||||
void mbuf_free_buf(struct mbuf_buffer *mb);
|
||||
|
||||
void mbuf_dereference_instance (struct mbuf_set *ms, struct multi_instance *mi);
|
||||
void mbuf_add_item(struct mbuf_set *ms, const struct mbuf_item *item);
|
||||
|
||||
bool mbuf_extract_item(struct mbuf_set *ms, struct mbuf_item *item);
|
||||
|
||||
void mbuf_dereference_instance(struct mbuf_set *ms, struct multi_instance *mi);
|
||||
|
||||
static inline bool
|
||||
mbuf_defined (const struct mbuf_set *ms)
|
||||
mbuf_defined(const struct mbuf_set *ms)
|
||||
{
|
||||
return ms && ms->len;
|
||||
return ms && ms->len;
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
mbuf_len (const struct mbuf_set *ms)
|
||||
mbuf_len(const struct mbuf_set *ms)
|
||||
{
|
||||
return ms->len;
|
||||
return ms->len;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mbuf_maximum_queued (const struct mbuf_set *ms)
|
||||
mbuf_maximum_queued(const struct mbuf_set *ms)
|
||||
{
|
||||
return (int) ms->max_queued;
|
||||
return (int) ms->max_queued;
|
||||
}
|
||||
|
||||
static inline struct multi_instance *
|
||||
mbuf_peek (struct mbuf_set *ms)
|
||||
mbuf_peek(struct mbuf_set *ms)
|
||||
{
|
||||
struct multi_instance *mbuf_peek_dowork (struct mbuf_set *ms);
|
||||
if (mbuf_defined (ms))
|
||||
return mbuf_peek_dowork (ms);
|
||||
else
|
||||
return NULL;
|
||||
struct multi_instance *mbuf_peek_dowork(struct mbuf_set *ms);
|
||||
|
||||
if (mbuf_defined(ms))
|
||||
{
|
||||
return mbuf_peek_dowork(ms);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif /* if P2MP */
|
||||
#endif /* ifndef MBUF_H */
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
|
||||
#define VALGRIND_MAKE_READABLE(addr, len)
|
||||
|
||||
#else
|
||||
#else /* ifdef USE_VALGRIND */
|
||||
|
||||
#define VALGRIND_MAKE_READABLE(addr, len)
|
||||
|
||||
|
|
|
|||
2208
src/openvpn/misc.c
2208
src/openvpn/misc.c
File diff suppressed because it is too large
Load diff
|
|
@ -43,88 +43,97 @@ struct plugin_list;
|
|||
*/
|
||||
|
||||
struct env_item {
|
||||
char *string;
|
||||
struct env_item *next;
|
||||
char *string;
|
||||
struct env_item *next;
|
||||
};
|
||||
|
||||
struct env_set {
|
||||
struct gc_arena *gc;
|
||||
struct env_item *list;
|
||||
struct gc_arena *gc;
|
||||
struct env_item *list;
|
||||
};
|
||||
|
||||
void run_up_down (const char *command,
|
||||
const struct plugin_list *plugins,
|
||||
int plugin_type,
|
||||
const char *arg,
|
||||
void run_up_down(const char *command,
|
||||
const struct plugin_list *plugins,
|
||||
int plugin_type,
|
||||
const char *arg,
|
||||
#ifdef _WIN32
|
||||
DWORD adapter_index,
|
||||
DWORD adapter_index,
|
||||
#endif
|
||||
const char *dev_type,
|
||||
int tun_mtu,
|
||||
int link_mtu,
|
||||
const char *ifconfig_local,
|
||||
const char* ifconfig_remote,
|
||||
const char *context,
|
||||
const char *signal_text,
|
||||
const char *script_type,
|
||||
struct env_set *es);
|
||||
const char *dev_type,
|
||||
int tun_mtu,
|
||||
int link_mtu,
|
||||
const char *ifconfig_local,
|
||||
const char *ifconfig_remote,
|
||||
const char *context,
|
||||
const char *signal_text,
|
||||
const char *script_type,
|
||||
struct env_set *es);
|
||||
|
||||
void write_pid (const char *filename);
|
||||
void write_pid(const char *filename);
|
||||
|
||||
/* system flags */
|
||||
#define S_SCRIPT (1<<0)
|
||||
#define S_FATAL (1<<1)
|
||||
|
||||
const char *system_error_message (int, struct gc_arena *gc);
|
||||
const char *system_error_message(int, struct gc_arena *gc);
|
||||
|
||||
/* wrapper around the execve() call */
|
||||
int openvpn_popen (const struct argv *a, const struct env_set *es);
|
||||
int openvpn_execve (const struct argv *a, const struct env_set *es, const unsigned int flags);
|
||||
bool openvpn_execve_check (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message);
|
||||
bool openvpn_execve_allowed (const unsigned int flags);
|
||||
int openvpn_popen(const struct argv *a, const struct env_set *es);
|
||||
|
||||
int openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags);
|
||||
|
||||
bool openvpn_execve_check(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *error_message);
|
||||
|
||||
bool openvpn_execve_allowed(const unsigned int flags);
|
||||
|
||||
static inline bool
|
||||
openvpn_run_script (const struct argv *a, const struct env_set *es, const unsigned int flags, const char *hook)
|
||||
openvpn_run_script(const struct argv *a, const struct env_set *es, const unsigned int flags, const char *hook)
|
||||
{
|
||||
char msg[256];
|
||||
char msg[256];
|
||||
|
||||
openvpn_snprintf(msg, sizeof(msg), "WARNING: Failed running command (%s)", hook);
|
||||
return openvpn_execve_check(a, es, flags | S_SCRIPT, msg);
|
||||
openvpn_snprintf(msg, sizeof(msg), "WARNING: Failed running command (%s)", hook);
|
||||
return openvpn_execve_check(a, es, flags | S_SCRIPT, msg);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_STRERROR
|
||||
/* a thread-safe version of strerror */
|
||||
const char* strerror_ts (int errnum, struct gc_arena *gc);
|
||||
const char *strerror_ts(int errnum, struct gc_arena *gc);
|
||||
|
||||
#endif
|
||||
|
||||
/* Set standard file descriptors to /dev/null */
|
||||
void set_std_files_to_null (bool stdin_only);
|
||||
void set_std_files_to_null(bool stdin_only);
|
||||
|
||||
/* dup inetd/xinetd socket descriptor and save */
|
||||
extern int inetd_socket_descriptor;
|
||||
void save_inetd_socket_descriptor (void);
|
||||
void save_inetd_socket_descriptor(void);
|
||||
|
||||
/* init random() function, only used as source for weak random numbers, when !ENABLE_CRYPTO */
|
||||
void init_random_seed(void);
|
||||
|
||||
/* set/delete environmental variable */
|
||||
void setenv_str_ex (struct env_set *es,
|
||||
const char *name,
|
||||
const char *value,
|
||||
const unsigned int name_include,
|
||||
const unsigned int name_exclude,
|
||||
const char name_replace,
|
||||
const unsigned int value_include,
|
||||
const unsigned int value_exclude,
|
||||
const char value_replace);
|
||||
void setenv_str_ex(struct env_set *es,
|
||||
const char *name,
|
||||
const char *value,
|
||||
const unsigned int name_include,
|
||||
const unsigned int name_exclude,
|
||||
const char name_replace,
|
||||
const unsigned int value_include,
|
||||
const unsigned int value_exclude,
|
||||
const char value_replace);
|
||||
|
||||
void setenv_counter (struct env_set *es, const char *name, counter_type value);
|
||||
void setenv_int (struct env_set *es, const char *name, int value);
|
||||
void setenv_unsigned (struct env_set *es, const char *name, unsigned int value);
|
||||
void setenv_str (struct env_set *es, const char *name, const char *value);
|
||||
void setenv_str_safe (struct env_set *es, const char *name, const char *value);
|
||||
void setenv_del (struct env_set *es, const char *name);
|
||||
void setenv_counter(struct env_set *es, const char *name, counter_type value);
|
||||
|
||||
void setenv_int(struct env_set *es, const char *name, int value);
|
||||
|
||||
void setenv_unsigned(struct env_set *es, const char *name, unsigned int value);
|
||||
|
||||
void setenv_str(struct env_set *es, const char *name, const char *value);
|
||||
|
||||
void setenv_str_safe(struct env_set *es, const char *name, const char *value);
|
||||
|
||||
void setenv_del(struct env_set *es, const char *name);
|
||||
|
||||
/**
|
||||
* Store the supplied name value pair in the env_set. If the variable with the
|
||||
|
|
@ -132,51 +141,59 @@ void setenv_del (struct env_set *es, const char *name);
|
|||
*/
|
||||
void setenv_str_incr(struct env_set *es, const char *name, const char *value);
|
||||
|
||||
void setenv_int_i (struct env_set *es, const char *name, const int value, const int i);
|
||||
void setenv_str_i (struct env_set *es, const char *name, const char *value, const int i);
|
||||
void setenv_int_i(struct env_set *es, const char *name, const int value, const int i);
|
||||
|
||||
void setenv_str_i(struct env_set *es, const char *name, const char *value, const int i);
|
||||
|
||||
/* struct env_set functions */
|
||||
|
||||
struct env_set *env_set_create (struct gc_arena *gc);
|
||||
void env_set_destroy (struct env_set *es);
|
||||
bool env_set_del (struct env_set *es, const char *str);
|
||||
void env_set_add (struct env_set *es, const char *str);
|
||||
const char* env_set_get (const struct env_set *es, const char *name);
|
||||
struct env_set *env_set_create(struct gc_arena *gc);
|
||||
|
||||
void env_set_print (int msglevel, const struct env_set *es);
|
||||
void env_set_destroy(struct env_set *es);
|
||||
|
||||
void env_set_inherit (struct env_set *es, const struct env_set *src);
|
||||
bool env_set_del(struct env_set *es, const char *str);
|
||||
|
||||
void env_set_add_to_environment (const struct env_set *es);
|
||||
void env_set_remove_from_environment (const struct env_set *es);
|
||||
void env_set_add(struct env_set *es, const char *str);
|
||||
|
||||
const char *env_set_get(const struct env_set *es, const char *name);
|
||||
|
||||
void env_set_print(int msglevel, const struct env_set *es);
|
||||
|
||||
void env_set_inherit(struct env_set *es, const struct env_set *src);
|
||||
|
||||
void env_set_add_to_environment(const struct env_set *es);
|
||||
|
||||
void env_set_remove_from_environment(const struct env_set *es);
|
||||
|
||||
/* Make arrays of strings */
|
||||
|
||||
const char **make_env_array (const struct env_set *es,
|
||||
const bool check_allowed,
|
||||
struct gc_arena *gc);
|
||||
const char **make_env_array(const struct env_set *es,
|
||||
const bool check_allowed,
|
||||
struct gc_arena *gc);
|
||||
|
||||
const char **make_arg_array (const char *first, const char *parms, struct gc_arena *gc);
|
||||
const char **make_extended_arg_array (char **p, struct gc_arena *gc);
|
||||
const char **make_arg_array(const char *first, const char *parms, struct gc_arena *gc);
|
||||
|
||||
const char **make_extended_arg_array(char **p, struct gc_arena *gc);
|
||||
|
||||
/* an analogue to the random() function, but use OpenSSL functions if available */
|
||||
#ifdef ENABLE_CRYPTO
|
||||
long int get_random(void);
|
||||
|
||||
#else
|
||||
#define get_random random
|
||||
#endif
|
||||
|
||||
/* return true if filename can be opened for read */
|
||||
bool test_file (const char *filename);
|
||||
bool test_file(const char *filename);
|
||||
|
||||
/* create a temporary file in directory, returns the filename of the created file */
|
||||
const char *create_temp_file (const char *directory, const char *prefix, struct gc_arena *gc);
|
||||
const char *create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc);
|
||||
|
||||
/* put a directory and filename together */
|
||||
const char *gen_path (const char *directory, const char *filename, struct gc_arena *gc);
|
||||
const char *gen_path(const char *directory, const char *filename, struct gc_arena *gc);
|
||||
|
||||
/* return true if pathname is absolute */
|
||||
bool absolute_pathname (const char *pathname);
|
||||
bool absolute_pathname(const char *pathname);
|
||||
|
||||
/* prepend a random prefix to hostname (need ENABLE_CRYPTO) */
|
||||
const char *hostname_randomize(const char *hostname, struct gc_arena *gc);
|
||||
|
|
@ -187,17 +204,17 @@ const char *hostname_randomize(const char *hostname, struct gc_arena *gc);
|
|||
|
||||
struct user_pass
|
||||
{
|
||||
bool defined;
|
||||
bool nocache;
|
||||
bool defined;
|
||||
bool nocache;
|
||||
|
||||
/* max length of username/password */
|
||||
# ifdef ENABLE_PKCS11
|
||||
# define USER_PASS_LEN 4096
|
||||
# else
|
||||
# define USER_PASS_LEN 128
|
||||
# endif
|
||||
char username[USER_PASS_LEN];
|
||||
char password[USER_PASS_LEN];
|
||||
#ifdef ENABLE_PKCS11
|
||||
#define USER_PASS_LEN 4096
|
||||
#else
|
||||
#define USER_PASS_LEN 128
|
||||
#endif
|
||||
char username[USER_PASS_LEN];
|
||||
char password[USER_PASS_LEN];
|
||||
};
|
||||
|
||||
#ifdef ENABLE_CLIENT_CR
|
||||
|
|
@ -205,31 +222,31 @@ struct user_pass
|
|||
* Challenge response info on client as pushed by server.
|
||||
*/
|
||||
struct auth_challenge_info {
|
||||
# define CR_ECHO (1<<0) /* echo response when typed by user */
|
||||
# define CR_RESPONSE (1<<1) /* response needed */
|
||||
unsigned int flags;
|
||||
#define CR_ECHO (1<<0) /* echo response when typed by user */
|
||||
#define CR_RESPONSE (1<<1) /* response needed */
|
||||
unsigned int flags;
|
||||
|
||||
const char *user;
|
||||
const char *state_id;
|
||||
const char *challenge_text;
|
||||
const char *user;
|
||||
const char *state_id;
|
||||
const char *challenge_text;
|
||||
};
|
||||
|
||||
struct auth_challenge_info *get_auth_challenge (const char *auth_challenge, struct gc_arena *gc);
|
||||
struct auth_challenge_info *get_auth_challenge(const char *auth_challenge, struct gc_arena *gc);
|
||||
|
||||
/*
|
||||
* Challenge response info on client as pushed by server.
|
||||
*/
|
||||
struct static_challenge_info {
|
||||
# define SC_ECHO (1<<0) /* echo response when typed by user */
|
||||
unsigned int flags;
|
||||
#define SC_ECHO (1<<0) /* echo response when typed by user */
|
||||
unsigned int flags;
|
||||
|
||||
const char *challenge_text;
|
||||
const char *challenge_text;
|
||||
};
|
||||
|
||||
#else
|
||||
#else /* ifdef ENABLE_CLIENT_CR */
|
||||
struct auth_challenge_info {};
|
||||
struct static_challenge_info {};
|
||||
#endif
|
||||
#endif /* ifdef ENABLE_CLIENT_CR */
|
||||
|
||||
/*
|
||||
* Flags for get_user_pass and management_query_user_pass
|
||||
|
|
@ -248,54 +265,55 @@ struct static_challenge_info {};
|
|||
|
||||
#define GET_USER_PASS_INLINE_CREDS (1<<10) /* indicates that auth_file is actually inline creds */
|
||||
|
||||
bool get_user_pass_cr (struct user_pass *up,
|
||||
const char *auth_file,
|
||||
const char *prefix,
|
||||
const unsigned int flags,
|
||||
const char *auth_challenge);
|
||||
bool get_user_pass_cr(struct user_pass *up,
|
||||
const char *auth_file,
|
||||
const char *prefix,
|
||||
const unsigned int flags,
|
||||
const char *auth_challenge);
|
||||
|
||||
static inline bool
|
||||
get_user_pass (struct user_pass *up,
|
||||
const char *auth_file,
|
||||
const char *prefix,
|
||||
const unsigned int flags)
|
||||
get_user_pass(struct user_pass *up,
|
||||
const char *auth_file,
|
||||
const char *prefix,
|
||||
const unsigned int flags)
|
||||
{
|
||||
return get_user_pass_cr (up, auth_file, prefix, flags, NULL);
|
||||
return get_user_pass_cr(up, auth_file, prefix, flags, NULL);
|
||||
}
|
||||
|
||||
void fail_user_pass (const char *prefix,
|
||||
const unsigned int flags,
|
||||
const char *reason);
|
||||
void fail_user_pass(const char *prefix,
|
||||
const unsigned int flags,
|
||||
const char *reason);
|
||||
|
||||
void purge_user_pass (struct user_pass *up, const bool force);
|
||||
void purge_user_pass(struct user_pass *up, const bool force);
|
||||
|
||||
void set_auth_token (struct user_pass *up, const char *token);
|
||||
void set_auth_token(struct user_pass *up, const char *token);
|
||||
|
||||
/*
|
||||
* Process string received by untrusted peer before
|
||||
* printing to console or log file.
|
||||
* Assumes that string has been null terminated.
|
||||
*/
|
||||
const char *safe_print (const char *str, struct gc_arena *gc);
|
||||
const char *safe_print(const char *str, struct gc_arena *gc);
|
||||
|
||||
/* returns true if environmental variable safe to print to log */
|
||||
bool env_safe_to_print (const char *str);
|
||||
bool env_safe_to_print(const char *str);
|
||||
|
||||
/* returns true if environmental variable may be passed to an external program */
|
||||
bool env_allowed (const char *str);
|
||||
bool env_allowed(const char *str);
|
||||
|
||||
/*
|
||||
* A sleep function that services the management layer for n
|
||||
* seconds rather than doing nothing.
|
||||
*/
|
||||
void openvpn_sleep (const int n);
|
||||
void openvpn_sleep(const int n);
|
||||
|
||||
void configure_path (void);
|
||||
void configure_path(void);
|
||||
|
||||
const char *sanitize_control_message(const char *str, struct gc_arena *gc);
|
||||
|
||||
#if AUTO_USERID
|
||||
void get_user_pass_auto_userid (struct user_pass *up, const char *tag);
|
||||
void get_user_pass_auto_userid(struct user_pass *up, const char *tag);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
@ -313,19 +331,21 @@ extern const char *iproute_path;
|
|||
extern int script_security; /* GLOBAL */
|
||||
|
||||
/* return the next largest power of 2 */
|
||||
size_t adjust_power_of_2 (size_t u);
|
||||
size_t adjust_power_of_2(size_t u);
|
||||
|
||||
#define COMPAT_FLAG_QUERY 0 /** compat_flags operator: Query for a flag */
|
||||
#define COMPAT_FLAG_SET (1<<0) /** compat_flags operator: Set a compat flag */
|
||||
#define COMPAT_NAMES (1<<1) /** compat flag: --compat-names set */
|
||||
#define COMPAT_NO_NAME_REMAPPING (1<<2) /** compat flag: --compat-names without char remapping */
|
||||
bool compat_flag (unsigned int flag);
|
||||
bool compat_flag(unsigned int flag);
|
||||
|
||||
#if P2MP_SERVER
|
||||
/* helper to parse peer_info received from multi client, validate
|
||||
* (this is untrusted data) and put into environment */
|
||||
bool validate_peer_info_line(char *line);
|
||||
void output_peer_info_env (struct env_set *es, const char * peer_info);
|
||||
|
||||
void output_peer_info_env(struct env_set *es, const char *peer_info);
|
||||
|
||||
#endif /* P2MP_SERVER */
|
||||
|
||||
#endif
|
||||
#endif /* ifndef MISC_H */
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@
|
|||
#include "memdbg.h"
|
||||
|
||||
void
|
||||
mroute_addr_init (struct mroute_addr *addr)
|
||||
mroute_addr_init(struct mroute_addr *addr)
|
||||
{
|
||||
CLEAR (*addr);
|
||||
CLEAR(*addr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -50,269 +50,288 @@ mroute_addr_init (struct mroute_addr *addr)
|
|||
*/
|
||||
|
||||
static inline bool
|
||||
is_mac_mcast_addr (const uint8_t *mac)
|
||||
is_mac_mcast_addr(const uint8_t *mac)
|
||||
{
|
||||
return (bool) (mac[0] & 1);
|
||||
return (bool) (mac[0] & 1);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
is_mac_mcast_maddr (const struct mroute_addr *addr)
|
||||
is_mac_mcast_maddr(const struct mroute_addr *addr)
|
||||
{
|
||||
return (addr->type & MR_ADDR_MASK) == MR_ADDR_ETHER &&
|
||||
is_mac_mcast_addr (addr->eth_addr);
|
||||
return (addr->type & MR_ADDR_MASK) == MR_ADDR_ETHER
|
||||
&& is_mac_mcast_addr(addr->eth_addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't learn certain addresses.
|
||||
*/
|
||||
bool
|
||||
mroute_learnable_address (const struct mroute_addr *addr)
|
||||
mroute_learnable_address(const struct mroute_addr *addr)
|
||||
{
|
||||
int i;
|
||||
bool not_all_zeros = false;
|
||||
bool not_all_ones = false;
|
||||
int i;
|
||||
bool not_all_zeros = false;
|
||||
bool not_all_ones = false;
|
||||
|
||||
for (i = 0; i < addr->len; ++i)
|
||||
for (i = 0; i < addr->len; ++i)
|
||||
{
|
||||
int b = addr->raw_addr[i];
|
||||
if (b != 0x00)
|
||||
not_all_zeros = true;
|
||||
if (b != 0xFF)
|
||||
not_all_ones = true;
|
||||
int b = addr->raw_addr[i];
|
||||
if (b != 0x00)
|
||||
{
|
||||
not_all_zeros = true;
|
||||
}
|
||||
if (b != 0xFF)
|
||||
{
|
||||
not_all_ones = true;
|
||||
}
|
||||
}
|
||||
return not_all_zeros && not_all_ones && !is_mac_mcast_maddr (addr);
|
||||
return not_all_zeros && not_all_ones && !is_mac_mcast_maddr(addr);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mroute_get_in_addr_t (struct mroute_addr *ma, const in_addr_t src, unsigned int mask)
|
||||
mroute_get_in_addr_t(struct mroute_addr *ma, const in_addr_t src, unsigned int mask)
|
||||
{
|
||||
if (ma)
|
||||
if (ma)
|
||||
{
|
||||
ma->type = MR_ADDR_IPV4 | mask;
|
||||
ma->netbits = 0;
|
||||
ma->len = 4;
|
||||
ma->v4.addr = src;
|
||||
ma->type = MR_ADDR_IPV4 | mask;
|
||||
ma->netbits = 0;
|
||||
ma->len = 4;
|
||||
ma->v4.addr = src;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
mroute_get_in6_addr (struct mroute_addr *ma, const struct in6_addr src, unsigned int mask)
|
||||
mroute_get_in6_addr(struct mroute_addr *ma, const struct in6_addr src, unsigned int mask)
|
||||
{
|
||||
if (ma)
|
||||
if (ma)
|
||||
{
|
||||
ma->type = MR_ADDR_IPV6 | mask;
|
||||
ma->netbits = 0;
|
||||
ma->len = 16;
|
||||
ma->v6.addr = src;
|
||||
ma->type = MR_ADDR_IPV6 | mask;
|
||||
ma->netbits = 0;
|
||||
ma->len = 16;
|
||||
ma->v6.addr = src;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mroute_is_mcast (const in_addr_t addr)
|
||||
mroute_is_mcast(const in_addr_t addr)
|
||||
{
|
||||
return ((addr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK));
|
||||
return ((addr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK));
|
||||
}
|
||||
|
||||
/* RFC 4291, 2.7, "binary 11111111 at the start of an address identifies
|
||||
/* RFC 4291, 2.7, "binary 11111111 at the start of an address identifies
|
||||
* the address as being a multicast address"
|
||||
*/
|
||||
static inline bool
|
||||
mroute_is_mcast_ipv6 (const struct in6_addr addr)
|
||||
mroute_is_mcast_ipv6(const struct in6_addr addr)
|
||||
{
|
||||
return (addr.s6_addr[0] == 0xff);
|
||||
return (addr.s6_addr[0] == 0xff);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_PF
|
||||
|
||||
static unsigned int
|
||||
mroute_extract_addr_arp (struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
const struct buffer *buf)
|
||||
mroute_extract_addr_arp(struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
const struct buffer *buf)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
if (BLEN (buf) >= (int) sizeof (struct openvpn_arp))
|
||||
unsigned int ret = 0;
|
||||
if (BLEN(buf) >= (int) sizeof(struct openvpn_arp))
|
||||
{
|
||||
const struct openvpn_arp *arp = (const struct openvpn_arp *) BPTR (buf);
|
||||
if (arp->mac_addr_type == htons(0x0001)
|
||||
&& arp->proto_addr_type == htons(0x0800)
|
||||
&& arp->mac_addr_size == 0x06
|
||||
&& arp->proto_addr_size == 0x04)
|
||||
{
|
||||
mroute_get_in_addr_t (src, arp->ip_src, MR_ARP);
|
||||
mroute_get_in_addr_t (dest, arp->ip_dest, MR_ARP);
|
||||
const struct openvpn_arp *arp = (const struct openvpn_arp *) BPTR(buf);
|
||||
if (arp->mac_addr_type == htons(0x0001)
|
||||
&& arp->proto_addr_type == htons(0x0800)
|
||||
&& arp->mac_addr_size == 0x06
|
||||
&& arp->proto_addr_size == 0x04)
|
||||
{
|
||||
mroute_get_in_addr_t(src, arp->ip_src, MR_ARP);
|
||||
mroute_get_in_addr_t(dest, arp->ip_dest, MR_ARP);
|
||||
|
||||
/* multicast packet? */
|
||||
if (mroute_is_mcast (arp->ip_dest))
|
||||
ret |= MROUTE_EXTRACT_MCAST;
|
||||
/* multicast packet? */
|
||||
if (mroute_is_mcast(arp->ip_dest))
|
||||
{
|
||||
ret |= MROUTE_EXTRACT_MCAST;
|
||||
}
|
||||
|
||||
ret |= MROUTE_EXTRACT_SUCCEEDED;
|
||||
}
|
||||
ret |= MROUTE_EXTRACT_SUCCEEDED;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* ifdef ENABLE_PF */
|
||||
|
||||
unsigned int
|
||||
mroute_extract_addr_ipv4 (struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
const struct buffer *buf)
|
||||
mroute_extract_addr_ipv4(struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
const struct buffer *buf)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
if (BLEN (buf) >= 1)
|
||||
unsigned int ret = 0;
|
||||
if (BLEN(buf) >= 1)
|
||||
{
|
||||
switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
|
||||
{
|
||||
case 4:
|
||||
if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
|
||||
{
|
||||
const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);
|
||||
switch (OPENVPN_IPH_GET_VER(*BPTR(buf)))
|
||||
{
|
||||
case 4:
|
||||
if (BLEN(buf) >= (int) sizeof(struct openvpn_iphdr))
|
||||
{
|
||||
const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR(buf);
|
||||
|
||||
mroute_get_in_addr_t (src, ip->saddr, 0);
|
||||
mroute_get_in_addr_t (dest, ip->daddr, 0);
|
||||
mroute_get_in_addr_t(src, ip->saddr, 0);
|
||||
mroute_get_in_addr_t(dest, ip->daddr, 0);
|
||||
|
||||
/* multicast packet? */
|
||||
if (mroute_is_mcast (ip->daddr))
|
||||
ret |= MROUTE_EXTRACT_MCAST;
|
||||
/* multicast packet? */
|
||||
if (mroute_is_mcast(ip->daddr))
|
||||
{
|
||||
ret |= MROUTE_EXTRACT_MCAST;
|
||||
}
|
||||
|
||||
/* IGMP message? */
|
||||
if (ip->protocol == OPENVPN_IPPROTO_IGMP)
|
||||
ret |= MROUTE_EXTRACT_IGMP;
|
||||
/* IGMP message? */
|
||||
if (ip->protocol == OPENVPN_IPPROTO_IGMP)
|
||||
{
|
||||
ret |= MROUTE_EXTRACT_IGMP;
|
||||
}
|
||||
|
||||
ret |= MROUTE_EXTRACT_SUCCEEDED;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (BLEN (buf) >= (int) sizeof (struct openvpn_ipv6hdr))
|
||||
{
|
||||
const struct openvpn_ipv6hdr *ipv6 = (const struct openvpn_ipv6hdr *) BPTR (buf);
|
||||
#if 0 /* very basic debug */
|
||||
struct gc_arena gc = gc_new ();
|
||||
msg( M_INFO, "IPv6 packet! src=%s, dst=%s",
|
||||
print_in6_addr( ipv6->saddr, 0, &gc ),
|
||||
print_in6_addr( ipv6->daddr, 0, &gc ));
|
||||
gc_free (&gc);
|
||||
ret |= MROUTE_EXTRACT_SUCCEEDED;
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if (BLEN(buf) >= (int) sizeof(struct openvpn_ipv6hdr))
|
||||
{
|
||||
const struct openvpn_ipv6hdr *ipv6 = (const struct openvpn_ipv6hdr *) BPTR(buf);
|
||||
#if 0 /* very basic debug */
|
||||
struct gc_arena gc = gc_new();
|
||||
msg( M_INFO, "IPv6 packet! src=%s, dst=%s",
|
||||
print_in6_addr( ipv6->saddr, 0, &gc ),
|
||||
print_in6_addr( ipv6->daddr, 0, &gc ));
|
||||
gc_free(&gc);
|
||||
#endif
|
||||
|
||||
mroute_get_in6_addr (src, ipv6->saddr, 0);
|
||||
mroute_get_in6_addr (dest, ipv6->daddr, 0);
|
||||
mroute_get_in6_addr(src, ipv6->saddr, 0);
|
||||
mroute_get_in6_addr(dest, ipv6->daddr, 0);
|
||||
|
||||
if (mroute_is_mcast_ipv6 (ipv6->daddr))
|
||||
ret |= MROUTE_EXTRACT_MCAST;
|
||||
if (mroute_is_mcast_ipv6(ipv6->daddr))
|
||||
{
|
||||
ret |= MROUTE_EXTRACT_MCAST;
|
||||
}
|
||||
|
||||
ret |= MROUTE_EXTRACT_SUCCEEDED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
msg (M_WARN, "IP packet with unknown IP version=%d seen",
|
||||
OPENVPN_IPH_GET_VER (*BPTR(buf)));
|
||||
}
|
||||
ret |= MROUTE_EXTRACT_SUCCEEDED;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
msg(M_WARN, "IP packet with unknown IP version=%d seen",
|
||||
OPENVPN_IPH_GET_VER(*BPTR(buf)));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
mroute_extract_addr_ether (struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
struct mroute_addr *esrc,
|
||||
struct mroute_addr *edest,
|
||||
const struct buffer *buf)
|
||||
mroute_extract_addr_ether(struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
struct mroute_addr *esrc,
|
||||
struct mroute_addr *edest,
|
||||
const struct buffer *buf)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr))
|
||||
unsigned int ret = 0;
|
||||
if (BLEN(buf) >= (int) sizeof(struct openvpn_ethhdr))
|
||||
{
|
||||
const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf);
|
||||
if (src)
|
||||
{
|
||||
src->type = MR_ADDR_ETHER;
|
||||
src->netbits = 0;
|
||||
src->len = 6;
|
||||
memcpy (src->eth_addr, eth->source, sizeof(dest->eth_addr));
|
||||
}
|
||||
if (dest)
|
||||
{
|
||||
dest->type = MR_ADDR_ETHER;
|
||||
dest->netbits = 0;
|
||||
dest->len = 6;
|
||||
memcpy (dest->eth_addr, eth->dest, sizeof(dest->eth_addr));
|
||||
const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR(buf);
|
||||
if (src)
|
||||
{
|
||||
src->type = MR_ADDR_ETHER;
|
||||
src->netbits = 0;
|
||||
src->len = 6;
|
||||
memcpy(src->eth_addr, eth->source, sizeof(dest->eth_addr));
|
||||
}
|
||||
if (dest)
|
||||
{
|
||||
dest->type = MR_ADDR_ETHER;
|
||||
dest->netbits = 0;
|
||||
dest->len = 6;
|
||||
memcpy(dest->eth_addr, eth->dest, sizeof(dest->eth_addr));
|
||||
|
||||
/* ethernet broadcast/multicast packet? */
|
||||
if (is_mac_mcast_addr (eth->dest))
|
||||
ret |= MROUTE_EXTRACT_BCAST;
|
||||
}
|
||||
|
||||
ret |= MROUTE_EXTRACT_SUCCEEDED;
|
||||
/* ethernet broadcast/multicast packet? */
|
||||
if (is_mac_mcast_addr(eth->dest))
|
||||
{
|
||||
ret |= MROUTE_EXTRACT_BCAST;
|
||||
}
|
||||
}
|
||||
|
||||
ret |= MROUTE_EXTRACT_SUCCEEDED;
|
||||
|
||||
#ifdef ENABLE_PF
|
||||
if (esrc || edest)
|
||||
{
|
||||
struct buffer b = *buf;
|
||||
if (buf_advance (&b, sizeof (struct openvpn_ethhdr)))
|
||||
{
|
||||
switch (ntohs (eth->proto))
|
||||
{
|
||||
case OPENVPN_ETH_P_IPV4:
|
||||
ret |= (mroute_extract_addr_ipv4 (esrc, edest, &b) << MROUTE_SEC_SHIFT);
|
||||
break;
|
||||
case OPENVPN_ETH_P_ARP:
|
||||
ret |= (mroute_extract_addr_arp (esrc, edest, &b) << MROUTE_SEC_SHIFT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (esrc || edest)
|
||||
{
|
||||
struct buffer b = *buf;
|
||||
if (buf_advance(&b, sizeof(struct openvpn_ethhdr)))
|
||||
{
|
||||
switch (ntohs(eth->proto))
|
||||
{
|
||||
case OPENVPN_ETH_P_IPV4:
|
||||
ret |= (mroute_extract_addr_ipv4(esrc, edest, &b) << MROUTE_SEC_SHIFT);
|
||||
break;
|
||||
|
||||
case OPENVPN_ETH_P_ARP:
|
||||
ret |= (mroute_extract_addr_arp(esrc, edest, &b) << MROUTE_SEC_SHIFT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a struct openvpn_sockaddr (osaddr)
|
||||
* to a struct mroute_addr (addr).
|
||||
*/
|
||||
bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
|
||||
const struct openvpn_sockaddr *osaddr,
|
||||
bool use_port)
|
||||
bool
|
||||
mroute_extract_openvpn_sockaddr(struct mroute_addr *addr,
|
||||
const struct openvpn_sockaddr *osaddr,
|
||||
bool use_port)
|
||||
{
|
||||
switch (osaddr->addr.sa.sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
switch (osaddr->addr.sa.sa_family)
|
||||
{
|
||||
if (use_port)
|
||||
{
|
||||
addr->type = MR_ADDR_IPV4 | MR_WITH_PORT;
|
||||
addr->netbits = 0;
|
||||
addr->len = 6;
|
||||
addr->v4.addr = osaddr->addr.in4.sin_addr.s_addr;
|
||||
addr->v4.port = osaddr->addr.in4.sin_port;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr->type = MR_ADDR_IPV4;
|
||||
addr->netbits = 0;
|
||||
addr->len = 4;
|
||||
addr->v4.addr = osaddr->addr.in4.sin_addr.s_addr;
|
||||
}
|
||||
return true;
|
||||
case AF_INET:
|
||||
{
|
||||
if (use_port)
|
||||
{
|
||||
addr->type = MR_ADDR_IPV4 | MR_WITH_PORT;
|
||||
addr->netbits = 0;
|
||||
addr->len = 6;
|
||||
addr->v4.addr = osaddr->addr.in4.sin_addr.s_addr;
|
||||
addr->v4.port = osaddr->addr.in4.sin_port;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr->type = MR_ADDR_IPV4;
|
||||
addr->netbits = 0;
|
||||
addr->len = 4;
|
||||
addr->v4.addr = osaddr->addr.in4.sin_addr.s_addr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case AF_INET6:
|
||||
if (use_port)
|
||||
{
|
||||
addr->type = MR_ADDR_IPV6 | MR_WITH_PORT;
|
||||
addr->netbits = 0;
|
||||
addr->len = 18;
|
||||
addr->v6.addr = osaddr->addr.in6.sin6_addr;
|
||||
addr->v6.port = osaddr->addr.in6.sin6_port;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr->type = MR_ADDR_IPV6;
|
||||
addr->netbits = 0;
|
||||
addr->len = 16;
|
||||
addr->v6.addr = osaddr->addr.in6.sin6_addr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case AF_INET6:
|
||||
if (use_port)
|
||||
{
|
||||
addr->type = MR_ADDR_IPV6 | MR_WITH_PORT;
|
||||
addr->netbits = 0;
|
||||
addr->len = 18;
|
||||
addr->v6.addr = osaddr->addr.in6.sin6_addr;
|
||||
addr->v6.port = osaddr->addr.in6.sin6_port;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr->type = MR_ADDR_IPV6;
|
||||
addr->netbits = 0;
|
||||
addr->len = 16;
|
||||
addr->v6.addr = osaddr->addr.in6.sin6_addr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -325,36 +344,38 @@ bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
|
|||
* might benefit from some "zeroize 32 bit at a time" improvements
|
||||
*/
|
||||
void
|
||||
mroute_addr_mask_host_bits (struct mroute_addr *ma)
|
||||
mroute_addr_mask_host_bits(struct mroute_addr *ma)
|
||||
{
|
||||
if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4)
|
||||
if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV4)
|
||||
{
|
||||
in_addr_t addr = ntohl (ma->v4.addr);
|
||||
addr &= netbits_to_netmask (ma->netbits);
|
||||
ma->v4.addr = htonl (addr);
|
||||
in_addr_t addr = ntohl(ma->v4.addr);
|
||||
addr &= netbits_to_netmask(ma->netbits);
|
||||
ma->v4.addr = htonl(addr);
|
||||
}
|
||||
else if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV6)
|
||||
else if ((ma->type & MR_ADDR_MASK) == MR_ADDR_IPV6)
|
||||
{
|
||||
int byte = sizeof (ma->v6.addr) - 1; /* rightmost byte in address */
|
||||
int bits_to_clear = 128 - ma->netbits;
|
||||
int byte = sizeof(ma->v6.addr) - 1; /* rightmost byte in address */
|
||||
int bits_to_clear = 128 - ma->netbits;
|
||||
|
||||
while( byte >= 0 && bits_to_clear > 0 )
|
||||
while (byte >= 0 && bits_to_clear > 0)
|
||||
{
|
||||
if ( bits_to_clear >= 8 )
|
||||
{
|
||||
ma->v6.addr.s6_addr[byte--] = 0;
|
||||
bits_to_clear -= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
ma->v6.addr.s6_addr[byte--] &= (IPV4_NETMASK_HOST << bits_to_clear);
|
||||
bits_to_clear = 0;
|
||||
}
|
||||
if (bits_to_clear >= 8)
|
||||
{
|
||||
ma->v6.addr.s6_addr[byte--] = 0;
|
||||
bits_to_clear -= 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
ma->v6.addr.s6_addr[byte--] &= (IPV4_NETMASK_HOST << bits_to_clear);
|
||||
bits_to_clear = 0;
|
||||
}
|
||||
}
|
||||
ASSERT( bits_to_clear == 0 );
|
||||
ASSERT( bits_to_clear == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
else
|
||||
ASSERT(0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -363,91 +384,100 @@ mroute_addr_mask_host_bits (struct mroute_addr *ma)
|
|||
* and the actual address.
|
||||
*/
|
||||
uint32_t
|
||||
mroute_addr_hash_function (const void *key, uint32_t iv)
|
||||
mroute_addr_hash_function(const void *key, uint32_t iv)
|
||||
{
|
||||
return hash_func (mroute_addr_hash_ptr ((const struct mroute_addr *) key),
|
||||
mroute_addr_hash_len ((const struct mroute_addr *) key),
|
||||
iv);
|
||||
return hash_func(mroute_addr_hash_ptr((const struct mroute_addr *) key),
|
||||
mroute_addr_hash_len((const struct mroute_addr *) key),
|
||||
iv);
|
||||
}
|
||||
|
||||
bool
|
||||
mroute_addr_compare_function (const void *key1, const void *key2)
|
||||
mroute_addr_compare_function(const void *key1, const void *key2)
|
||||
{
|
||||
return mroute_addr_equal ((const struct mroute_addr *) key1,
|
||||
(const struct mroute_addr *) key2);
|
||||
return mroute_addr_equal((const struct mroute_addr *) key1,
|
||||
(const struct mroute_addr *) key2);
|
||||
}
|
||||
|
||||
const char *
|
||||
mroute_addr_print (const struct mroute_addr *ma,
|
||||
struct gc_arena *gc)
|
||||
mroute_addr_print(const struct mroute_addr *ma,
|
||||
struct gc_arena *gc)
|
||||
{
|
||||
return mroute_addr_print_ex (ma, MAPF_IA_EMPTY_IF_UNDEF, gc);
|
||||
return mroute_addr_print_ex(ma, MAPF_IA_EMPTY_IF_UNDEF, gc);
|
||||
}
|
||||
|
||||
const char *
|
||||
mroute_addr_print_ex (const struct mroute_addr *ma,
|
||||
const unsigned int flags,
|
||||
struct gc_arena *gc)
|
||||
mroute_addr_print_ex(const struct mroute_addr *ma,
|
||||
const unsigned int flags,
|
||||
struct gc_arena *gc)
|
||||
{
|
||||
struct buffer out = alloc_buf_gc (64, gc);
|
||||
if (ma)
|
||||
struct buffer out = alloc_buf_gc(64, gc);
|
||||
if (ma)
|
||||
{
|
||||
struct mroute_addr maddr = *ma;
|
||||
struct mroute_addr maddr = *ma;
|
||||
|
||||
switch (maddr.type & MR_ADDR_MASK)
|
||||
{
|
||||
case MR_ADDR_ETHER:
|
||||
buf_printf (&out, "%s", format_hex_ex (ma->eth_addr,
|
||||
sizeof(ma->eth_addr), 0, 1, ":", gc));
|
||||
break;
|
||||
case MR_ADDR_IPV4:
|
||||
{
|
||||
if ((flags & MAPF_SHOW_ARP) && (maddr.type & MR_ARP))
|
||||
buf_printf (&out, "ARP/");
|
||||
buf_printf (&out, "%s", print_in_addr_t (ntohl (maddr.v4.addr),
|
||||
(flags & MAPF_IA_EMPTY_IF_UNDEF) ? IA_EMPTY_IF_UNDEF : 0, gc));
|
||||
if (maddr.type & MR_WITH_NETBITS)
|
||||
{
|
||||
if (flags & MAPF_SUBNET)
|
||||
{
|
||||
const in_addr_t netmask = netbits_to_netmask (maddr.netbits);
|
||||
buf_printf (&out, "/%s", print_in_addr_t (netmask, 0, gc));
|
||||
}
|
||||
else
|
||||
buf_printf (&out, "/%d", maddr.netbits);
|
||||
}
|
||||
if (maddr.type & MR_WITH_PORT)
|
||||
{
|
||||
buf_printf (&out, ":%d", ntohs (maddr.v4.port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MR_ADDR_IPV6:
|
||||
{
|
||||
if ( IN6_IS_ADDR_V4MAPPED( &maddr.v6.addr ) )
|
||||
{
|
||||
buf_printf (&out, "%s", print_in_addr_t (maddr.v4mappedv6.addr,
|
||||
IA_NET_ORDER, gc));
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_printf (&out, "%s", print_in6_addr (maddr.v6.addr, 0, gc));
|
||||
}
|
||||
if (maddr.type & MR_WITH_NETBITS)
|
||||
{
|
||||
buf_printf (&out, "/%d", maddr.netbits);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
buf_printf (&out, "UNKNOWN");
|
||||
break;
|
||||
}
|
||||
return BSTR (&out);
|
||||
}
|
||||
switch (maddr.type & MR_ADDR_MASK)
|
||||
{
|
||||
case MR_ADDR_ETHER:
|
||||
buf_printf(&out, "%s", format_hex_ex(ma->eth_addr,
|
||||
sizeof(ma->eth_addr), 0, 1, ":", gc));
|
||||
break;
|
||||
|
||||
case MR_ADDR_IPV4:
|
||||
{
|
||||
if ((flags & MAPF_SHOW_ARP) && (maddr.type & MR_ARP))
|
||||
{
|
||||
buf_printf(&out, "ARP/");
|
||||
}
|
||||
buf_printf(&out, "%s", print_in_addr_t(ntohl(maddr.v4.addr),
|
||||
(flags & MAPF_IA_EMPTY_IF_UNDEF) ? IA_EMPTY_IF_UNDEF : 0, gc));
|
||||
if (maddr.type & MR_WITH_NETBITS)
|
||||
{
|
||||
if (flags & MAPF_SUBNET)
|
||||
{
|
||||
const in_addr_t netmask = netbits_to_netmask(maddr.netbits);
|
||||
buf_printf(&out, "/%s", print_in_addr_t(netmask, 0, gc));
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_printf(&out, "/%d", maddr.netbits);
|
||||
}
|
||||
}
|
||||
if (maddr.type & MR_WITH_PORT)
|
||||
{
|
||||
buf_printf(&out, ":%d", ntohs(maddr.v4.port));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MR_ADDR_IPV6:
|
||||
{
|
||||
if (IN6_IS_ADDR_V4MAPPED( &maddr.v6.addr ) )
|
||||
{
|
||||
buf_printf(&out, "%s", print_in_addr_t(maddr.v4mappedv6.addr,
|
||||
IA_NET_ORDER, gc));
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_printf(&out, "%s", print_in6_addr(maddr.v6.addr, 0, gc));
|
||||
}
|
||||
if (maddr.type & MR_WITH_NETBITS)
|
||||
{
|
||||
buf_printf(&out, "/%d", maddr.netbits);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
buf_printf(&out, "UNKNOWN");
|
||||
break;
|
||||
}
|
||||
return BSTR(&out);
|
||||
}
|
||||
else
|
||||
return "[NULL]";
|
||||
}
|
||||
{
|
||||
return "[NULL]";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* mroute_helper's main job is keeping track of
|
||||
|
|
@ -456,74 +486,82 @@ mroute_addr_print_ex (const struct mroute_addr *ma,
|
|||
*/
|
||||
|
||||
struct mroute_helper *
|
||||
mroute_helper_init (int ageable_ttl_secs)
|
||||
mroute_helper_init(int ageable_ttl_secs)
|
||||
{
|
||||
struct mroute_helper *mh;
|
||||
ALLOC_OBJ_CLEAR (mh, struct mroute_helper);
|
||||
mh->ageable_ttl_secs = ageable_ttl_secs;
|
||||
return mh;
|
||||
struct mroute_helper *mh;
|
||||
ALLOC_OBJ_CLEAR(mh, struct mroute_helper);
|
||||
mh->ageable_ttl_secs = ageable_ttl_secs;
|
||||
return mh;
|
||||
}
|
||||
|
||||
static void
|
||||
mroute_helper_regenerate (struct mroute_helper *mh)
|
||||
mroute_helper_regenerate(struct mroute_helper *mh)
|
||||
{
|
||||
int i, j = 0;
|
||||
for (i = MR_HELPER_NET_LEN - 1; i >= 0; --i)
|
||||
int i, j = 0;
|
||||
for (i = MR_HELPER_NET_LEN - 1; i >= 0; --i)
|
||||
{
|
||||
if (mh->net_len_refcount[i] > 0)
|
||||
mh->net_len[j++] = (uint8_t) i;
|
||||
if (mh->net_len_refcount[i] > 0)
|
||||
{
|
||||
mh->net_len[j++] = (uint8_t) i;
|
||||
}
|
||||
}
|
||||
mh->n_net_len = j;
|
||||
mh->n_net_len = j;
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
if (check_debug_level (D_MULTI_DEBUG))
|
||||
if (check_debug_level(D_MULTI_DEBUG))
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct buffer out = alloc_buf_gc (256, &gc);
|
||||
buf_printf (&out, "MROUTE CIDR netlen:");
|
||||
for (i = 0; i < mh->n_net_len; ++i)
|
||||
{
|
||||
buf_printf (&out, " /%d", mh->net_len[i]);
|
||||
}
|
||||
dmsg (D_MULTI_DEBUG, "%s", BSTR (&out));
|
||||
gc_free (&gc);
|
||||
struct gc_arena gc = gc_new();
|
||||
struct buffer out = alloc_buf_gc(256, &gc);
|
||||
buf_printf(&out, "MROUTE CIDR netlen:");
|
||||
for (i = 0; i < mh->n_net_len; ++i)
|
||||
{
|
||||
buf_printf(&out, " /%d", mh->net_len[i]);
|
||||
}
|
||||
dmsg(D_MULTI_DEBUG, "%s", BSTR(&out));
|
||||
gc_free(&gc);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
mroute_helper_add_iroute46 (struct mroute_helper *mh, int netbits)
|
||||
mroute_helper_add_iroute46(struct mroute_helper *mh, int netbits)
|
||||
{
|
||||
if (netbits >= 0)
|
||||
if (netbits >= 0)
|
||||
{
|
||||
ASSERT (netbits < MR_HELPER_NET_LEN);
|
||||
++mh->cache_generation;
|
||||
++mh->net_len_refcount[netbits];
|
||||
if (mh->net_len_refcount[netbits] == 1)
|
||||
mroute_helper_regenerate (mh);
|
||||
ASSERT(netbits < MR_HELPER_NET_LEN);
|
||||
++mh->cache_generation;
|
||||
++mh->net_len_refcount[netbits];
|
||||
if (mh->net_len_refcount[netbits] == 1)
|
||||
{
|
||||
mroute_helper_regenerate(mh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mroute_helper_del_iroute46 (struct mroute_helper *mh, int netbits)
|
||||
mroute_helper_del_iroute46(struct mroute_helper *mh, int netbits)
|
||||
{
|
||||
if (netbits >= 0)
|
||||
if (netbits >= 0)
|
||||
{
|
||||
ASSERT (netbits < MR_HELPER_NET_LEN);
|
||||
++mh->cache_generation;
|
||||
--mh->net_len_refcount[netbits];
|
||||
ASSERT (mh->net_len_refcount[netbits] >= 0);
|
||||
if (!mh->net_len_refcount[netbits])
|
||||
mroute_helper_regenerate (mh);
|
||||
ASSERT(netbits < MR_HELPER_NET_LEN);
|
||||
++mh->cache_generation;
|
||||
--mh->net_len_refcount[netbits];
|
||||
ASSERT(mh->net_len_refcount[netbits] >= 0);
|
||||
if (!mh->net_len_refcount[netbits])
|
||||
{
|
||||
mroute_helper_regenerate(mh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mroute_helper_free (struct mroute_helper *mh)
|
||||
mroute_helper_free(struct mroute_helper *mh)
|
||||
{
|
||||
free (mh);
|
||||
free(mh);
|
||||
}
|
||||
|
||||
#else
|
||||
static void dummy(void) {}
|
||||
#else /* if P2MP_SERVER */
|
||||
static void
|
||||
dummy(void) {
|
||||
}
|
||||
#endif /* P2MP_SERVER */
|
||||
|
|
|
|||
|
|
@ -76,49 +76,49 @@
|
|||
#define MR_ARP 16
|
||||
|
||||
struct mroute_addr {
|
||||
uint8_t len; /* length of address */
|
||||
uint8_t unused;
|
||||
uint8_t type; /* MR_ADDR/MR_WITH flags */
|
||||
uint8_t netbits; /* number of bits in network part of address,
|
||||
valid if MR_WITH_NETBITS is set */
|
||||
union {
|
||||
uint8_t raw_addr[MR_MAX_ADDR_LEN]; /* actual address */
|
||||
uint8_t eth_addr[OPENVPN_ETH_ALEN];
|
||||
struct {
|
||||
in_addr_t addr; /* _network order_ IPv4 address */
|
||||
in_port_t port; /* _network order_ TCP/UDP port */
|
||||
} v4;
|
||||
struct {
|
||||
struct in6_addr addr;
|
||||
in_port_t port; /* _network order_ TCP/UDP port */
|
||||
} v6;
|
||||
struct {
|
||||
uint8_t prefix[12];
|
||||
in_addr_t addr; /* _network order_ IPv4 address */
|
||||
} v4mappedv6;
|
||||
}
|
||||
uint8_t len; /* length of address */
|
||||
uint8_t unused;
|
||||
uint8_t type; /* MR_ADDR/MR_WITH flags */
|
||||
uint8_t netbits; /* number of bits in network part of address,
|
||||
* valid if MR_WITH_NETBITS is set */
|
||||
union {
|
||||
uint8_t raw_addr[MR_MAX_ADDR_LEN]; /* actual address */
|
||||
uint8_t eth_addr[OPENVPN_ETH_ALEN];
|
||||
struct {
|
||||
in_addr_t addr; /* _network order_ IPv4 address */
|
||||
in_port_t port; /* _network order_ TCP/UDP port */
|
||||
} v4;
|
||||
struct {
|
||||
struct in6_addr addr;
|
||||
in_port_t port; /* _network order_ TCP/UDP port */
|
||||
} v6;
|
||||
struct {
|
||||
uint8_t prefix[12];
|
||||
in_addr_t addr; /* _network order_ IPv4 address */
|
||||
} v4mappedv6;
|
||||
}
|
||||
#ifndef HAVE_ANONYMOUS_UNION_SUPPORT
|
||||
/* Wrappers to support compilers that do not grok anonymous unions */
|
||||
mroute_union
|
||||
mroute_union
|
||||
#define raw_addr mroute_union.raw_addr
|
||||
#define eth_addr mroute_union.eth_addr
|
||||
#define v4 mroute_union.v4
|
||||
#define v6 mroute_union.v6
|
||||
#define v4mappedv6 mroute_union.v4mappedv6
|
||||
#endif
|
||||
;
|
||||
;
|
||||
};
|
||||
|
||||
/* Double-check that struct packing works as expected */
|
||||
static_assert (offsetof(struct mroute_addr, v4.port) ==
|
||||
offsetof(struct mroute_addr, v4) + 4,
|
||||
"Unexpected struct packing of v4");
|
||||
static_assert (offsetof(struct mroute_addr, v6.port) ==
|
||||
offsetof(struct mroute_addr, v6) + 16,
|
||||
"Unexpected struct packing of v6");
|
||||
static_assert (offsetof(struct mroute_addr, v4mappedv6.addr) ==
|
||||
offsetof(struct mroute_addr, v4mappedv6) + 12,
|
||||
"Unexpected struct packing of v4mappedv6");
|
||||
static_assert(offsetof(struct mroute_addr, v4.port) ==
|
||||
offsetof(struct mroute_addr, v4) + 4,
|
||||
"Unexpected struct packing of v4");
|
||||
static_assert(offsetof(struct mroute_addr, v6.port) ==
|
||||
offsetof(struct mroute_addr, v6) + 16,
|
||||
"Unexpected struct packing of v6");
|
||||
static_assert(offsetof(struct mroute_addr, v4mappedv6.addr) ==
|
||||
offsetof(struct mroute_addr, v4mappedv6) + 12,
|
||||
"Unexpected struct packing of v4mappedv6");
|
||||
|
||||
/*
|
||||
* Number of bits in an address. Should be raised for IPv6.
|
||||
|
|
@ -129,122 +129,140 @@ static_assert (offsetof(struct mroute_addr, v4mappedv6.addr) ==
|
|||
* Used to help maintain CIDR routing table.
|
||||
*/
|
||||
struct mroute_helper {
|
||||
unsigned int cache_generation; /* incremented when route added */
|
||||
int ageable_ttl_secs; /* host route cache entry time-to-live*/
|
||||
int n_net_len; /* length of net_len array */
|
||||
uint8_t net_len[MR_HELPER_NET_LEN]; /* CIDR netlengths in descending order */
|
||||
int net_len_refcount[MR_HELPER_NET_LEN]; /* refcount of each netlength */
|
||||
unsigned int cache_generation; /* incremented when route added */
|
||||
int ageable_ttl_secs; /* host route cache entry time-to-live*/
|
||||
int n_net_len; /* length of net_len array */
|
||||
uint8_t net_len[MR_HELPER_NET_LEN]; /* CIDR netlengths in descending order */
|
||||
int net_len_refcount[MR_HELPER_NET_LEN]; /* refcount of each netlength */
|
||||
};
|
||||
|
||||
struct openvpn_sockaddr;
|
||||
|
||||
bool mroute_extract_openvpn_sockaddr (struct mroute_addr *addr,
|
||||
const struct openvpn_sockaddr *osaddr,
|
||||
bool use_port);
|
||||
bool mroute_extract_openvpn_sockaddr(struct mroute_addr *addr,
|
||||
const struct openvpn_sockaddr *osaddr,
|
||||
bool use_port);
|
||||
|
||||
bool mroute_learnable_address (const struct mroute_addr *addr);
|
||||
bool mroute_learnable_address(const struct mroute_addr *addr);
|
||||
|
||||
uint32_t mroute_addr_hash_function (const void *key, uint32_t iv);
|
||||
bool mroute_addr_compare_function (const void *key1, const void *key2);
|
||||
uint32_t mroute_addr_hash_function(const void *key, uint32_t iv);
|
||||
|
||||
void mroute_addr_init (struct mroute_addr *addr);
|
||||
bool mroute_addr_compare_function(const void *key1, const void *key2);
|
||||
|
||||
const char *mroute_addr_print (const struct mroute_addr *ma,
|
||||
struct gc_arena *gc);
|
||||
void mroute_addr_init(struct mroute_addr *addr);
|
||||
|
||||
const char *mroute_addr_print(const struct mroute_addr *ma,
|
||||
struct gc_arena *gc);
|
||||
|
||||
#define MAPF_SUBNET (1<<0)
|
||||
#define MAPF_IA_EMPTY_IF_UNDEF (1<<1)
|
||||
#define MAPF_SHOW_ARP (1<<2)
|
||||
const char *mroute_addr_print_ex (const struct mroute_addr *ma,
|
||||
const unsigned int flags,
|
||||
struct gc_arena *gc);
|
||||
const char *mroute_addr_print_ex(const struct mroute_addr *ma,
|
||||
const unsigned int flags,
|
||||
struct gc_arena *gc);
|
||||
|
||||
void mroute_addr_mask_host_bits (struct mroute_addr *ma);
|
||||
void mroute_addr_mask_host_bits(struct mroute_addr *ma);
|
||||
|
||||
struct mroute_helper *mroute_helper_init (int ageable_ttl_secs);
|
||||
void mroute_helper_free (struct mroute_helper *mh);
|
||||
void mroute_helper_add_iroute46 (struct mroute_helper *mh, int netbits);
|
||||
void mroute_helper_del_iroute46 (struct mroute_helper *mh, int netbits);
|
||||
struct mroute_helper *mroute_helper_init(int ageable_ttl_secs);
|
||||
|
||||
void mroute_helper_free(struct mroute_helper *mh);
|
||||
|
||||
void mroute_helper_add_iroute46(struct mroute_helper *mh, int netbits);
|
||||
|
||||
void mroute_helper_del_iroute46(struct mroute_helper *mh, int netbits);
|
||||
|
||||
/*
|
||||
* Given a raw packet in buf, return the src and dest
|
||||
* addresses of the packet.
|
||||
*/
|
||||
static inline unsigned int
|
||||
mroute_extract_addr_from_packet (struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
struct mroute_addr *esrc,
|
||||
struct mroute_addr *edest,
|
||||
const struct buffer *buf,
|
||||
int tunnel_type)
|
||||
mroute_extract_addr_from_packet(struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
struct mroute_addr *esrc,
|
||||
struct mroute_addr *edest,
|
||||
const struct buffer *buf,
|
||||
int tunnel_type)
|
||||
{
|
||||
unsigned int mroute_extract_addr_ipv4 (struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
const struct buffer *buf);
|
||||
unsigned int mroute_extract_addr_ipv4(struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
const struct buffer *buf);
|
||||
|
||||
unsigned int mroute_extract_addr_ether (struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
struct mroute_addr *esrc,
|
||||
struct mroute_addr *edest,
|
||||
const struct buffer *buf);
|
||||
unsigned int ret = 0;
|
||||
verify_align_4 (buf);
|
||||
if (tunnel_type == DEV_TYPE_TUN)
|
||||
ret = mroute_extract_addr_ipv4 (src, dest, buf);
|
||||
else if (tunnel_type == DEV_TYPE_TAP)
|
||||
ret = mroute_extract_addr_ether (src, dest, esrc, edest, buf);
|
||||
return ret;
|
||||
unsigned int mroute_extract_addr_ether(struct mroute_addr *src,
|
||||
struct mroute_addr *dest,
|
||||
struct mroute_addr *esrc,
|
||||
struct mroute_addr *edest,
|
||||
const struct buffer *buf);
|
||||
|
||||
unsigned int ret = 0;
|
||||
verify_align_4(buf);
|
||||
if (tunnel_type == DEV_TYPE_TUN)
|
||||
{
|
||||
ret = mroute_extract_addr_ipv4(src, dest, buf);
|
||||
}
|
||||
else if (tunnel_type == DEV_TYPE_TAP)
|
||||
{
|
||||
ret = mroute_extract_addr_ether(src, dest, esrc, edest, buf);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
mroute_addr_equal (const struct mroute_addr *a1, const struct mroute_addr *a2)
|
||||
mroute_addr_equal(const struct mroute_addr *a1, const struct mroute_addr *a2)
|
||||
{
|
||||
if (a1->type != a2->type)
|
||||
return false;
|
||||
if (a1->netbits != a2->netbits)
|
||||
return false;
|
||||
if (a1->len != a2->len)
|
||||
return false;
|
||||
return memcmp (a1->raw_addr, a2->raw_addr, a1->len) == 0;
|
||||
if (a1->type != a2->type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (a1->netbits != a2->netbits)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (a1->len != a2->len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return memcmp(a1->raw_addr, a2->raw_addr, a1->len) == 0;
|
||||
}
|
||||
|
||||
static inline const uint8_t *
|
||||
mroute_addr_hash_ptr (const struct mroute_addr *a)
|
||||
mroute_addr_hash_ptr(const struct mroute_addr *a)
|
||||
{
|
||||
/* NOTE: depends on ordering of struct mroute_addr */
|
||||
return (uint8_t *) &a->type;
|
||||
/* NOTE: depends on ordering of struct mroute_addr */
|
||||
return (uint8_t *) &a->type;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
mroute_addr_hash_len (const struct mroute_addr *a)
|
||||
mroute_addr_hash_len(const struct mroute_addr *a)
|
||||
{
|
||||
return (uint32_t) a->len + 2;
|
||||
return (uint32_t) a->len + 2;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mroute_extract_in_addr_t (struct mroute_addr *dest, const in_addr_t src)
|
||||
mroute_extract_in_addr_t(struct mroute_addr *dest, const in_addr_t src)
|
||||
{
|
||||
dest->type = MR_ADDR_IPV4;
|
||||
dest->netbits = 0;
|
||||
dest->len = 4;
|
||||
dest->v4.addr = htonl (src);
|
||||
dest->type = MR_ADDR_IPV4;
|
||||
dest->netbits = 0;
|
||||
dest->len = 4;
|
||||
dest->v4.addr = htonl(src);
|
||||
}
|
||||
|
||||
static inline in_addr_t
|
||||
in_addr_t_from_mroute_addr (const struct mroute_addr *addr)
|
||||
in_addr_t_from_mroute_addr(const struct mroute_addr *addr)
|
||||
{
|
||||
if ((addr->type & MR_ADDR_MASK) == MR_ADDR_IPV4 && addr->netbits == 0 && addr->len == 4) {
|
||||
return ntohl(addr->v4.addr);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
if ((addr->type & MR_ADDR_MASK) == MR_ADDR_IPV4 && addr->netbits == 0 && addr->len == 4)
|
||||
{
|
||||
return ntohl(addr->v4.addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
mroute_addr_reset (struct mroute_addr *ma)
|
||||
mroute_addr_reset(struct mroute_addr *ma)
|
||||
{
|
||||
ma->len = 0;
|
||||
ma->type = MR_ADDR_NONE;
|
||||
ma->len = 0;
|
||||
ma->type = MR_ADDR_NONE;
|
||||
}
|
||||
|
||||
#endif /* P2MP_SERVER */
|
||||
|
|
|
|||
|
|
@ -44,33 +44,37 @@
|
|||
* if yes, hand to mss_fixup_dowork()
|
||||
*/
|
||||
void
|
||||
mss_fixup_ipv4 (struct buffer *buf, int maxmss)
|
||||
mss_fixup_ipv4(struct buffer *buf, int maxmss)
|
||||
{
|
||||
const struct openvpn_iphdr *pip;
|
||||
int hlen;
|
||||
const struct openvpn_iphdr *pip;
|
||||
int hlen;
|
||||
|
||||
if (BLEN (buf) < (int) sizeof (struct openvpn_iphdr))
|
||||
return;
|
||||
|
||||
verify_align_4 (buf);
|
||||
pip = (struct openvpn_iphdr *) BPTR (buf);
|
||||
|
||||
hlen = OPENVPN_IPH_GET_LEN (pip->version_len);
|
||||
|
||||
if (pip->protocol == OPENVPN_IPPROTO_TCP
|
||||
&& ntohs (pip->tot_len) == BLEN (buf)
|
||||
&& (ntohs (pip->frag_off) & OPENVPN_IP_OFFMASK) == 0
|
||||
&& hlen <= BLEN (buf)
|
||||
&& BLEN (buf) - hlen
|
||||
>= (int) sizeof (struct openvpn_tcphdr))
|
||||
if (BLEN(buf) < (int) sizeof(struct openvpn_iphdr))
|
||||
{
|
||||
struct buffer newbuf = *buf;
|
||||
if (buf_advance (&newbuf, hlen))
|
||||
{
|
||||
struct openvpn_tcphdr *tc = (struct openvpn_tcphdr *) BPTR (&newbuf);
|
||||
if (tc->flags & OPENVPN_TCPH_SYN_MASK)
|
||||
mss_fixup_dowork (&newbuf, (uint16_t) maxmss);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
verify_align_4(buf);
|
||||
pip = (struct openvpn_iphdr *) BPTR(buf);
|
||||
|
||||
hlen = OPENVPN_IPH_GET_LEN(pip->version_len);
|
||||
|
||||
if (pip->protocol == OPENVPN_IPPROTO_TCP
|
||||
&& ntohs(pip->tot_len) == BLEN(buf)
|
||||
&& (ntohs(pip->frag_off) & OPENVPN_IP_OFFMASK) == 0
|
||||
&& hlen <= BLEN(buf)
|
||||
&& BLEN(buf) - hlen
|
||||
>= (int) sizeof(struct openvpn_tcphdr))
|
||||
{
|
||||
struct buffer newbuf = *buf;
|
||||
if (buf_advance(&newbuf, hlen))
|
||||
{
|
||||
struct openvpn_tcphdr *tc = (struct openvpn_tcphdr *) BPTR(&newbuf);
|
||||
if (tc->flags & OPENVPN_TCPH_SYN_MASK)
|
||||
{
|
||||
mss_fixup_dowork(&newbuf, (uint16_t) maxmss);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,42 +84,50 @@ mss_fixup_ipv4 (struct buffer *buf, int maxmss)
|
|||
* (IPv6 header structure is sufficiently different from IPv4...)
|
||||
*/
|
||||
void
|
||||
mss_fixup_ipv6 (struct buffer *buf, int maxmss)
|
||||
mss_fixup_ipv6(struct buffer *buf, int maxmss)
|
||||
{
|
||||
const struct openvpn_ipv6hdr *pip6;
|
||||
struct buffer newbuf;
|
||||
const struct openvpn_ipv6hdr *pip6;
|
||||
struct buffer newbuf;
|
||||
|
||||
if (BLEN (buf) < (int) sizeof (struct openvpn_ipv6hdr))
|
||||
return;
|
||||
|
||||
verify_align_4 (buf);
|
||||
pip6 = (struct openvpn_ipv6hdr *) BPTR (buf);
|
||||
|
||||
/* do we have the full IPv6 packet?
|
||||
* "payload_len" does not include IPv6 header (+40 bytes)
|
||||
*/
|
||||
if (BLEN (buf) != (int) ntohs(pip6->payload_len)+40 )
|
||||
return;
|
||||
|
||||
/* follow header chain until we reach final header, then check for TCP
|
||||
*
|
||||
* An IPv6 packet could, theoretically, have a chain of multiple headers
|
||||
* before the final header (TCP, UDP, ...), so we'd need to walk that
|
||||
* chain (see RFC 2460 and RFC 6564 for details).
|
||||
*
|
||||
* In practice, "most typically used" extention headers (AH, routing,
|
||||
* fragment, mobility) are very unlikely to be seen inside an OpenVPN
|
||||
* tun, so for now, we only handle the case of "single next header = TCP"
|
||||
*/
|
||||
if ( pip6->nexthdr != OPENVPN_IPPROTO_TCP )
|
||||
return;
|
||||
|
||||
newbuf = *buf;
|
||||
if ( buf_advance( &newbuf, 40 ) )
|
||||
if (BLEN(buf) < (int) sizeof(struct openvpn_ipv6hdr))
|
||||
{
|
||||
struct openvpn_tcphdr *tc = (struct openvpn_tcphdr *) BPTR (&newbuf);
|
||||
if (tc->flags & OPENVPN_TCPH_SYN_MASK)
|
||||
mss_fixup_dowork (&newbuf, (uint16_t) maxmss-20);
|
||||
return;
|
||||
}
|
||||
|
||||
verify_align_4(buf);
|
||||
pip6 = (struct openvpn_ipv6hdr *) BPTR(buf);
|
||||
|
||||
/* do we have the full IPv6 packet?
|
||||
* "payload_len" does not include IPv6 header (+40 bytes)
|
||||
*/
|
||||
if (BLEN(buf) != (int) ntohs(pip6->payload_len)+40)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* follow header chain until we reach final header, then check for TCP
|
||||
*
|
||||
* An IPv6 packet could, theoretically, have a chain of multiple headers
|
||||
* before the final header (TCP, UDP, ...), so we'd need to walk that
|
||||
* chain (see RFC 2460 and RFC 6564 for details).
|
||||
*
|
||||
* In practice, "most typically used" extention headers (AH, routing,
|
||||
* fragment, mobility) are very unlikely to be seen inside an OpenVPN
|
||||
* tun, so for now, we only handle the case of "single next header = TCP"
|
||||
*/
|
||||
if (pip6->nexthdr != OPENVPN_IPPROTO_TCP)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
newbuf = *buf;
|
||||
if (buf_advance( &newbuf, 40 ) )
|
||||
{
|
||||
struct openvpn_tcphdr *tc = (struct openvpn_tcphdr *) BPTR(&newbuf);
|
||||
if (tc->flags & OPENVPN_TCPH_SYN_MASK)
|
||||
{
|
||||
mss_fixup_dowork(&newbuf, (uint16_t) maxmss-20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,50 +137,63 @@ mss_fixup_ipv6 (struct buffer *buf, int maxmss)
|
|||
*/
|
||||
|
||||
void
|
||||
mss_fixup_dowork (struct buffer *buf, uint16_t maxmss)
|
||||
mss_fixup_dowork(struct buffer *buf, uint16_t maxmss)
|
||||
{
|
||||
int hlen, olen, optlen;
|
||||
uint8_t *opt;
|
||||
uint16_t mssval;
|
||||
int accumulate;
|
||||
struct openvpn_tcphdr *tc;
|
||||
int hlen, olen, optlen;
|
||||
uint8_t *opt;
|
||||
uint16_t mssval;
|
||||
int accumulate;
|
||||
struct openvpn_tcphdr *tc;
|
||||
|
||||
ASSERT (BLEN (buf) >= (int) sizeof (struct openvpn_tcphdr));
|
||||
ASSERT(BLEN(buf) >= (int) sizeof(struct openvpn_tcphdr));
|
||||
|
||||
verify_align_4 (buf);
|
||||
tc = (struct openvpn_tcphdr *) BPTR (buf);
|
||||
hlen = OPENVPN_TCPH_GET_DOFF (tc->doff_res);
|
||||
verify_align_4(buf);
|
||||
tc = (struct openvpn_tcphdr *) BPTR(buf);
|
||||
hlen = OPENVPN_TCPH_GET_DOFF(tc->doff_res);
|
||||
|
||||
/* Invalid header length or header without options. */
|
||||
if (hlen <= (int) sizeof (struct openvpn_tcphdr)
|
||||
|| hlen > BLEN (buf))
|
||||
return;
|
||||
|
||||
for (olen = hlen - sizeof (struct openvpn_tcphdr),
|
||||
opt = (uint8_t *)(tc + 1);
|
||||
olen > 0;
|
||||
olen -= optlen, opt += optlen) {
|
||||
if (*opt == OPENVPN_TCPOPT_EOL)
|
||||
break;
|
||||
else if (*opt == OPENVPN_TCPOPT_NOP)
|
||||
optlen = 1;
|
||||
else {
|
||||
optlen = *(opt + 1);
|
||||
if (optlen <= 0 || optlen > olen)
|
||||
break;
|
||||
if (*opt == OPENVPN_TCPOPT_MAXSEG) {
|
||||
if (optlen != OPENVPN_TCPOLEN_MAXSEG)
|
||||
continue;
|
||||
mssval = (opt[2]<<8)+opt[3];
|
||||
if (mssval > maxmss) {
|
||||
dmsg (D_MSS, "MSS: %d -> %d", (int) mssval, (int) maxmss);
|
||||
accumulate = htons(mssval);
|
||||
opt[2] = (maxmss>>8)&0xff;
|
||||
opt[3] = maxmss&0xff;
|
||||
accumulate -= htons(maxmss);
|
||||
ADJUST_CHECKSUM (accumulate, tc->check);
|
||||
}
|
||||
}
|
||||
/* Invalid header length or header without options. */
|
||||
if (hlen <= (int) sizeof(struct openvpn_tcphdr)
|
||||
|| hlen > BLEN(buf))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (olen = hlen - sizeof(struct openvpn_tcphdr),
|
||||
opt = (uint8_t *)(tc + 1);
|
||||
olen > 0;
|
||||
olen -= optlen, opt += optlen) {
|
||||
if (*opt == OPENVPN_TCPOPT_EOL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (*opt == OPENVPN_TCPOPT_NOP)
|
||||
{
|
||||
optlen = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
optlen = *(opt + 1);
|
||||
if (optlen <= 0 || optlen > olen)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (*opt == OPENVPN_TCPOPT_MAXSEG)
|
||||
{
|
||||
if (optlen != OPENVPN_TCPOLEN_MAXSEG)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
mssval = (opt[2]<<8)+opt[3];
|
||||
if (mssval > maxmss)
|
||||
{
|
||||
dmsg(D_MSS, "MSS: %d -> %d", (int) mssval, (int) maxmss);
|
||||
accumulate = htons(mssval);
|
||||
opt[2] = (maxmss>>8)&0xff;
|
||||
opt[3] = maxmss&0xff;
|
||||
accumulate -= htons(maxmss);
|
||||
ADJUST_CHECKSUM(accumulate, tc->check);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,10 @@
|
|||
#include "proto.h"
|
||||
#include "error.h"
|
||||
|
||||
void mss_fixup_ipv4 (struct buffer *buf, int maxmss);
|
||||
void mss_fixup_ipv6 (struct buffer *buf, int maxmss);
|
||||
void mss_fixup_dowork (struct buffer *buf, uint16_t maxmss);
|
||||
void mss_fixup_ipv4(struct buffer *buf, int maxmss);
|
||||
|
||||
void mss_fixup_ipv6(struct buffer *buf, int maxmss);
|
||||
|
||||
void mss_fixup_dowork(struct buffer *buf, uint16_t maxmss);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,73 +50,79 @@ static char mmap_fn[128];
|
|||
void
|
||||
mstats_open(const char *fn)
|
||||
{
|
||||
void *data;
|
||||
ssize_t stat;
|
||||
int fd;
|
||||
struct mmap_stats ms;
|
||||
void *data;
|
||||
ssize_t stat;
|
||||
int fd;
|
||||
struct mmap_stats ms;
|
||||
|
||||
if (mmap_stats) /* already called? */
|
||||
return;
|
||||
|
||||
/* verify that filename is not too long */
|
||||
if (strlen(fn) >= sizeof(mmap_fn))
|
||||
msg (M_FATAL, "mstats_open: filename too long");
|
||||
|
||||
/* create file that will be memory mapped */
|
||||
fd = open (fn, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0)
|
||||
if (mmap_stats) /* already called? */
|
||||
{
|
||||
msg (M_ERR, "mstats_open: cannot open: %s", fn);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
/* set the file to the correct size to contain a
|
||||
struct mmap_stats, and zero it */
|
||||
CLEAR(ms);
|
||||
ms.state = MSTATS_ACTIVE;
|
||||
stat = write(fd, &ms, sizeof(ms));
|
||||
if (stat != sizeof(ms))
|
||||
/* verify that filename is not too long */
|
||||
if (strlen(fn) >= sizeof(mmap_fn))
|
||||
{
|
||||
msg (M_ERR, "mstats_open: write error: %s", fn);
|
||||
close(fd);
|
||||
return;
|
||||
msg(M_FATAL, "mstats_open: filename too long");
|
||||
}
|
||||
|
||||
/* mmap the file */
|
||||
data = mmap(NULL, sizeof(struct mmap_stats), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (data == MAP_FAILED)
|
||||
/* create file that will be memory mapped */
|
||||
fd = open(fn, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0)
|
||||
{
|
||||
msg (M_ERR, "mstats_open: write error: %s", fn);
|
||||
close(fd);
|
||||
return;
|
||||
msg(M_ERR, "mstats_open: cannot open: %s", fn);
|
||||
return;
|
||||
}
|
||||
|
||||
/* close the fd (mmap now controls the file) */
|
||||
if (close(fd))
|
||||
/* set the file to the correct size to contain a
|
||||
* struct mmap_stats, and zero it */
|
||||
CLEAR(ms);
|
||||
ms.state = MSTATS_ACTIVE;
|
||||
stat = write(fd, &ms, sizeof(ms));
|
||||
if (stat != sizeof(ms))
|
||||
{
|
||||
msg (M_ERR, "mstats_open: close error: %s", fn);
|
||||
msg(M_ERR, "mstats_open: write error: %s", fn);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* save filename so we can delete it later */
|
||||
strcpy(mmap_fn, fn);
|
||||
/* mmap the file */
|
||||
data = mmap(NULL, sizeof(struct mmap_stats), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (data == MAP_FAILED)
|
||||
{
|
||||
msg(M_ERR, "mstats_open: write error: %s", fn);
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
/* save a global pointer to memory-mapped region */
|
||||
mmap_stats = (struct mmap_stats *)data;
|
||||
/* close the fd (mmap now controls the file) */
|
||||
if (close(fd))
|
||||
{
|
||||
msg(M_ERR, "mstats_open: close error: %s", fn);
|
||||
}
|
||||
|
||||
msg (M_INFO, "memstats data will be written to %s", fn);
|
||||
/* save filename so we can delete it later */
|
||||
strcpy(mmap_fn, fn);
|
||||
|
||||
/* save a global pointer to memory-mapped region */
|
||||
mmap_stats = (struct mmap_stats *)data;
|
||||
|
||||
msg(M_INFO, "memstats data will be written to %s", fn);
|
||||
}
|
||||
|
||||
void
|
||||
mstats_close(void)
|
||||
{
|
||||
if (mmap_stats)
|
||||
if (mmap_stats)
|
||||
{
|
||||
mmap_stats->state = MSTATS_EXPIRED;
|
||||
if (munmap((void *)mmap_stats, sizeof(struct mmap_stats)))
|
||||
msg (M_WARN | M_ERRNO, "mstats_close: munmap error");
|
||||
platform_unlink(mmap_fn);
|
||||
mmap_stats = NULL;
|
||||
mmap_stats->state = MSTATS_EXPIRED;
|
||||
if (munmap((void *)mmap_stats, sizeof(struct mmap_stats)))
|
||||
{
|
||||
msg(M_WARN | M_ERRNO, "mstats_close: munmap error");
|
||||
}
|
||||
platform_unlink(mmap_fn);
|
||||
mmap_stats = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* if defined(ENABLE_MEMSTATS) */
|
||||
|
|
|
|||
|
|
@ -33,19 +33,20 @@
|
|||
|
||||
/* this struct is mapped to the file */
|
||||
struct mmap_stats {
|
||||
counter_type link_read_bytes; /* counter_type can be assumed to be a uint64_t */
|
||||
counter_type link_write_bytes;
|
||||
int n_clients;
|
||||
counter_type link_read_bytes; /* counter_type can be assumed to be a uint64_t */
|
||||
counter_type link_write_bytes;
|
||||
int n_clients;
|
||||
|
||||
# define MSTATS_UNDEF 0
|
||||
# define MSTATS_ACTIVE 1
|
||||
# define MSTATS_EXPIRED 2
|
||||
int state;
|
||||
#define MSTATS_UNDEF 0
|
||||
#define MSTATS_ACTIVE 1
|
||||
#define MSTATS_EXPIRED 2
|
||||
int state;
|
||||
};
|
||||
|
||||
extern volatile struct mmap_stats *mmap_stats; /* GLOBAL */
|
||||
|
||||
void mstats_open(const char *fn);
|
||||
|
||||
void mstats_close(void);
|
||||
|
||||
#endif
|
||||
#endif /* if !defined(OPENVPN_MEMSTATS_H) && defined(ENABLE_MEMSTATS) */
|
||||
|
|
|
|||
1117
src/openvpn/mtcp.c
1117
src/openvpn/mtcp.c
File diff suppressed because it is too large
Load diff
|
|
@ -38,27 +38,30 @@
|
|||
*/
|
||||
struct multi_tcp
|
||||
{
|
||||
struct event_set *es;
|
||||
struct event_set_return *esr;
|
||||
int n_esr;
|
||||
int maxevents;
|
||||
unsigned int tun_rwflags;
|
||||
struct event_set *es;
|
||||
struct event_set_return *esr;
|
||||
int n_esr;
|
||||
int maxevents;
|
||||
unsigned int tun_rwflags;
|
||||
#ifdef ENABLE_MANAGEMENT
|
||||
unsigned int management_persist_flags;
|
||||
unsigned int management_persist_flags;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct multi_instance;
|
||||
struct context;
|
||||
|
||||
struct multi_tcp *multi_tcp_init (int maxevents, int *maxclients);
|
||||
void multi_tcp_free (struct multi_tcp *mtcp);
|
||||
void multi_tcp_dereference_instance (struct multi_tcp *mtcp, struct multi_instance *mi);
|
||||
struct multi_tcp *multi_tcp_init(int maxevents, int *maxclients);
|
||||
|
||||
bool multi_tcp_instance_specific_init (struct multi_context *m, struct multi_instance *mi);
|
||||
void multi_tcp_instance_specific_free (struct multi_instance *mi);
|
||||
void multi_tcp_free(struct multi_tcp *mtcp);
|
||||
|
||||
void multi_tcp_link_out_deferred (struct multi_context *m, struct multi_instance *mi);
|
||||
void multi_tcp_dereference_instance(struct multi_tcp *mtcp, struct multi_instance *mi);
|
||||
|
||||
bool multi_tcp_instance_specific_init(struct multi_context *m, struct multi_instance *mi);
|
||||
|
||||
void multi_tcp_instance_specific_free(struct multi_instance *mi);
|
||||
|
||||
void multi_tcp_link_out_deferred(struct multi_context *m, struct multi_instance *mi);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
@ -68,10 +71,10 @@ void multi_tcp_link_out_deferred (struct multi_context *m, struct multi_instance
|
|||
*
|
||||
* @param top - Top-level context structure.
|
||||
*/
|
||||
void tunnel_server_tcp (struct context *top);
|
||||
void tunnel_server_tcp(struct context *top);
|
||||
|
||||
|
||||
void multi_tcp_delete_event (struct multi_tcp *mtcp, event_t event);
|
||||
void multi_tcp_delete_event(struct multi_tcp *mtcp, event_t event);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif /* if P2MP_SERVER */
|
||||
#endif /* ifndef MTCP_H */
|
||||
|
|
|
|||
|
|
@ -41,76 +41,78 @@
|
|||
|
||||
/* allocate a buffer for socket or tun layer */
|
||||
void
|
||||
alloc_buf_sock_tun (struct buffer *buf,
|
||||
const struct frame *frame,
|
||||
const bool tuntap_buffer,
|
||||
const unsigned int align_mask)
|
||||
alloc_buf_sock_tun(struct buffer *buf,
|
||||
const struct frame *frame,
|
||||
const bool tuntap_buffer,
|
||||
const unsigned int align_mask)
|
||||
{
|
||||
/* allocate buffer for overlapped I/O */
|
||||
*buf = alloc_buf (BUF_SIZE (frame));
|
||||
ASSERT (buf_init (buf, FRAME_HEADROOM_ADJ (frame, align_mask)));
|
||||
buf->len = tuntap_buffer ? MAX_RW_SIZE_TUN (frame) : MAX_RW_SIZE_LINK (frame);
|
||||
ASSERT (buf_safe (buf, 0));
|
||||
/* allocate buffer for overlapped I/O */
|
||||
*buf = alloc_buf(BUF_SIZE(frame));
|
||||
ASSERT(buf_init(buf, FRAME_HEADROOM_ADJ(frame, align_mask)));
|
||||
buf->len = tuntap_buffer ? MAX_RW_SIZE_TUN(frame) : MAX_RW_SIZE_LINK(frame);
|
||||
ASSERT(buf_safe(buf, 0));
|
||||
}
|
||||
|
||||
void
|
||||
frame_finalize (struct frame *frame,
|
||||
bool link_mtu_defined,
|
||||
int link_mtu,
|
||||
bool tun_mtu_defined,
|
||||
int tun_mtu)
|
||||
frame_finalize(struct frame *frame,
|
||||
bool link_mtu_defined,
|
||||
int link_mtu,
|
||||
bool tun_mtu_defined,
|
||||
int tun_mtu)
|
||||
{
|
||||
/* Set link_mtu based on command line options */
|
||||
if (tun_mtu_defined)
|
||||
/* Set link_mtu based on command line options */
|
||||
if (tun_mtu_defined)
|
||||
{
|
||||
ASSERT (!link_mtu_defined);
|
||||
frame->link_mtu = tun_mtu + TUN_LINK_DELTA (frame);
|
||||
ASSERT(!link_mtu_defined);
|
||||
frame->link_mtu = tun_mtu + TUN_LINK_DELTA(frame);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
ASSERT (link_mtu_defined);
|
||||
frame->link_mtu = link_mtu;
|
||||
ASSERT(link_mtu_defined);
|
||||
frame->link_mtu = link_mtu;
|
||||
}
|
||||
|
||||
if (TUN_MTU_SIZE (frame) < TUN_MTU_MIN)
|
||||
if (TUN_MTU_SIZE(frame) < TUN_MTU_MIN)
|
||||
{
|
||||
msg (M_WARN, "TUN MTU value (%d) must be at least %d", TUN_MTU_SIZE (frame), TUN_MTU_MIN);
|
||||
frame_print (frame, M_FATAL, "MTU is too small");
|
||||
msg(M_WARN, "TUN MTU value (%d) must be at least %d", TUN_MTU_SIZE(frame), TUN_MTU_MIN);
|
||||
frame_print(frame, M_FATAL, "MTU is too small");
|
||||
}
|
||||
|
||||
frame->link_mtu_dynamic = frame->link_mtu;
|
||||
frame->link_mtu_dynamic = frame->link_mtu;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the tun MTU dynamically.
|
||||
*/
|
||||
void
|
||||
frame_set_mtu_dynamic (struct frame *frame, int mtu, unsigned int flags)
|
||||
frame_set_mtu_dynamic(struct frame *frame, int mtu, unsigned int flags)
|
||||
{
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
const int orig_mtu = mtu;
|
||||
const int orig_link_mtu_dynamic = frame->link_mtu_dynamic;
|
||||
const int orig_mtu = mtu;
|
||||
const int orig_link_mtu_dynamic = frame->link_mtu_dynamic;
|
||||
#endif
|
||||
|
||||
ASSERT (mtu >= 0);
|
||||
ASSERT(mtu >= 0);
|
||||
|
||||
if (flags & SET_MTU_TUN)
|
||||
mtu += TUN_LINK_DELTA (frame);
|
||||
|
||||
if (!(flags & SET_MTU_UPPER_BOUND) || mtu < frame->link_mtu_dynamic)
|
||||
if (flags & SET_MTU_TUN)
|
||||
{
|
||||
frame->link_mtu_dynamic = constrain_int (
|
||||
mtu,
|
||||
EXPANDED_SIZE_MIN (frame),
|
||||
EXPANDED_SIZE (frame));
|
||||
mtu += TUN_LINK_DELTA(frame);
|
||||
}
|
||||
|
||||
dmsg (D_MTU_DEBUG, "MTU DYNAMIC mtu=%d, flags=%u, %d -> %d",
|
||||
orig_mtu,
|
||||
flags,
|
||||
orig_link_mtu_dynamic,
|
||||
frame->link_mtu_dynamic);
|
||||
if (!(flags & SET_MTU_UPPER_BOUND) || mtu < frame->link_mtu_dynamic)
|
||||
{
|
||||
frame->link_mtu_dynamic = constrain_int(
|
||||
mtu,
|
||||
EXPANDED_SIZE_MIN(frame),
|
||||
EXPANDED_SIZE(frame));
|
||||
}
|
||||
|
||||
dmsg(D_MTU_DEBUG, "MTU DYNAMIC mtu=%d, flags=%u, %d -> %d",
|
||||
orig_mtu,
|
||||
flags,
|
||||
orig_link_mtu_dynamic,
|
||||
frame->link_mtu_dynamic);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -119,200 +121,227 @@ frame_set_mtu_dynamic (struct frame *frame, int mtu, unsigned int flags)
|
|||
* queue.
|
||||
*/
|
||||
void
|
||||
frame_subtract_extra (struct frame *frame, const struct frame *src)
|
||||
frame_subtract_extra(struct frame *frame, const struct frame *src)
|
||||
{
|
||||
frame->extra_frame -= src->extra_frame;
|
||||
frame->extra_tun += src->extra_frame;
|
||||
frame->extra_frame -= src->extra_frame;
|
||||
frame->extra_tun += src->extra_frame;
|
||||
}
|
||||
|
||||
void
|
||||
frame_init_mssfix (struct frame *frame, const struct options *options)
|
||||
frame_init_mssfix(struct frame *frame, const struct options *options)
|
||||
{
|
||||
if (options->ce.mssfix)
|
||||
if (options->ce.mssfix)
|
||||
{
|
||||
frame_set_mtu_dynamic (frame, options->ce.mssfix, SET_MTU_UPPER_BOUND);
|
||||
frame_set_mtu_dynamic(frame, options->ce.mssfix, SET_MTU_UPPER_BOUND);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
frame_print (const struct frame *frame,
|
||||
int level,
|
||||
const char *prefix)
|
||||
frame_print(const struct frame *frame,
|
||||
int level,
|
||||
const char *prefix)
|
||||
{
|
||||
struct gc_arena gc = gc_new ();
|
||||
struct buffer out = alloc_buf_gc (256, &gc);
|
||||
if (prefix)
|
||||
buf_printf (&out, "%s ", prefix);
|
||||
buf_printf (&out, "[");
|
||||
buf_printf (&out, " L:%d", frame->link_mtu);
|
||||
buf_printf (&out, " D:%d", frame->link_mtu_dynamic);
|
||||
buf_printf (&out, " EF:%d", frame->extra_frame);
|
||||
buf_printf (&out, " EB:%d", frame->extra_buffer);
|
||||
buf_printf (&out, " ET:%d", frame->extra_tun);
|
||||
buf_printf (&out, " EL:%d", frame->extra_link);
|
||||
if (frame->align_flags && frame->align_adjust)
|
||||
buf_printf (&out, " AF:%u/%d", frame->align_flags, frame->align_adjust);
|
||||
buf_printf (&out, " ]");
|
||||
struct gc_arena gc = gc_new();
|
||||
struct buffer out = alloc_buf_gc(256, &gc);
|
||||
if (prefix)
|
||||
{
|
||||
buf_printf(&out, "%s ", prefix);
|
||||
}
|
||||
buf_printf(&out, "[");
|
||||
buf_printf(&out, " L:%d", frame->link_mtu);
|
||||
buf_printf(&out, " D:%d", frame->link_mtu_dynamic);
|
||||
buf_printf(&out, " EF:%d", frame->extra_frame);
|
||||
buf_printf(&out, " EB:%d", frame->extra_buffer);
|
||||
buf_printf(&out, " ET:%d", frame->extra_tun);
|
||||
buf_printf(&out, " EL:%d", frame->extra_link);
|
||||
if (frame->align_flags && frame->align_adjust)
|
||||
{
|
||||
buf_printf(&out, " AF:%u/%d", frame->align_flags, frame->align_adjust);
|
||||
}
|
||||
buf_printf(&out, " ]");
|
||||
|
||||
msg (level, "%s", out.data);
|
||||
gc_free (&gc);
|
||||
msg(level, "%s", out.data);
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
#define MTUDISC_NOT_SUPPORTED_MSG "--mtu-disc is not supported on this OS"
|
||||
|
||||
void
|
||||
set_mtu_discover_type (int sd, int mtu_type, sa_family_t proto_af)
|
||||
set_mtu_discover_type(int sd, int mtu_type, sa_family_t proto_af)
|
||||
{
|
||||
if (mtu_type >= 0)
|
||||
if (mtu_type >= 0)
|
||||
{
|
||||
switch (proto_af)
|
||||
{
|
||||
switch (proto_af)
|
||||
{
|
||||
#if defined(HAVE_SETSOCKOPT) && defined(IP_MTU_DISCOVER)
|
||||
case AF_INET:
|
||||
if (setsockopt
|
||||
(sd, IPPROTO_IP, IP_MTU_DISCOVER, &mtu_type, sizeof (mtu_type)))
|
||||
msg (M_ERR, "Error setting IP_MTU_DISCOVER type=%d on TCP/UDP socket",
|
||||
mtu_type);
|
||||
break;
|
||||
case AF_INET:
|
||||
if (setsockopt
|
||||
(sd, IPPROTO_IP, IP_MTU_DISCOVER, &mtu_type, sizeof(mtu_type)))
|
||||
{
|
||||
msg(M_ERR, "Error setting IP_MTU_DISCOVER type=%d on TCP/UDP socket",
|
||||
mtu_type);
|
||||
}
|
||||
break;
|
||||
|
||||
#endif
|
||||
#if defined(HAVE_SETSOCKOPT) && defined(IPV6_MTU_DISCOVER)
|
||||
case AF_INET6:
|
||||
if (setsockopt
|
||||
(sd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &mtu_type, sizeof (mtu_type)))
|
||||
msg (M_ERR, "Error setting IPV6_MTU_DISCOVER type=%d on TCP6/UDP6 socket",
|
||||
mtu_type);
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (setsockopt
|
||||
(sd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &mtu_type, sizeof(mtu_type)))
|
||||
{
|
||||
msg(M_ERR, "Error setting IPV6_MTU_DISCOVER type=%d on TCP6/UDP6 socket",
|
||||
mtu_type);
|
||||
}
|
||||
break;
|
||||
|
||||
#endif
|
||||
default:
|
||||
msg (M_FATAL, MTUDISC_NOT_SUPPORTED_MSG);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
msg(M_FATAL, MTUDISC_NOT_SUPPORTED_MSG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
translate_mtu_discover_type_name (const char *name)
|
||||
translate_mtu_discover_type_name(const char *name)
|
||||
{
|
||||
#if defined(IP_PMTUDISC_DONT) && defined(IP_PMTUDISC_WANT) && defined(IP_PMTUDISC_DO)
|
||||
if (!strcmp (name, "yes"))
|
||||
return IP_PMTUDISC_DO;
|
||||
if (!strcmp (name, "maybe"))
|
||||
return IP_PMTUDISC_WANT;
|
||||
if (!strcmp (name, "no"))
|
||||
return IP_PMTUDISC_DONT;
|
||||
msg (M_FATAL,
|
||||
"invalid --mtu-disc type: '%s' -- valid types are 'yes', 'maybe', or 'no'",
|
||||
name);
|
||||
#else
|
||||
msg (M_FATAL, MTUDISC_NOT_SUPPORTED_MSG);
|
||||
if (!strcmp(name, "yes"))
|
||||
{
|
||||
return IP_PMTUDISC_DO;
|
||||
}
|
||||
if (!strcmp(name, "maybe"))
|
||||
{
|
||||
return IP_PMTUDISC_WANT;
|
||||
}
|
||||
if (!strcmp(name, "no"))
|
||||
{
|
||||
return IP_PMTUDISC_DONT;
|
||||
}
|
||||
msg(M_FATAL,
|
||||
"invalid --mtu-disc type: '%s' -- valid types are 'yes', 'maybe', or 'no'",
|
||||
name);
|
||||
#else /* if defined(IP_PMTUDISC_DONT) && defined(IP_PMTUDISC_WANT) && defined(IP_PMTUDISC_DO) */
|
||||
msg(M_FATAL, MTUDISC_NOT_SUPPORTED_MSG);
|
||||
#endif
|
||||
return -1; /* NOTREACHED */
|
||||
return -1; /* NOTREACHED */
|
||||
}
|
||||
|
||||
#if EXTENDED_SOCKET_ERROR_CAPABILITY
|
||||
|
||||
struct probehdr
|
||||
{
|
||||
uint32_t ttl;
|
||||
struct timeval tv;
|
||||
uint32_t ttl;
|
||||
struct timeval tv;
|
||||
};
|
||||
|
||||
const char *
|
||||
format_extended_socket_error (int fd, int *mtu, struct gc_arena *gc)
|
||||
format_extended_socket_error(int fd, int *mtu, struct gc_arena *gc)
|
||||
{
|
||||
int res;
|
||||
struct probehdr rcvbuf;
|
||||
struct iovec iov;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct sock_extended_err *e;
|
||||
struct sockaddr_in addr;
|
||||
struct buffer out = alloc_buf_gc (256, gc);
|
||||
char *cbuf = (char *) gc_malloc (256, false, gc);
|
||||
int res;
|
||||
struct probehdr rcvbuf;
|
||||
struct iovec iov;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct sock_extended_err *e;
|
||||
struct sockaddr_in addr;
|
||||
struct buffer out = alloc_buf_gc(256, gc);
|
||||
char *cbuf = (char *) gc_malloc(256, false, gc);
|
||||
|
||||
*mtu = 0;
|
||||
*mtu = 0;
|
||||
|
||||
while (true)
|
||||
while (true)
|
||||
{
|
||||
memset (&rcvbuf, -1, sizeof (rcvbuf));
|
||||
iov.iov_base = &rcvbuf;
|
||||
iov.iov_len = sizeof (rcvbuf);
|
||||
msg.msg_name = (uint8_t *) &addr;
|
||||
msg.msg_namelen = sizeof (addr);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_control = cbuf;
|
||||
msg.msg_controllen = 256; /* size of cbuf */
|
||||
memset(&rcvbuf, -1, sizeof(rcvbuf));
|
||||
iov.iov_base = &rcvbuf;
|
||||
iov.iov_len = sizeof(rcvbuf);
|
||||
msg.msg_name = (uint8_t *) &addr;
|
||||
msg.msg_namelen = sizeof(addr);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_control = cbuf;
|
||||
msg.msg_controllen = 256; /* size of cbuf */
|
||||
|
||||
res = recvmsg (fd, &msg, MSG_ERRQUEUE);
|
||||
if (res < 0)
|
||||
goto exit;
|
||||
res = recvmsg(fd, &msg, MSG_ERRQUEUE);
|
||||
if (res < 0)
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
|
||||
e = NULL;
|
||||
e = NULL;
|
||||
|
||||
for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
|
||||
{
|
||||
if (cmsg->cmsg_level == SOL_IP)
|
||||
{
|
||||
if (cmsg->cmsg_type == IP_RECVERR)
|
||||
{
|
||||
e = (struct sock_extended_err *) CMSG_DATA (cmsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_printf (&out ,"CMSG=%d|", cmsg->cmsg_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (e == NULL)
|
||||
{
|
||||
buf_printf (&out, "NO-INFO|");
|
||||
goto exit;
|
||||
}
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
|
||||
{
|
||||
if (cmsg->cmsg_level == SOL_IP)
|
||||
{
|
||||
if (cmsg->cmsg_type == IP_RECVERR)
|
||||
{
|
||||
e = (struct sock_extended_err *) CMSG_DATA(cmsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf_printf(&out,"CMSG=%d|", cmsg->cmsg_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (e == NULL)
|
||||
{
|
||||
buf_printf(&out, "NO-INFO|");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (e->ee_errno)
|
||||
{
|
||||
case ETIMEDOUT:
|
||||
buf_printf (&out, "ETIMEDOUT|");
|
||||
break;
|
||||
case EMSGSIZE:
|
||||
buf_printf (&out, "EMSGSIZE Path-MTU=%d|", e->ee_info);
|
||||
*mtu = e->ee_info;
|
||||
break;
|
||||
case ECONNREFUSED:
|
||||
buf_printf (&out, "ECONNREFUSED|");
|
||||
break;
|
||||
case EPROTO:
|
||||
buf_printf (&out, "EPROTO|");
|
||||
break;
|
||||
case EHOSTUNREACH:
|
||||
buf_printf (&out, "EHOSTUNREACH|");
|
||||
break;
|
||||
case ENETUNREACH:
|
||||
buf_printf (&out, "ENETUNREACH|");
|
||||
break;
|
||||
case EACCES:
|
||||
buf_printf (&out, "EACCES|");
|
||||
break;
|
||||
default:
|
||||
buf_printf (&out, "UNKNOWN|");
|
||||
break;
|
||||
}
|
||||
switch (e->ee_errno)
|
||||
{
|
||||
case ETIMEDOUT:
|
||||
buf_printf(&out, "ETIMEDOUT|");
|
||||
break;
|
||||
|
||||
case EMSGSIZE:
|
||||
buf_printf(&out, "EMSGSIZE Path-MTU=%d|", e->ee_info);
|
||||
*mtu = e->ee_info;
|
||||
break;
|
||||
|
||||
case ECONNREFUSED:
|
||||
buf_printf(&out, "ECONNREFUSED|");
|
||||
break;
|
||||
|
||||
case EPROTO:
|
||||
buf_printf(&out, "EPROTO|");
|
||||
break;
|
||||
|
||||
case EHOSTUNREACH:
|
||||
buf_printf(&out, "EHOSTUNREACH|");
|
||||
break;
|
||||
|
||||
case ENETUNREACH:
|
||||
buf_printf(&out, "ENETUNREACH|");
|
||||
break;
|
||||
|
||||
case EACCES:
|
||||
buf_printf(&out, "EACCES|");
|
||||
break;
|
||||
|
||||
default:
|
||||
buf_printf(&out, "UNKNOWN|");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
buf_rmtail (&out, '|');
|
||||
return BSTR (&out);
|
||||
exit:
|
||||
buf_rmtail(&out, '|');
|
||||
return BSTR(&out);
|
||||
}
|
||||
|
||||
void
|
||||
set_sock_extended_error_passing (int sd)
|
||||
set_sock_extended_error_passing(int sd)
|
||||
{
|
||||
int on = 1;
|
||||
if (setsockopt (sd, SOL_IP, IP_RECVERR, (void *) &on, sizeof (on)))
|
||||
msg (M_WARN | M_ERRNO,
|
||||
"Note: enable extended error passing on TCP/UDP socket failed (IP_RECVERR)");
|
||||
int on = 1;
|
||||
if (setsockopt(sd, SOL_IP, IP_RECVERR, (void *) &on, sizeof(on)))
|
||||
{
|
||||
msg(M_WARN | M_ERRNO,
|
||||
"Note: enable extended error passing on TCP/UDP socket failed (IP_RECVERR)");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* if EXTENDED_SOCKET_ERROR_CAPABILITY */
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include "buffer.h"
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* Packet maninipulation routes such as encrypt, decrypt, compress, decompress
|
||||
* are passed a frame buffer that looks like this:
|
||||
*
|
||||
|
|
@ -92,20 +92,20 @@
|
|||
* Packet geometry parameters.
|
||||
*/
|
||||
struct frame {
|
||||
int link_mtu; /**< Maximum packet size to be sent over
|
||||
int link_mtu; /**< Maximum packet size to be sent over
|
||||
* the external network interface. */
|
||||
|
||||
int link_mtu_dynamic; /**< Dynamic MTU value for the external
|
||||
int link_mtu_dynamic; /**< Dynamic MTU value for the external
|
||||
* network interface. */
|
||||
|
||||
int extra_frame; /**< Maximum number of bytes that all
|
||||
int extra_frame; /**< Maximum number of bytes that all
|
||||
* processing steps together could add.
|
||||
* @code
|
||||
* frame.link_mtu = "socket MTU" - extra_frame;
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
int extra_buffer; /**< Maximum number of bytes that
|
||||
int extra_buffer; /**< Maximum number of bytes that
|
||||
* processing steps could expand the
|
||||
* internal work buffer.
|
||||
*
|
||||
|
|
@ -115,24 +115,24 @@ struct frame {
|
|||
* space for worst-case expansion of
|
||||
* incompressible content. */
|
||||
|
||||
int extra_tun; /**< Maximum number of bytes in excess of
|
||||
int extra_tun; /**< Maximum number of bytes in excess of
|
||||
* the tun/tap MTU that might be read
|
||||
* from or written to the virtual
|
||||
* tun/tap network interface. */
|
||||
|
||||
int extra_link; /**< Maximum number of bytes in excess of
|
||||
int extra_link; /**< Maximum number of bytes in excess of
|
||||
* external network interface's MTU that
|
||||
* might be read from or written to it. */
|
||||
|
||||
/*
|
||||
* Alignment control
|
||||
*/
|
||||
# define FRAME_HEADROOM_MARKER_DECRYPT (1<<0)
|
||||
# define FRAME_HEADROOM_MARKER_FRAGMENT (1<<1)
|
||||
# define FRAME_HEADROOM_MARKER_READ_LINK (1<<2)
|
||||
# define FRAME_HEADROOM_MARKER_READ_STREAM (1<<3)
|
||||
unsigned int align_flags;
|
||||
int align_adjust;
|
||||
/*
|
||||
* Alignment control
|
||||
*/
|
||||
#define FRAME_HEADROOM_MARKER_DECRYPT (1<<0)
|
||||
#define FRAME_HEADROOM_MARKER_FRAGMENT (1<<1)
|
||||
#define FRAME_HEADROOM_MARKER_READ_LINK (1<<2)
|
||||
#define FRAME_HEADROOM_MARKER_READ_STREAM (1<<3)
|
||||
unsigned int align_flags;
|
||||
int align_adjust;
|
||||
};
|
||||
|
||||
/* Forward declarations, to prevent includes */
|
||||
|
|
@ -198,20 +198,21 @@ struct options;
|
|||
* Function prototypes.
|
||||
*/
|
||||
|
||||
void frame_finalize (struct frame *frame,
|
||||
bool link_mtu_defined,
|
||||
int link_mtu,
|
||||
bool tun_mtu_defined,
|
||||
int tun_mtu);
|
||||
void frame_finalize(struct frame *frame,
|
||||
bool link_mtu_defined,
|
||||
int link_mtu,
|
||||
bool tun_mtu_defined,
|
||||
int tun_mtu);
|
||||
|
||||
void frame_subtract_extra (struct frame *frame, const struct frame *src);
|
||||
void frame_subtract_extra(struct frame *frame, const struct frame *src);
|
||||
|
||||
void frame_print (const struct frame *frame,
|
||||
int level,
|
||||
const char *prefix);
|
||||
void frame_print(const struct frame *frame,
|
||||
int level,
|
||||
const char *prefix);
|
||||
|
||||
void set_mtu_discover_type (int sd, int mtu_type, sa_family_t proto_af);
|
||||
int translate_mtu_discover_type_name (const char *name);
|
||||
void set_mtu_discover_type(int sd, int mtu_type, sa_family_t proto_af);
|
||||
|
||||
int translate_mtu_discover_type_name(const char *name);
|
||||
|
||||
/*
|
||||
* frame_set_mtu_dynamic and flags
|
||||
|
|
@ -220,18 +221,18 @@ int translate_mtu_discover_type_name (const char *name);
|
|||
#define SET_MTU_TUN (1<<0) /* use tun/tap rather than link sizing */
|
||||
#define SET_MTU_UPPER_BOUND (1<<1) /* only decrease dynamic MTU */
|
||||
|
||||
void frame_set_mtu_dynamic (struct frame *frame, int mtu, unsigned int flags);
|
||||
void frame_set_mtu_dynamic(struct frame *frame, int mtu, unsigned int flags);
|
||||
|
||||
/*
|
||||
* allocate a buffer for socket or tun layer
|
||||
*/
|
||||
void alloc_buf_sock_tun (struct buffer *buf,
|
||||
const struct frame *frame,
|
||||
const bool tuntap_buffer,
|
||||
const unsigned int align_mask);
|
||||
void alloc_buf_sock_tun(struct buffer *buf,
|
||||
const struct frame *frame,
|
||||
const bool tuntap_buffer,
|
||||
const unsigned int align_mask);
|
||||
|
||||
/** Set the --mssfix option. */
|
||||
void frame_init_mssfix (struct frame *frame, const struct options *options);
|
||||
void frame_init_mssfix(struct frame *frame, const struct options *options);
|
||||
|
||||
/*
|
||||
* EXTENDED_SOCKET_ERROR_CAPABILITY functions -- print extra error info
|
||||
|
|
@ -241,8 +242,9 @@ void frame_init_mssfix (struct frame *frame, const struct options *options);
|
|||
|
||||
#if EXTENDED_SOCKET_ERROR_CAPABILITY
|
||||
|
||||
void set_sock_extended_error_passing (int sd);
|
||||
const char *format_extended_socket_error (int fd, int *mtu, struct gc_arena *gc);
|
||||
void set_sock_extended_error_passing(int sd);
|
||||
|
||||
const char *format_extended_socket_error(int fd, int *mtu, struct gc_arena *gc);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -251,12 +253,12 @@ const char *format_extended_socket_error (int fd, int *mtu, struct gc_arena *gc)
|
|||
* headroom and alignment issues.
|
||||
*/
|
||||
static inline int
|
||||
frame_headroom (const struct frame *f, const unsigned int flag_mask)
|
||||
frame_headroom(const struct frame *f, const unsigned int flag_mask)
|
||||
{
|
||||
const int offset = FRAME_HEADROOM_BASE (f);
|
||||
const int adjust = (flag_mask & f->align_flags) ? f->align_adjust : 0;
|
||||
const int delta = ((PAYLOAD_ALIGN << 24) - (offset + adjust)) & (PAYLOAD_ALIGN - 1);
|
||||
return offset + delta;
|
||||
const int offset = FRAME_HEADROOM_BASE(f);
|
||||
const int adjust = (flag_mask & f->align_flags) ? f->align_adjust : 0;
|
||||
const int delta = ((PAYLOAD_ALIGN << 24) - (offset + adjust)) & (PAYLOAD_ALIGN - 1);
|
||||
return offset + delta;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -264,57 +266,57 @@ frame_headroom (const struct frame *f, const unsigned int flag_mask)
|
|||
*/
|
||||
|
||||
static inline void
|
||||
frame_add_to_link_mtu (struct frame *frame, const int increment)
|
||||
frame_add_to_link_mtu(struct frame *frame, const int increment)
|
||||
{
|
||||
frame->link_mtu += increment;
|
||||
frame->link_mtu += increment;
|
||||
}
|
||||
|
||||
static inline void
|
||||
frame_add_to_extra_frame (struct frame *frame, const int increment)
|
||||
frame_add_to_extra_frame(struct frame *frame, const int increment)
|
||||
{
|
||||
frame->extra_frame += increment;
|
||||
frame->extra_frame += increment;
|
||||
}
|
||||
|
||||
static inline void
|
||||
frame_add_to_extra_tun (struct frame *frame, const int increment)
|
||||
frame_add_to_extra_tun(struct frame *frame, const int increment)
|
||||
{
|
||||
frame->extra_tun += increment;
|
||||
frame->extra_tun += increment;
|
||||
}
|
||||
|
||||
static inline void
|
||||
frame_add_to_extra_link (struct frame *frame, const int increment)
|
||||
frame_add_to_extra_link(struct frame *frame, const int increment)
|
||||
{
|
||||
frame->extra_link += increment;
|
||||
frame->extra_link += increment;
|
||||
}
|
||||
|
||||
static inline void
|
||||
frame_add_to_extra_buffer (struct frame *frame, const int increment)
|
||||
frame_add_to_extra_buffer(struct frame *frame, const int increment)
|
||||
{
|
||||
frame->extra_buffer += increment;
|
||||
frame->extra_buffer += increment;
|
||||
}
|
||||
|
||||
static inline void
|
||||
frame_add_to_align_adjust (struct frame *frame, const int increment)
|
||||
frame_add_to_align_adjust(struct frame *frame, const int increment)
|
||||
{
|
||||
frame->align_adjust += increment;
|
||||
frame->align_adjust += increment;
|
||||
}
|
||||
|
||||
static inline void
|
||||
frame_align_to_extra_frame (struct frame *frame)
|
||||
frame_align_to_extra_frame(struct frame *frame)
|
||||
{
|
||||
frame->align_adjust = frame->extra_frame + frame->extra_link;
|
||||
frame->align_adjust = frame->extra_frame + frame->extra_link;
|
||||
}
|
||||
|
||||
static inline void
|
||||
frame_or_align_flags (struct frame *frame, const unsigned int flag_mask)
|
||||
frame_or_align_flags(struct frame *frame, const unsigned int flag_mask)
|
||||
{
|
||||
frame->align_flags |= flag_mask;
|
||||
frame->align_flags |= flag_mask;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
frame_defined (const struct frame *frame)
|
||||
frame_defined(const struct frame *frame)
|
||||
{
|
||||
return frame->link_mtu > 0;
|
||||
return frame->link_mtu > 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* ifndef MTU_H */
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue