mirror of
https://github.com/shadowsocks/shadowsocks-libev.git
synced 2026-10-22 06:53:46 +00:00
clean up
This commit is contained in:
+149
-76
@@ -109,11 +109,13 @@ static const CCAlgorithm supported_ciphers_applecc[CIPHER_NUM] =
|
||||
};
|
||||
|
||||
#ifdef USE_CRYPTO_POLARSSL
|
||||
static const int supported_ciphers_iv_size[CIPHER_NUM] = {
|
||||
static const int supported_ciphers_iv_size[CIPHER_NUM] =
|
||||
{
|
||||
0, 0, 16, 16, 16, 8, 16, 16, 16, 8, 8, 8, 8, 16
|
||||
};
|
||||
|
||||
static const int supported_ciphers_key_size[CIPHER_NUM] = {
|
||||
static const int supported_ciphers_key_size[CIPHER_NUM] =
|
||||
{
|
||||
0, 16, 16, 24, 32, 16, 16, 24, 32, 16, 8, 16, 16, 16
|
||||
};
|
||||
#endif
|
||||
@@ -211,7 +213,8 @@ unsigned char *enc_md5(const unsigned char *d, size_t n, unsigned char *md)
|
||||
return MD5(d, n, md);
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
static unsigned char m[16];
|
||||
if (md == NULL) {
|
||||
if (md == NULL)
|
||||
{
|
||||
md = m;
|
||||
}
|
||||
md5(d, n, md);
|
||||
@@ -257,7 +260,8 @@ int cipher_iv_size(const cipher_kt_t *cipher)
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
return EVP_CIPHER_iv_length (cipher);
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
if (cipher == NULL) {
|
||||
if (cipher == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return cipher->iv_size;
|
||||
@@ -269,11 +273,13 @@ int cipher_key_size (const cipher_kt_t *cipher)
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
return EVP_CIPHER_key_length(cipher);
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
if (cipher == NULL) {
|
||||
if (cipher == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* Override PolarSSL 32 bit default key size with sane 128 bit default */
|
||||
if (cipher->base != NULL && POLARSSL_CIPHER_ID_BLOWFISH == cipher->base->cipher) {
|
||||
if (cipher->base != NULL && POLARSSL_CIPHER_ID_BLOWFISH == cipher->base->cipher)
|
||||
{
|
||||
return 128 / 8;
|
||||
}
|
||||
return cipher->key_length / 8;
|
||||
@@ -299,28 +305,37 @@ int bytes_to_key(const cipher_kt_t *cipher, const digest_type_t *md, const uint8
|
||||
nkey = cipher_key_size(cipher);
|
||||
niv = cipher_iv_size(cipher);
|
||||
rv = nkey;
|
||||
if (pass == NULL) {
|
||||
if (pass == NULL)
|
||||
{
|
||||
return nkey;
|
||||
}
|
||||
|
||||
memset(&c, 0, sizeof(md_context_t));
|
||||
if (md_init_ctx(&c, md)) {
|
||||
if (md_init_ctx(&c, md))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
addmd = 0;
|
||||
mds = md_get_size(md);
|
||||
for (;;) {
|
||||
for (;;)
|
||||
{
|
||||
int error;
|
||||
do {
|
||||
do
|
||||
{
|
||||
error = 1;
|
||||
if (md_starts(&c)) {
|
||||
if (md_starts(&c))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (addmd) {
|
||||
if (md_update(&c, &(md_buf[0]), mds)) {
|
||||
if (addmd)
|
||||
{
|
||||
if (md_update(&c, &(md_buf[0]), mds))
|
||||
{
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
addmd = 1;
|
||||
}
|
||||
if (md_update(&c, pass, datal))
|
||||
@@ -328,16 +343,20 @@ int bytes_to_key(const cipher_kt_t *cipher, const digest_type_t *md, const uint8
|
||||
if (md_finish(&c, &(md_buf[0])))
|
||||
break;
|
||||
error = 0;
|
||||
} while (0);
|
||||
if (error) {
|
||||
}
|
||||
while (0);
|
||||
if (error)
|
||||
{
|
||||
md_free_ctx(&c);
|
||||
memset(md_buf, 0, MAX_MD_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i=0;
|
||||
if (nkey) {
|
||||
for (;;) {
|
||||
if (nkey)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (nkey == 0) break;
|
||||
if (i == mds) break;
|
||||
if (key != NULL)
|
||||
@@ -346,8 +365,10 @@ int bytes_to_key(const cipher_kt_t *cipher, const digest_type_t *md, const uint8
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (niv && (i != mds)) {
|
||||
for (;;) {
|
||||
if (niv && (i != mds))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (niv == 0) break;
|
||||
if (i == mds) break;
|
||||
if (iv != NULL)
|
||||
@@ -374,39 +395,49 @@ int rand_bytes(uint8_t *output, int len)
|
||||
static unsigned char rand_initialised = 0;
|
||||
const size_t blen = min(len, CTR_DRBG_MAX_REQUEST);
|
||||
|
||||
if (!rand_initialised) {
|
||||
if (!rand_initialised)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HCRYPTPROV hProvider;
|
||||
union {
|
||||
union
|
||||
{
|
||||
unsigned __int64 seed;
|
||||
BYTE buffer[8];
|
||||
} rand_buffer;
|
||||
|
||||
hProvider = 0;
|
||||
if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, \
|
||||
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
|
||||
CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
|
||||
{
|
||||
CryptGenRandom(hProvider, 8, rand_buffer.buffer);
|
||||
CryptReleaseContext(hProvider, 0);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
rand_buffer.seed = (unsigned __int64) clock();
|
||||
}
|
||||
#else
|
||||
FILE *urand;
|
||||
union {
|
||||
union
|
||||
{
|
||||
uint64_t seed;
|
||||
uint8_t buffer[8];
|
||||
} rand_buffer;
|
||||
|
||||
urand = fopen("/dev/urandom", "r");
|
||||
if (urand) {
|
||||
if (urand)
|
||||
{
|
||||
fread(&rand_buffer.seed, sizeof(rand_buffer.seed), 1, urand);
|
||||
fclose(urand);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
rand_buffer.seed = (uint64_t) clock();
|
||||
}
|
||||
#endif
|
||||
entropy_init(&ec);
|
||||
if (ctr_drbg_init(&cd_ctx, entropy_func, &ec, (const unsigned char *) rand_buffer.buffer, 8) != 0) {
|
||||
if (ctr_drbg_init(&cd_ctx, entropy_func, &ec, (const unsigned char *) rand_buffer.buffer, 8) != 0)
|
||||
{
|
||||
#if POLARSSL_VERSION_NUMBER >= 0x01030000
|
||||
entropy_free(&ec);
|
||||
#endif
|
||||
@@ -414,8 +445,10 @@ int rand_bytes(uint8_t *output, int len)
|
||||
}
|
||||
rand_initialised = 1;
|
||||
}
|
||||
while (len > 0) {
|
||||
if (ctr_drbg_random(&cd_ctx, output, blen) != 0) {
|
||||
while (len > 0)
|
||||
{
|
||||
if (ctr_drbg_random(&cd_ctx, output, blen) != 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
output += blen;
|
||||
@@ -427,7 +460,8 @@ int rand_bytes(uint8_t *output, int len)
|
||||
|
||||
const cipher_kt_t *get_cipher_type(int method)
|
||||
{
|
||||
if (method <= TABLE || method >= CIPHER_NUM) {
|
||||
if (method <= TABLE || method >= CIPHER_NUM)
|
||||
{
|
||||
LOGE("get_cipher_type(): Illegal method");
|
||||
return NULL;
|
||||
}
|
||||
@@ -437,7 +471,8 @@ const cipher_kt_t *get_cipher_type(int method)
|
||||
return EVP_get_cipherbyname(ciphername);
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
const char *polarname = supported_ciphers_polarssl[method];
|
||||
if (strcmp(polarname, CIPHER_UNSUPPORTED) == 0) {
|
||||
if (strcmp(polarname, CIPHER_UNSUPPORTED) == 0)
|
||||
{
|
||||
LOGE("Cipher %s currently is not supported by PolarSSL library", ciphername);
|
||||
return NULL;
|
||||
}
|
||||
@@ -447,7 +482,8 @@ const cipher_kt_t *get_cipher_type(int method)
|
||||
|
||||
const digest_type_t *get_digest_type(const char *digest)
|
||||
{
|
||||
if (digest == NULL) {
|
||||
if (digest == NULL)
|
||||
{
|
||||
LOGE("get_digest_type(): Digest name is null");
|
||||
return NULL;
|
||||
}
|
||||
@@ -461,7 +497,8 @@ const digest_type_t *get_digest_type(const char *digest)
|
||||
|
||||
void cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
|
||||
{
|
||||
if (method <= TABLE || method >= CIPHER_NUM) {
|
||||
if (method <= TABLE || method >= CIPHER_NUM)
|
||||
{
|
||||
LOGE("cipher_context_init(): Illegal method");
|
||||
return;
|
||||
}
|
||||
@@ -471,14 +508,20 @@ void cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
|
||||
cipher_cc_t *cc = &ctx->cc;
|
||||
cc->cryptor = NULL;
|
||||
cc->cipher = supported_ciphers_applecc[method];
|
||||
if (cc->cipher == kCCAlgorithmInvalid) {
|
||||
if (cc->cipher == kCCAlgorithmInvalid)
|
||||
{
|
||||
cc->valid = kCCContextInvalid;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
cc->valid = kCCContextValid;
|
||||
if (cc->cipher == kCCAlgorithmRC4) {
|
||||
if (cc->cipher == kCCAlgorithmRC4)
|
||||
{
|
||||
cc->mode = kCCModeRC4;
|
||||
cc->padding = ccNoPadding;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
cc->mode = kCCModeCFB;
|
||||
cc->padding = ccPKCS7Padding;
|
||||
}
|
||||
@@ -489,29 +532,35 @@ void cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
const cipher_kt_t *cipher = get_cipher_type(method);
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
if (cipher == NULL) {
|
||||
if (cipher == NULL)
|
||||
{
|
||||
LOGE("Cipher %s not found in OpenSSL library", ciphername);
|
||||
FATAL("Cannot initialize cipher");
|
||||
}
|
||||
EVP_CIPHER_CTX_init(evp);
|
||||
if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc)) {
|
||||
if (!EVP_CipherInit_ex(evp, cipher, NULL, NULL, NULL, enc))
|
||||
{
|
||||
LOGE("Cannot initialize cipher %s", ciphername);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!EVP_CIPHER_CTX_set_key_length(evp, enc_key_len)) {
|
||||
if (!EVP_CIPHER_CTX_set_key_length(evp, enc_key_len))
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup(evp);
|
||||
LOGE("Invalid key length: %d", enc_key_len);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (method > RC4) {
|
||||
if (method > RC4)
|
||||
{
|
||||
EVP_CIPHER_CTX_set_padding(evp, 1);
|
||||
}
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
if (cipher == NULL) {
|
||||
if (cipher == NULL)
|
||||
{
|
||||
LOGE("Cipher %s not found in PolarSSL library", ciphername);
|
||||
FATAL("Cannot initialize PolarSSL cipher");
|
||||
}
|
||||
if (cipher_init_ctx(evp, cipher) != 0) {
|
||||
if (cipher_init_ctx(evp, cipher) != 0)
|
||||
{
|
||||
FATAL("Cannot initialize PolarSSL cipher context");
|
||||
}
|
||||
#endif
|
||||
@@ -519,38 +568,44 @@ void cipher_context_init(cipher_ctx_t *ctx, int method, int enc)
|
||||
|
||||
void cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len, int enc)
|
||||
{
|
||||
if (iv == NULL) {
|
||||
if (iv == NULL)
|
||||
{
|
||||
LOGE("cipher_context_set_iv(): IV is null");
|
||||
return;
|
||||
}
|
||||
if (enc) {
|
||||
if (enc)
|
||||
{
|
||||
rand_bytes(iv, iv_len);
|
||||
}
|
||||
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t *cc = &ctx->cc;
|
||||
if (cc->valid == kCCContextValid) {
|
||||
if (cc->valid == kCCContextValid)
|
||||
{
|
||||
memcpy(cc->iv, iv, iv_len);
|
||||
memcpy(cc->key, enc_key, enc_key_len);
|
||||
cc->iv_len = iv_len;
|
||||
cc->key_len = enc_key_len;
|
||||
cc->encrypt = enc ? kCCEncrypt : kCCDecrypt;
|
||||
if (cc->cryptor != NULL) {
|
||||
if (cc->cryptor != NULL)
|
||||
{
|
||||
CCCryptorRelease(cc->cryptor);
|
||||
cc->cryptor = NULL;
|
||||
}
|
||||
|
||||
CCCryptorStatus ret;
|
||||
ret = CCCryptorCreateWithMode(
|
||||
cc->encrypt,
|
||||
cc->mode,
|
||||
cc->cipher,
|
||||
cc->padding,
|
||||
cc->iv, cc->key, cc->key_len,
|
||||
NULL, 0, 0, 0,
|
||||
&cc->cryptor);
|
||||
if (ret != kCCSuccess) {
|
||||
if (cc->cryptor != NULL) {
|
||||
cc->encrypt,
|
||||
cc->mode,
|
||||
cc->cipher,
|
||||
cc->padding,
|
||||
cc->iv, cc->key, cc->key_len,
|
||||
NULL, 0, 0, 0,
|
||||
&cc->cryptor);
|
||||
if (ret != kCCSuccess)
|
||||
{
|
||||
if (cc->cryptor != NULL)
|
||||
{
|
||||
CCCryptorRelease(cc->cryptor);
|
||||
cc->cryptor = NULL;
|
||||
}
|
||||
@@ -561,31 +616,37 @@ void cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len, int en
|
||||
#endif
|
||||
|
||||
cipher_evp_t *evp = &ctx->evp;
|
||||
if (evp == NULL) {
|
||||
if (evp == NULL)
|
||||
{
|
||||
LOGE("cipher_context_set_iv(): Cipher context is null");
|
||||
return;
|
||||
}
|
||||
#if defined(USE_CRYPTO_OPENSSL)
|
||||
if (!EVP_CipherInit_ex(evp, NULL, NULL, enc_key, iv, enc)) {
|
||||
if (!EVP_CipherInit_ex(evp, NULL, NULL, enc_key, iv, enc))
|
||||
{
|
||||
EVP_CIPHER_CTX_cleanup(evp);
|
||||
FATAL("Cannot set key and IV");
|
||||
}
|
||||
#elif defined(USE_CRYPTO_POLARSSL)
|
||||
if (cipher_setkey(evp, enc_key, enc_key_len * 8, enc) != 0) {
|
||||
if (cipher_setkey(evp, enc_key, enc_key_len * 8, enc) != 0)
|
||||
{
|
||||
cipher_free_ctx(evp);
|
||||
FATAL("Cannot set PolarSSL cipher key");
|
||||
}
|
||||
#if POLARSSL_VERSION_NUMBER >= 0x01030000
|
||||
if (cipher_set_iv(evp, iv, iv_len) != 0) {
|
||||
if (cipher_set_iv(evp, iv, iv_len) != 0)
|
||||
{
|
||||
cipher_free_ctx(evp);
|
||||
FATAL("Cannot set PolarSSL cipher IV");
|
||||
}
|
||||
if(cipher_reset(evp) != 0) {
|
||||
if(cipher_reset(evp) != 0)
|
||||
{
|
||||
cipher_free_ctx(evp);
|
||||
FATAL("Cannot finalize PolarSSL cipher context");
|
||||
}
|
||||
#else
|
||||
if(cipher_reset(evp, iv) != 0) {
|
||||
if(cipher_reset(evp, iv) != 0)
|
||||
{
|
||||
cipher_free_ctx(evp);
|
||||
FATAL("Cannot set PolarSSL cipher IV");
|
||||
}
|
||||
@@ -597,14 +658,17 @@ void cipher_context_set_iv(cipher_ctx_t *ctx, uint8_t *iv, size_t iv_len, int en
|
||||
#endif
|
||||
}
|
||||
|
||||
void cipher_context_release(cipher_ctx_t *ctx) {
|
||||
void cipher_context_release(cipher_ctx_t *ctx)
|
||||
{
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t *cc = &ctx->cc;
|
||||
if (cc->cryptor != NULL) {
|
||||
if (cc->cryptor != NULL)
|
||||
{
|
||||
CCCryptorRelease(cc->cryptor);
|
||||
cc->cryptor = NULL;
|
||||
}
|
||||
if (cc->valid == kCCContextValid) {
|
||||
if (cc->valid == kCCContextValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -618,10 +682,12 @@ void cipher_context_release(cipher_ctx_t *ctx) {
|
||||
}
|
||||
|
||||
static int cipher_context_update(cipher_ctx_t *ctx, uint8_t *output, int *olen,
|
||||
const uint8_t *input, int ilen) {
|
||||
const uint8_t *input, int ilen)
|
||||
{
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t *cc = &ctx->cc;
|
||||
if (cc->valid == kCCContextValid) {
|
||||
if (cc->valid == kCCContextValid)
|
||||
{
|
||||
CCCryptorStatus ret;
|
||||
ret = CCCryptorUpdate(cc->cryptor, input, ilen, output, ilen + BLOCK_SIZE, (size_t *) olen);
|
||||
return (ret == kCCSuccess) ? 1 : 0;
|
||||
@@ -841,7 +907,8 @@ void enc_ctx_init(int method, struct enc_ctx *ctx, int enc)
|
||||
|
||||
void enc_key_init(int method, const char *pass)
|
||||
{
|
||||
if (method <= TABLE || method >= CIPHER_NUM) {
|
||||
if (method <= TABLE || method >= CIPHER_NUM)
|
||||
{
|
||||
LOGE("enc_key_init(): Illegal method");
|
||||
return;
|
||||
}
|
||||
@@ -856,10 +923,13 @@ void enc_key_init(int method, const char *pass)
|
||||
|
||||
uint8_t iv[MAX_IV_LENGTH];
|
||||
const cipher_kt_t *cipher = get_cipher_type(method);
|
||||
if (cipher == NULL) {
|
||||
do {
|
||||
if (cipher == NULL)
|
||||
{
|
||||
do
|
||||
{
|
||||
#if defined(USE_CRYPTO_POLARSSL) && defined(USE_CRYPTO_APPLECC)
|
||||
if (supported_ciphers_applecc[method] != kCCAlgorithmInvalid) {
|
||||
if (supported_ciphers_applecc[method] != kCCAlgorithmInvalid)
|
||||
{
|
||||
cipher_info.base = NULL;
|
||||
cipher_info.key_length = supported_ciphers_key_size[method] * 8;
|
||||
cipher_info.iv_size = supported_ciphers_iv_size[method];
|
||||
@@ -869,15 +939,18 @@ void enc_key_init(int method, const char *pass)
|
||||
#endif
|
||||
LOGE("Cipher %s not found in crypto library", supported_ciphers[method]);
|
||||
FATAL("Cannot initialize cipher");
|
||||
} while (0);
|
||||
}
|
||||
while (0);
|
||||
}
|
||||
const digest_type_t *md = get_digest_type("MD5");
|
||||
if (md == NULL) {
|
||||
if (md == NULL)
|
||||
{
|
||||
FATAL("MD5 Digest not found in crypto library");
|
||||
}
|
||||
|
||||
enc_key_len = bytes_to_key(cipher, md, (const uint8_t *) pass, enc_key, iv);
|
||||
if (enc_key_len == 0) {
|
||||
if (enc_key_len == 0)
|
||||
{
|
||||
FATAL("Cannot generate key and IV");
|
||||
}
|
||||
enc_iv_len = cipher_iv_size(cipher);
|
||||
|
||||
+4
-2
@@ -52,7 +52,8 @@ typedef md_info_t digest_type_t;
|
||||
#define kCCContextValid 0
|
||||
#define kCCContextInvalid -1
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
CCCryptorRef cryptor;
|
||||
int valid;
|
||||
CCOperation encrypt;
|
||||
@@ -67,7 +68,8 @@ typedef struct {
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
cipher_evp_t evp;
|
||||
#ifdef USE_CRYPTO_APPLECC
|
||||
cipher_cc_t cc;
|
||||
|
||||
+4
-4
@@ -3,14 +3,14 @@
|
||||
|
||||
int udprelay_init(const char *server_host, const char *server_port,
|
||||
#ifdef UDPRELAY_LOCAL
|
||||
const char *remote_host, const char *remote_port,
|
||||
const char *remote_host, const char *remote_port,
|
||||
#ifdef UDPRELAY_TUNNEL
|
||||
const ss_addr_t tunnel_addr,
|
||||
const ss_addr_t tunnel_addr,
|
||||
#endif
|
||||
#endif
|
||||
#ifdef UDPRELAY_REMOTE
|
||||
asyncns_t *asyncns,
|
||||
asyncns_t *asyncns,
|
||||
#endif
|
||||
int method, int timeout, const char *iface);
|
||||
int method, int timeout, const char *iface);
|
||||
|
||||
#endif // _INCLUDE_H
|
||||
|
||||
+2
-1
@@ -54,7 +54,8 @@ void parse_addr(const char *str, ss_addr_t *addr)
|
||||
ret = pch - str;
|
||||
pch = strchr(pch + 1, ':');
|
||||
}
|
||||
if (n > 1) {
|
||||
if (n > 1)
|
||||
{
|
||||
if (strcmp(str+ret, "]") != 0)
|
||||
{
|
||||
ret = -1;
|
||||
|
||||
+660
-621
File diff suppressed because it is too large
Load Diff
+157
-152
@@ -32,41 +32,41 @@
|
||||
#define _JSON_H
|
||||
|
||||
#ifndef json_char
|
||||
#define json_char char
|
||||
#define json_char char
|
||||
#endif
|
||||
|
||||
#ifndef json_int_t
|
||||
#ifndef _MSC_VER
|
||||
#include <inttypes.h>
|
||||
#define json_int_t int64_t
|
||||
#else
|
||||
#define json_int_t __int64
|
||||
#endif
|
||||
#ifndef _MSC_VER
|
||||
#include <inttypes.h>
|
||||
#define json_int_t int64_t
|
||||
#else
|
||||
#define json_int_t __int64
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <string.h>
|
||||
#include <string.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long max_memory;
|
||||
int settings;
|
||||
unsigned long max_memory;
|
||||
int settings;
|
||||
|
||||
/* Custom allocator support (leave null to use malloc/free)
|
||||
*/
|
||||
/* Custom allocator support (leave null to use malloc/free)
|
||||
*/
|
||||
|
||||
void * (* mem_alloc) (size_t, int zero, void * user_data);
|
||||
void (* mem_free) (void *, void * user_data);
|
||||
void * (* mem_alloc) (size_t, int zero, void * user_data);
|
||||
void (* mem_free) (void *, void * user_data);
|
||||
|
||||
void * user_data; /* will be passed to mem_alloc and mem_free */
|
||||
void * user_data; /* will be passed to mem_alloc and mem_free */
|
||||
|
||||
} json_settings;
|
||||
|
||||
@@ -74,14 +74,14 @@ typedef struct
|
||||
|
||||
typedef enum
|
||||
{
|
||||
json_none,
|
||||
json_object,
|
||||
json_array,
|
||||
json_integer,
|
||||
json_double,
|
||||
json_string,
|
||||
json_boolean,
|
||||
json_null
|
||||
json_none,
|
||||
json_object,
|
||||
json_array,
|
||||
json_integer,
|
||||
json_double,
|
||||
json_string,
|
||||
json_boolean,
|
||||
json_null
|
||||
|
||||
} json_type;
|
||||
|
||||
@@ -89,181 +89,186 @@ extern const struct _json_value json_value_none;
|
||||
|
||||
typedef struct _json_value
|
||||
{
|
||||
struct _json_value * parent;
|
||||
struct _json_value * parent;
|
||||
|
||||
json_type type;
|
||||
json_type type;
|
||||
|
||||
union
|
||||
{
|
||||
int boolean;
|
||||
json_int_t integer;
|
||||
double dbl;
|
||||
union
|
||||
{
|
||||
int boolean;
|
||||
json_int_t integer;
|
||||
double dbl;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
json_char * ptr; /* null terminated */
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
json_char * ptr; /* null terminated */
|
||||
|
||||
} string;
|
||||
} string;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
|
||||
struct
|
||||
{
|
||||
json_char * name;
|
||||
unsigned int name_length;
|
||||
|
||||
struct _json_value * value;
|
||||
|
||||
} * values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin () const
|
||||
{ return values;
|
||||
}
|
||||
decltype(values) end () const
|
||||
{ return values + length;
|
||||
}
|
||||
#endif
|
||||
|
||||
} object;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
struct _json_value ** values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin () const
|
||||
{ return values;
|
||||
}
|
||||
decltype(values) end () const
|
||||
{ return values + length;
|
||||
}
|
||||
#endif
|
||||
|
||||
} array;
|
||||
|
||||
} u;
|
||||
|
||||
union
|
||||
{
|
||||
struct _json_value * next_alloc;
|
||||
void * object_mem;
|
||||
|
||||
} _reserved;
|
||||
|
||||
|
||||
/* Some C++ operator sugar */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
public:
|
||||
|
||||
inline _json_value ()
|
||||
{ memset (this, 0, sizeof (_json_value));
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (int index) const
|
||||
{
|
||||
if (type != json_array || index < 0
|
||||
|| ((unsigned int) index) >= u.array.length)
|
||||
struct
|
||||
{
|
||||
return json_value_none;
|
||||
json_char * name;
|
||||
unsigned int name_length;
|
||||
|
||||
struct _json_value * value;
|
||||
|
||||
} * values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin () const
|
||||
{
|
||||
return values;
|
||||
}
|
||||
decltype(values) end () const
|
||||
{
|
||||
return values + length;
|
||||
}
|
||||
#endif
|
||||
|
||||
} object;
|
||||
|
||||
struct
|
||||
{
|
||||
unsigned int length;
|
||||
struct _json_value ** values;
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201103L
|
||||
decltype(values) begin () const
|
||||
{
|
||||
return values;
|
||||
}
|
||||
decltype(values) end () const
|
||||
{
|
||||
return values + length;
|
||||
}
|
||||
#endif
|
||||
|
||||
} array;
|
||||
|
||||
} u;
|
||||
|
||||
union
|
||||
{
|
||||
struct _json_value * next_alloc;
|
||||
void * object_mem;
|
||||
|
||||
} _reserved;
|
||||
|
||||
|
||||
/* Some C++ operator sugar */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
public:
|
||||
|
||||
inline _json_value ()
|
||||
{
|
||||
memset (this, 0, sizeof (_json_value));
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (int index) const
|
||||
{
|
||||
if (type != json_array || index < 0
|
||||
|| ((unsigned int) index) >= u.array.length)
|
||||
{
|
||||
return json_value_none;
|
||||
}
|
||||
|
||||
return *u.array.values [index];
|
||||
}
|
||||
}
|
||||
|
||||
inline const struct _json_value &operator [] (const char * index) const
|
||||
{
|
||||
inline const struct _json_value &operator [] (const char * index) const
|
||||
{
|
||||
if (type != json_object)
|
||||
return json_value_none;
|
||||
return json_value_none;
|
||||
|
||||
for (unsigned int i = 0; i < u.object.length; ++ i)
|
||||
if (!strcmp (u.object.values [i].name, index))
|
||||
return *u.object.values [i].value;
|
||||
if (!strcmp (u.object.values [i].name, index))
|
||||
return *u.object.values [i].value;
|
||||
|
||||
return json_value_none;
|
||||
}
|
||||
}
|
||||
|
||||
inline operator const char * () const
|
||||
{
|
||||
inline operator const char * () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_string:
|
||||
return u.string.ptr;
|
||||
case json_string:
|
||||
return u.string.ptr;
|
||||
|
||||
default:
|
||||
return "";
|
||||
default:
|
||||
return "";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
inline operator json_int_t () const
|
||||
{
|
||||
inline operator json_int_t () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_integer:
|
||||
return u.integer;
|
||||
case json_integer:
|
||||
return u.integer;
|
||||
|
||||
case json_double:
|
||||
return (json_int_t) u.dbl;
|
||||
case json_double:
|
||||
return (json_int_t) u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
inline operator bool () const
|
||||
{
|
||||
inline operator bool () const
|
||||
{
|
||||
if (type != json_boolean)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
return u.boolean != 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline operator double () const
|
||||
{
|
||||
inline operator double () const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case json_integer:
|
||||
return (double) u.integer;
|
||||
case json_integer:
|
||||
return (double) u.integer;
|
||||
|
||||
case json_double:
|
||||
return u.dbl;
|
||||
case json_double:
|
||||
return u.dbl;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} json_value;
|
||||
} json_value;
|
||||
|
||||
json_value * json_parse (const json_char * json,
|
||||
size_t length);
|
||||
json_value * json_parse (const json_char * json,
|
||||
size_t length);
|
||||
|
||||
#define json_error_max 128
|
||||
json_value * json_parse_ex (json_settings * settings,
|
||||
const json_char * json,
|
||||
size_t length,
|
||||
char * error);
|
||||
json_value * json_parse_ex (json_settings * settings,
|
||||
const json_char * json,
|
||||
size_t length,
|
||||
char * error);
|
||||
|
||||
void json_value_free (json_value *);
|
||||
void json_value_free (json_value *);
|
||||
|
||||
|
||||
/* Not usually necessary, unless you used a custom mem_alloc and now want to
|
||||
* use a custom mem_free.
|
||||
*/
|
||||
void json_value_free_ex (json_settings * settings,
|
||||
json_value *);
|
||||
/* Not usually necessary, unless you used a custom mem_alloc and now want to
|
||||
* use a custom mem_free.
|
||||
*/
|
||||
void json_value_free_ex (json_settings * settings,
|
||||
json_value *);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+2
-1
@@ -361,7 +361,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
|
||||
return;
|
||||
}
|
||||
|
||||
if (request->cmd == 3) {
|
||||
if (request->cmd == 3)
|
||||
{
|
||||
close_and_free_remote(EV_A_ remote);
|
||||
close_and_free_server(EV_A_ server);
|
||||
return;
|
||||
|
||||
+1
-1
@@ -874,7 +874,7 @@ int main (int argc, char **argv)
|
||||
{
|
||||
LOGD("udprelay enabled.");
|
||||
udprelay_init(local_addr, local_port, remote_addr[0].host, remote_addr[0].port,
|
||||
tunnel_addr, m, listen_ctx.timeout, iface);
|
||||
tunnel_addr, m, listen_ctx.timeout, iface);
|
||||
}
|
||||
|
||||
// setuid
|
||||
|
||||
+26
-23
@@ -158,23 +158,24 @@ static char *get_addr_str(const struct sockaddr *sa)
|
||||
char port[PORTSTRLEN] = {0};
|
||||
uint16_t p;
|
||||
|
||||
switch(sa->sa_family) {
|
||||
case AF_INET:
|
||||
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
|
||||
addr, INET_ADDRSTRLEN);
|
||||
p = ntohs(((struct sockaddr_in *)sa)->sin_port);
|
||||
sprintf(port, "%d", p);
|
||||
break;
|
||||
switch(sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
|
||||
addr, INET_ADDRSTRLEN);
|
||||
p = ntohs(((struct sockaddr_in *)sa)->sin_port);
|
||||
sprintf(port, "%d", p);
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
|
||||
addr, INET6_ADDRSTRLEN);
|
||||
p = ntohs(((struct sockaddr_in *)sa)->sin_port);
|
||||
sprintf(port, "%d", p);
|
||||
break;
|
||||
case AF_INET6:
|
||||
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
|
||||
addr, INET6_ADDRSTRLEN);
|
||||
p = ntohs(((struct sockaddr_in *)sa)->sin_port);
|
||||
sprintf(port, "%d", p);
|
||||
break;
|
||||
|
||||
default:
|
||||
strncpy(s, "Unknown AF", SS_ADDRSTRLEN);
|
||||
default:
|
||||
strncpy(s, "Unknown AF", SS_ADDRSTRLEN);
|
||||
}
|
||||
|
||||
int addr_len = strlen(addr);
|
||||
@@ -504,7 +505,8 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents)
|
||||
|
||||
#ifdef UDPRELAY_LOCAL
|
||||
buf = ss_decrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method);
|
||||
if (buf == NULL){
|
||||
if (buf == NULL)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
ERROR("udprelay_server_ss_decrypt_all");
|
||||
@@ -587,7 +589,8 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
|
||||
|
||||
#ifdef UDPRELAY_REMOTE
|
||||
buf = ss_decrypt_all(BUF_SIZE, buf, &buf_len, server_ctx->method);
|
||||
if (buf == NULL){
|
||||
if (buf == NULL)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
ERROR("udprelay_server_ss_decrypt_all");
|
||||
@@ -808,7 +811,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
|
||||
}
|
||||
|
||||
struct query_ctx *query_ctx = new_query_ctx(query, buf + addr_header_len,
|
||||
buf_len - addr_header_len);
|
||||
buf_len - addr_header_len);
|
||||
query_ctx->server_ctx = server_ctx;
|
||||
query_ctx->addr_header_len = addr_header_len;
|
||||
query_ctx->src_addr = src_addr;
|
||||
@@ -820,7 +823,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents)
|
||||
else
|
||||
{
|
||||
int s = sendto(remote_ctx->fd, buf + addr_header_len,
|
||||
buf_len - addr_header_len, 0, &remote_ctx->dst_addr, sizeof(remote_ctx->dst_addr));
|
||||
buf_len - addr_header_len, 0, &remote_ctx->dst_addr, sizeof(remote_ctx->dst_addr));
|
||||
|
||||
if (s == -1)
|
||||
{
|
||||
@@ -848,15 +851,15 @@ void free_cb(void *element)
|
||||
|
||||
int udprelay_init(const char *server_host, const char *server_port,
|
||||
#ifdef UDPRELAY_LOCAL
|
||||
const char *remote_host, const char *remote_port,
|
||||
const char *remote_host, const char *remote_port,
|
||||
#ifdef UDPRELAY_TUNNEL
|
||||
const ss_addr_t tunnel_addr,
|
||||
const ss_addr_t tunnel_addr,
|
||||
#endif
|
||||
#endif
|
||||
#ifdef UDPRELAY_REMOTE
|
||||
asyncns_t *asyncns,
|
||||
asyncns_t *asyncns,
|
||||
#endif
|
||||
int method, int timeout, const char *iface)
|
||||
int method, int timeout, const char *iface)
|
||||
{
|
||||
|
||||
// Inilitialize ev loop
|
||||
|
||||
+58
-58
@@ -68,83 +68,83 @@ char *itoa(int i)
|
||||
int run_as(const char *user)
|
||||
{
|
||||
#ifndef __MINGW32__
|
||||
if (user[0])
|
||||
if (user[0])
|
||||
{
|
||||
#ifdef HAVE_GETPWNAM_R
|
||||
struct passwd pwdbuf, *pwd;
|
||||
size_t buflen;
|
||||
int err;
|
||||
struct passwd pwdbuf, *pwd;
|
||||
size_t buflen;
|
||||
int err;
|
||||
|
||||
for (buflen = 128;; buflen *= 2)
|
||||
for (buflen = 128;; buflen *= 2)
|
||||
{
|
||||
char buf[buflen]; /* variable length array */
|
||||
char buf[buflen]; /* variable length array */
|
||||
|
||||
/* Note that we use getpwnam_r() instead of getpwnam(),
|
||||
which returns its result in a statically allocated buffer and
|
||||
cannot be considered thread safe. */
|
||||
err = getpwnam_r(user, &pwdbuf, buf, buflen, &pwd);
|
||||
if(err == 0 && pwd)
|
||||
/* Note that we use getpwnam_r() instead of getpwnam(),
|
||||
which returns its result in a statically allocated buffer and
|
||||
cannot be considered thread safe. */
|
||||
err = getpwnam_r(user, &pwdbuf, buf, buflen, &pwd);
|
||||
if(err == 0 && pwd)
|
||||
{
|
||||
/* setgid first, because we may not be allowed to do it anymore after setuid */
|
||||
if (setgid(pwd->pw_gid) != 0)
|
||||
/* setgid first, because we may not be allowed to do it anymore after setuid */
|
||||
if (setgid(pwd->pw_gid) != 0)
|
||||
{
|
||||
LOGE("Could not change group id to that of run_as user '%s': %s",
|
||||
user,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
LOGE("Could not change group id to that of run_as user '%s': %s",
|
||||
user,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (setuid(pwd->pw_uid) != 0)
|
||||
if (setuid(pwd->pw_uid) != 0)
|
||||
{
|
||||
LOGE("Could not change user id to that of run_as user '%s': %s",
|
||||
user,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (err != ERANGE)
|
||||
LOGE("Could not change user id to that of run_as user '%s': %s",
|
||||
user,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (err != ERANGE)
|
||||
{
|
||||
if(err)
|
||||
LOGE("run_as user '%s' could not be found: %s",user,strerror(err));
|
||||
else
|
||||
LOGE("run_as user '%s' could not be found.",user);
|
||||
return 0;
|
||||
}
|
||||
else if (buflen >= 16*1024)
|
||||
if(err)
|
||||
LOGE("run_as user '%s' could not be found: %s",user,strerror(err));
|
||||
else
|
||||
LOGE("run_as user '%s' could not be found.",user);
|
||||
return 0;
|
||||
}
|
||||
else if (buflen >= 16*1024)
|
||||
{
|
||||
/* If getpwnam_r() seems defective, call it quits rather than
|
||||
keep on allocating ever larger buffers until we crash. */
|
||||
LOGE("getpwnam_r() requires more than %u bytes of buffer space.",(unsigned)buflen);
|
||||
return 0;
|
||||
}
|
||||
/* Else try again with larger buffer. */
|
||||
}
|
||||
/* If getpwnam_r() seems defective, call it quits rather than
|
||||
keep on allocating ever larger buffers until we crash. */
|
||||
LOGE("getpwnam_r() requires more than %u bytes of buffer space.",(unsigned)buflen);
|
||||
return 0;
|
||||
}
|
||||
/* Else try again with larger buffer. */
|
||||
}
|
||||
#else
|
||||
/* No getpwnam_r() :-( We'll use getpwnam() and hope for the best. */
|
||||
struct passwd *pwd;
|
||||
/* No getpwnam_r() :-( We'll use getpwnam() and hope for the best. */
|
||||
struct passwd *pwd;
|
||||
|
||||
if (!(pwd=getpwnam(user)))
|
||||
if (!(pwd=getpwnam(user)))
|
||||
{
|
||||
LOGE("run_as user %s could not be found.",user);
|
||||
return 0;
|
||||
}
|
||||
/* setgid first, because we may not allowed to do it anymore after setuid */
|
||||
if (setgid(pwd->pw_gid) != 0)
|
||||
LOGE("run_as user %s could not be found.",user);
|
||||
return 0;
|
||||
}
|
||||
/* setgid first, because we may not allowed to do it anymore after setuid */
|
||||
if (setgid(pwd->pw_gid) != 0)
|
||||
{
|
||||
LOGE("Could not change group id to that of run_as user '%s': %s",
|
||||
user,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (setuid(pwd->pw_uid) != 0)
|
||||
LOGE("Could not change group id to that of run_as user '%s': %s",
|
||||
user,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if (setuid(pwd->pw_uid) != 0)
|
||||
{
|
||||
LOGE("Could not change user id to that of run_as user '%s': %s",
|
||||
user,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
LOGE("Could not change user id to that of run_as user '%s': %s",
|
||||
user,strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif //__MINGW32__
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+19
-14
@@ -11,10 +11,12 @@ void winsock_init(void)
|
||||
int ret;
|
||||
wVersionRequested = MAKEWORD(1, 1);
|
||||
ret = WSAStartup(wVersionRequested, &wsaData);
|
||||
if (ret != 0) {
|
||||
if (ret != 0)
|
||||
{
|
||||
FATAL("Could not initialize winsock");
|
||||
}
|
||||
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) {
|
||||
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
|
||||
{
|
||||
WSACleanup();
|
||||
FATAL("Could not find a usable version of winsock");
|
||||
}
|
||||
@@ -28,11 +30,12 @@ void winsock_cleanup(void)
|
||||
void ss_error(const char *s)
|
||||
{
|
||||
LPVOID *msg = NULL;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, WSAGetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &msg, 0, NULL);
|
||||
if (msg != NULL) {
|
||||
if (msg != NULL)
|
||||
{
|
||||
LOGE("%s: %s", s, (char *)msg);
|
||||
LocalFree(msg);
|
||||
}
|
||||
@@ -43,7 +46,8 @@ int setnonblocking(int fd)
|
||||
u_long iMode = 0;
|
||||
long int iResult;
|
||||
iResult = ioctlsocket(fd, FIONBIO, &iMode);
|
||||
if (iResult != NO_ERROR) {
|
||||
if (iResult != NO_ERROR)
|
||||
{
|
||||
LOGE("ioctlsocket failed with error: %ld\n", iResult);
|
||||
}
|
||||
return iResult;
|
||||
@@ -61,15 +65,16 @@ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
|
||||
unsigned long s = size;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0) ? dst : NULL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user