proxy: Configure proxy options using URI scheme
This commit is contained in:
119
src/dns_conf.c
119
src/dns_conf.c
@@ -101,10 +101,6 @@ struct dns_domain_check_orders dns_conf_check_orders = {
|
||||
};
|
||||
static int dns_has_cap_ping = 0;
|
||||
|
||||
/* proxy servers */
|
||||
struct dns_proxy_servers dns_conf_proxy_servers[PROXY_MAX_SERVERS];
|
||||
int dns_conf_proxy_server_num;
|
||||
|
||||
/* logging */
|
||||
int dns_conf_log_level = TLOG_ERROR;
|
||||
char dns_conf_log_file[DNS_MAX_PATH];
|
||||
@@ -451,6 +447,7 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
struct dns_servers *server = NULL;
|
||||
int port = -1;
|
||||
char *ip = NULL;
|
||||
char scheme[DNS_MAX_CNAME_LEN] = {0};
|
||||
int opt = 0;
|
||||
unsigned int result_flag = 0;
|
||||
unsigned int server_flag = 0;
|
||||
@@ -497,20 +494,35 @@ static int _config_server(int argc, char *argv[], dns_server_type_t type, int de
|
||||
server->proxyname[0] = '\0';
|
||||
server->set_mark = -1;
|
||||
|
||||
if (type == DNS_SERVER_HTTPS) {
|
||||
if (parse_uri(ip, NULL, server->server, &port, server->path) != 0) {
|
||||
if (parse_uri(ip, scheme, server->server, &port, server->path) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (scheme[0] != '\0') {
|
||||
if (strcasecmp(scheme, "https") == 0) {
|
||||
type = DNS_SERVER_HTTPS;
|
||||
default_port = DEFAULT_DNS_HTTPS_PORT;
|
||||
} else if (strcasecmp(scheme, "tls") == 0) {
|
||||
type = DNS_SERVER_TLS;
|
||||
default_port = DEFAULT_DNS_TLS_PORT;
|
||||
} else if (strcasecmp(scheme, "tcp") == 0) {
|
||||
type = DNS_SERVER_TCP;
|
||||
default_port = DEFAULT_DNS_PORT;
|
||||
} else if (strcasecmp(scheme, "udp") == 0) {
|
||||
type = DNS_SERVER_UDP;
|
||||
default_port = DEFAULT_DNS_PORT;
|
||||
} else {
|
||||
tlog(TLOG_ERROR, "invalid scheme: %s", scheme);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == DNS_SERVER_HTTPS) {
|
||||
safe_strncpy(server->hostname, server->server, sizeof(server->hostname));
|
||||
safe_strncpy(server->httphost, server->server, sizeof(server->httphost));
|
||||
if (server->path[0] == 0) {
|
||||
safe_strncpy(server->path, "/", sizeof(server->path));
|
||||
}
|
||||
} else {
|
||||
/* parse ip, port from ip */
|
||||
if (parse_ip(ip, server->server, &port) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* if port is not defined, set port to default 53 */
|
||||
@@ -1599,34 +1611,27 @@ errout:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _config_proxy_server(int argc, char *argv[], struct dns_proxy_servers **pserver, proxy_type_t type)
|
||||
static int _config_proxy_server(void *data, int argc, char *argv[])
|
||||
{
|
||||
int index = dns_conf_proxy_server_num;
|
||||
struct dns_proxy_servers *server = NULL;
|
||||
char *servers_name = NULL;
|
||||
int port = -1;
|
||||
struct dns_proxy_servers *server = NULL;
|
||||
proxy_type_t type = PROXY_TYPE_END;
|
||||
|
||||
char *ip = NULL;
|
||||
int opt = 0;
|
||||
unsigned int server_flag = 0;
|
||||
int use_domain = 0;
|
||||
char scheme[DNS_MAX_CNAME_LEN] = {0};
|
||||
int port = PORT_NOT_DEFINED;
|
||||
|
||||
/* clang-format off */
|
||||
static struct option long_options[] = {
|
||||
{"name", required_argument, NULL, 'n'},
|
||||
{"use-domain", no_argument, NULL, 'd'},
|
||||
{"user", required_argument, NULL, 'u'},
|
||||
{"password", required_argument, NULL, 'p'},
|
||||
{NULL, no_argument, NULL, 0}
|
||||
};
|
||||
/* clang-format on */
|
||||
if (argc <= 1) {
|
||||
tlog(TLOG_ERROR, "invalid parameter.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ip = argv[1];
|
||||
if (index >= PROXY_MAX_SERVERS) {
|
||||
tlog(TLOG_WARN, "exceeds max server number, %s", ip);
|
||||
if (argc <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1637,10 +1642,15 @@ static int _config_proxy_server(int argc, char *argv[], struct dns_proxy_servers
|
||||
}
|
||||
memset(server, 0, sizeof(*server));
|
||||
|
||||
ip = argv[1];
|
||||
if (parse_uri_ext(ip, scheme, server->username, server->password, server->server, &port, NULL) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* process extra options */
|
||||
optind = 1;
|
||||
while (1) {
|
||||
opt = getopt_long_only(argc, argv, "n:du:p:", long_options, NULL);
|
||||
opt = getopt_long_only(argc, argv, "n:d", long_options, NULL);
|
||||
if (opt == -1) {
|
||||
break;
|
||||
}
|
||||
@@ -1654,32 +1664,26 @@ static int _config_proxy_server(int argc, char *argv[], struct dns_proxy_servers
|
||||
use_domain = 1;
|
||||
break;
|
||||
}
|
||||
case 'u': {
|
||||
safe_strncpy(server->username, optarg, sizeof(server->username));
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
safe_strncpy(server->password, optarg, sizeof(server->password));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ip = argv[optind];
|
||||
if (ip) {
|
||||
/* parse ip, port from ip */
|
||||
if (parse_ip(ip, server->server, &port) != 0) {
|
||||
return -1;
|
||||
if (strcasecmp(scheme, "socks5") == 0) {
|
||||
if (port == PORT_NOT_DEFINED) {
|
||||
port = 1080;
|
||||
}
|
||||
|
||||
/* if port is not defined, set port to default 53 */
|
||||
type = PROXY_SOCKS5;
|
||||
} else if (strcasecmp(scheme, "http") == 0) {
|
||||
if (port == PORT_NOT_DEFINED) {
|
||||
port = 443;
|
||||
port = 3128;
|
||||
}
|
||||
|
||||
type = PROXY_HTTP;
|
||||
} else {
|
||||
goto errout;
|
||||
tlog(TLOG_ERROR, "invalid scheme %s", scheme);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (servers_name == NULL) {
|
||||
@@ -1695,14 +1699,8 @@ static int _config_proxy_server(int argc, char *argv[], struct dns_proxy_servers
|
||||
/* add new server */
|
||||
server->type = type;
|
||||
server->port = port;
|
||||
server->server_flag = server_flag;
|
||||
server->use_domain = use_domain;
|
||||
dns_conf_proxy_server_num++;
|
||||
tlog(TLOG_DEBUG, "add proxy server %s, flag: %X", ip, server_flag);
|
||||
|
||||
if (pserver) {
|
||||
*pserver = server;
|
||||
}
|
||||
tlog(TLOG_DEBUG, "add proxy server %s", ip);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1714,26 +1712,6 @@ errout:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _config_proxy_socks5(void *data, int argc, char *argv[])
|
||||
{
|
||||
struct dns_proxy_servers *server = NULL;
|
||||
int ret = _config_proxy_server(argc, argv, &server, PROXY_SOCKS5);
|
||||
if (ret == 0) {
|
||||
server->socks5 = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _config_proxy_http(void *data, int argc, char *argv[])
|
||||
{
|
||||
struct dns_proxy_servers *server = NULL;
|
||||
int ret = _config_proxy_server(argc, argv, &server, PROXY_HTTP);
|
||||
if (ret == 0) {
|
||||
server->https = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static radix_node_t *_create_addr_node(char *addr)
|
||||
{
|
||||
radix_node_t *node = NULL;
|
||||
@@ -2645,8 +2623,7 @@ static struct config_item _config_item[] = {
|
||||
CONF_CUSTOM("server-https", _config_server_https, NULL),
|
||||
CONF_CUSTOM("nameserver", _config_nameserver, NULL),
|
||||
CONF_CUSTOM("address", _config_address, NULL),
|
||||
CONF_CUSTOM("proxy-socks5", _config_proxy_socks5, NULL),
|
||||
CONF_CUSTOM("proxy-http", _config_proxy_http, NULL),
|
||||
CONF_CUSTOM("proxy-server", _config_proxy_server, NULL),
|
||||
CONF_YESNO("ipset-timeout", &dns_conf_ipset_timeout_enable),
|
||||
CONF_CUSTOM("ipset", _config_ipset, NULL),
|
||||
CONF_YESNO("nftset-timeout", &dns_conf_nftset_timeout_enable),
|
||||
|
||||
@@ -263,12 +263,8 @@ struct dns_proxy_servers {
|
||||
char server[DNS_MAX_IPLEN];
|
||||
proxy_type_t type;
|
||||
unsigned short port;
|
||||
unsigned int server_flag;
|
||||
char username[DNS_PROXY_MAX_LEN];
|
||||
char password[DNS_PROXY_MAX_LEN];
|
||||
|
||||
int socks5;
|
||||
int https;
|
||||
int use_domain;
|
||||
};
|
||||
|
||||
|
||||
114
src/proxy.c
114
src/proxy.c
@@ -45,7 +45,7 @@
|
||||
#define PROXY_SOCKS5_CONNECT_UDP 0x03
|
||||
|
||||
#define PROXY_MAX_EVENTS 64
|
||||
#define PROXY_BUFFER_SIZE (1024 * 8)
|
||||
#define PROXY_BUFFER_SIZE (1024 * 4)
|
||||
#define PROXY_MAX_HOSTNAME_LEN 256
|
||||
|
||||
typedef enum PROXY_CONN_STATE {
|
||||
@@ -57,6 +57,11 @@ typedef enum PROXY_CONN_STATE {
|
||||
PROXY_CONN_CONNECTED = 5,
|
||||
} PROXY_CONN_STATE;
|
||||
|
||||
struct proxy_conn_buffer {
|
||||
int len;
|
||||
char buffer[PROXY_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
struct proxy_conn {
|
||||
proxy_type_t type;
|
||||
PROXY_CONN_STATE state;
|
||||
@@ -68,6 +73,7 @@ struct proxy_conn {
|
||||
int is_udp;
|
||||
struct sockaddr_storage udp_dest_addr;
|
||||
socklen_t udp_dest_addrlen;
|
||||
struct proxy_conn_buffer buffer;
|
||||
struct proxy_server_info *server_info;
|
||||
};
|
||||
|
||||
@@ -501,7 +507,8 @@ static proxy_handshake_state _proxy_handshake_socks5(struct proxy_conn *proxy_co
|
||||
return PROXY_HANDSHAKE_WANT_READ;
|
||||
} break;
|
||||
case PROXY_CONN_INIT_ACK:
|
||||
len = recv(proxy_conn->fd, buff, sizeof(buff), 0);
|
||||
len = recv(proxy_conn->fd, proxy_conn->buffer.buffer + proxy_conn->buffer.len,
|
||||
sizeof(proxy_conn->buffer.buffer), 0);
|
||||
if (len <= 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return PROXY_HANDSHAKE_WANT_READ;
|
||||
@@ -511,35 +518,43 @@ static proxy_handshake_state _proxy_handshake_socks5(struct proxy_conn *proxy_co
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
if (len != 2) {
|
||||
proxy_conn->buffer.len += len;
|
||||
if (proxy_conn->buffer.len < 2) {
|
||||
return PROXY_HANDSHAKE_WANT_READ;
|
||||
}
|
||||
|
||||
if (proxy_conn->buffer.len > 2) {
|
||||
tlog(TLOG_ERROR, "recv socks5 init ack failed, len = %d", len);
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
if (buff[0] != PROXY_SOCKS5_VERSION) {
|
||||
proxy_conn->buffer.len = 0;
|
||||
|
||||
if (proxy_conn->buffer.buffer[0] != PROXY_SOCKS5_VERSION) {
|
||||
tlog(TLOG_ERROR, "Server not support socks5");
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
if ((unsigned char)buff[1] == PROXY_SOCKS5_AUTH_NONE) {
|
||||
if ((unsigned char)proxy_conn->buffer.buffer[1] == PROXY_SOCKS5_AUTH_NONE) {
|
||||
tlog(TLOG_ERROR, "Server not support auth methods");
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
tlog(TLOG_INFO, "Server select auth method is %d", buff[1]);
|
||||
if (buff[1] == PROXY_SOCKS5_AUTH_USER_PASS) {
|
||||
tlog(TLOG_INFO, "Server select auth method is %d", proxy_conn->buffer.buffer[1]);
|
||||
if (proxy_conn->buffer.buffer[1] == PROXY_SOCKS5_AUTH_USER_PASS) {
|
||||
return _proxy_handshake_socks5_send_auth(proxy_conn);
|
||||
}
|
||||
|
||||
if (buff[1] == PROXY_SOCKS5_NO_AUTH) {
|
||||
if (proxy_conn->buffer.buffer[1] == PROXY_SOCKS5_NO_AUTH) {
|
||||
return _proxy_handshake_socks5_reply_connect_addr(proxy_conn);
|
||||
}
|
||||
|
||||
tlog(TLOG_ERROR, "Server select invalid auth method %d", buff[1]);
|
||||
tlog(TLOG_ERROR, "Server select invalid auth method %d", proxy_conn->buffer.buffer[1]);
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
break;
|
||||
case PROXY_CONN_AUTH_ACK:
|
||||
len = recv(proxy_conn->fd, buff, sizeof(buff), 0);
|
||||
len = recv(proxy_conn->fd, proxy_conn->buffer.buffer + proxy_conn->buffer.len,
|
||||
sizeof(proxy_conn->buffer.buffer), 0);
|
||||
if (len <= 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return PROXY_HANDSHAKE_WANT_READ;
|
||||
@@ -549,18 +564,25 @@ static proxy_handshake_state _proxy_handshake_socks5(struct proxy_conn *proxy_co
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
if (len != 2) {
|
||||
proxy_conn->buffer.len += len;
|
||||
if (proxy_conn->buffer.len < 2) {
|
||||
return PROXY_HANDSHAKE_WANT_READ;
|
||||
}
|
||||
|
||||
if (proxy_conn->buffer.len != 2) {
|
||||
tlog(TLOG_ERROR, "recv socks5 auth ack failed, len = %d", len);
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
if (buff[0] != 0x1) {
|
||||
proxy_conn->buffer.len = 0;
|
||||
|
||||
if (proxy_conn->buffer.buffer[0] != 0x1) {
|
||||
tlog(TLOG_ERROR, "Server not support socks5");
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
if (buff[1] != 0x0) {
|
||||
tlog(TLOG_ERROR, "Server auth failed, code = %d", buff[1]);
|
||||
if (proxy_conn->buffer.buffer[1] != 0x0) {
|
||||
tlog(TLOG_ERROR, "Server auth failed, code = %d", proxy_conn->buffer.buffer[1]);
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
@@ -571,9 +593,11 @@ static proxy_handshake_state _proxy_handshake_socks5(struct proxy_conn *proxy_co
|
||||
unsigned char addr[16];
|
||||
unsigned short port = 0;
|
||||
int use_dest_ip = 0;
|
||||
char *recv_buff = NULL;
|
||||
|
||||
int addr_len = 0;
|
||||
len = recv(proxy_conn->fd, buff, sizeof(buff), 0);
|
||||
len = recv(proxy_conn->fd, proxy_conn->buffer.buffer + proxy_conn->buffer.len,
|
||||
sizeof(proxy_conn->buffer.buffer), 0);
|
||||
if (len <= 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
return PROXY_HANDSHAKE_WANT_READ;
|
||||
@@ -583,40 +607,42 @@ static proxy_handshake_state _proxy_handshake_socks5(struct proxy_conn *proxy_co
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
if (len < 10) {
|
||||
tlog(TLOG_ERROR, "Server reply connect addr failed, len = %d", len);
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
proxy_conn->buffer.len += len;
|
||||
if (proxy_conn->buffer.len < 10) {
|
||||
return PROXY_HANDSHAKE_WANT_READ;
|
||||
}
|
||||
recv_buff = proxy_conn->buffer.buffer;
|
||||
|
||||
if (buff[0] != PROXY_SOCKS5_VERSION) {
|
||||
if (recv_buff[0] != PROXY_SOCKS5_VERSION) {
|
||||
tlog(TLOG_ERROR, "Server not support socks5");
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
if (buff[1] != 0) {
|
||||
if ((unsigned char)buff[1] <= (sizeof(proxy_socks5_status_code) / sizeof(proxy_socks5_status_code[0]))) {
|
||||
tlog(TLOG_ERROR, "Server replay failed, error code %s", proxy_socks5_status_code[(int)buff[1]]);
|
||||
if (recv_buff[1] != 0) {
|
||||
if ((unsigned char)recv_buff[1] <=
|
||||
(sizeof(proxy_socks5_status_code) / sizeof(proxy_socks5_status_code[0]))) {
|
||||
tlog(TLOG_ERROR, "Server replay failed, error code %s", proxy_socks5_status_code[(int)recv_buff[1]]);
|
||||
} else {
|
||||
tlog(TLOG_ERROR, "Server replay failed, error code %x", buff[1]);
|
||||
tlog(TLOG_ERROR, "Server replay failed, error code %x", recv_buff[1]);
|
||||
}
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
}
|
||||
|
||||
switch (buff[3]) {
|
||||
switch (recv_buff[3]) {
|
||||
case PROXY_SOCKS5_TYPE_IPV4: {
|
||||
struct sockaddr_in *addr_in = NULL;
|
||||
addr_in = (struct sockaddr_in *)&proxy_conn->udp_dest_addr;
|
||||
proxy_conn->udp_dest_addrlen = sizeof(struct sockaddr_in);
|
||||
if (len != 10) {
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
if (proxy_conn->buffer.len < 10) {
|
||||
return PROXY_HANDSHAKE_WANT_READ;
|
||||
}
|
||||
|
||||
addr_len = 4;
|
||||
memcpy(addr, buff + 4, addr_len);
|
||||
port = ntohs(*((short *)(buff + 4 + addr_len)));
|
||||
memcpy(addr, recv_buff + 4, addr_len);
|
||||
port = ntohs(*((short *)(recv_buff + 4 + addr_len)));
|
||||
addr_in->sin_family = AF_INET;
|
||||
addr_in->sin_addr.s_addr = *((int *)addr);
|
||||
addr_in->sin_port = *((short *)(buff + 4 + addr_len));
|
||||
addr_in->sin_port = *((short *)(recv_buff + 4 + addr_len));
|
||||
if (addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0) {
|
||||
use_dest_ip = 1;
|
||||
}
|
||||
@@ -627,16 +653,16 @@ static proxy_handshake_state _proxy_handshake_socks5(struct proxy_conn *proxy_co
|
||||
struct sockaddr_in6 *addr_in6 = NULL;
|
||||
addr_in6 = (struct sockaddr_in6 *)&proxy_conn->udp_dest_addr;
|
||||
proxy_conn->udp_dest_addrlen = sizeof(struct sockaddr_in6);
|
||||
if (len != 22) {
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
if (proxy_conn->buffer.len < 22) {
|
||||
return PROXY_HANDSHAKE_WANT_READ;
|
||||
}
|
||||
|
||||
addr_len = 16;
|
||||
memcpy(addr, buff + 4, addr_len);
|
||||
port = ntohs(*((short *)(buff + 4 + addr_len)));
|
||||
memcpy(addr, recv_buff + 4, addr_len);
|
||||
port = ntohs(*((short *)(recv_buff + 4 + addr_len)));
|
||||
addr_in6->sin6_family = AF_INET6;
|
||||
memcpy(addr_in6->sin6_addr.s6_addr, addr, addr_len);
|
||||
addr_in6->sin6_port = *((short *)(buff + 4 + addr_len));
|
||||
addr_in6->sin6_port = *((short *)(recv_buff + 4 + addr_len));
|
||||
|
||||
if (addr[0] == 0 && addr[1] == 0 && addr[2] == 0 && addr[3] == 0 && addr[4] == 0 && addr[5] == 0 &&
|
||||
addr[6] == 0 && addr[7] == 0 && addr[8] == 0 && addr[9] == 0 && addr[10] == 0 && addr[11] == 0 &&
|
||||
@@ -661,12 +687,12 @@ static proxy_handshake_state _proxy_handshake_socks5(struct proxy_conn *proxy_co
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *addr_in = NULL;
|
||||
addr_in = (struct sockaddr_in *)&proxy_conn->udp_dest_addr;
|
||||
addr_in->sin_port = *((short *)(buff + 4 + addr_len));
|
||||
addr_in->sin_port = *((short *)(recv_buff + 4 + addr_len));
|
||||
} break;
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *addr_in6 = NULL;
|
||||
addr_in6 = (struct sockaddr_in6 *)&proxy_conn->udp_dest_addr;
|
||||
addr_in6->sin6_port = *((short *)(buff + 4 + addr_len));
|
||||
addr_in6->sin6_port = *((short *)(recv_buff + 4 + addr_len));
|
||||
} break;
|
||||
default:
|
||||
return PROXY_HANDSHAKE_ERR;
|
||||
@@ -754,7 +780,8 @@ static int _proxy_handshake_http(struct proxy_conn *proxy_conn)
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = recv(proxy_conn->fd, buff, sizeof(buff), 0);
|
||||
len = recv(proxy_conn->fd, proxy_conn->buffer.buffer + proxy_conn->buffer.len,
|
||||
sizeof(proxy_conn->buffer.buffer), 0);
|
||||
if (len <= 0) {
|
||||
if (len == 0) {
|
||||
tlog(TLOG_ERROR, "remote server closed.");
|
||||
@@ -763,10 +790,12 @@ static int _proxy_handshake_http(struct proxy_conn *proxy_conn)
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
proxy_conn->buffer.len += len;
|
||||
|
||||
len = http_head_parse(http_head, buff, len);
|
||||
len = http_head_parse(http_head, proxy_conn->buffer.buffer, proxy_conn->buffer.len);
|
||||
if (len < 0) {
|
||||
if (len == -1) {
|
||||
ret = PROXY_HANDSHAKE_WANT_READ;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -780,6 +809,15 @@ static int _proxy_handshake_http(struct proxy_conn *proxy_conn)
|
||||
goto out;
|
||||
}
|
||||
|
||||
proxy_conn->buffer.len -= len;
|
||||
if (proxy_conn->buffer.len > 0) {
|
||||
memmove(proxy_conn->buffer.buffer, proxy_conn->buffer.buffer + len, proxy_conn->buffer.len);
|
||||
}
|
||||
|
||||
if (proxy_conn->buffer.len < 0) {
|
||||
proxy_conn->buffer.len = 0;
|
||||
}
|
||||
tlog(TLOG_INFO, "connected to http proxy server.");
|
||||
proxy_conn->state = PROXY_CONN_CONNECTED;
|
||||
ret = PROXY_HANDSHAKE_CONNECTED;
|
||||
goto out;
|
||||
|
||||
78
src/util.c
78
src/util.c
@@ -24,6 +24,7 @@
|
||||
#include "tlog.h"
|
||||
#include "util.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <ctype.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -389,11 +390,54 @@ int check_is_ipaddr(const char *ip)
|
||||
}
|
||||
|
||||
int parse_uri(char *value, char *scheme, char *host, int *port, char *path)
|
||||
{
|
||||
return parse_uri_ext(value, scheme, NULL, NULL, host, port, path);
|
||||
}
|
||||
|
||||
void urldecode(char *dst, const char *src)
|
||||
{
|
||||
char a, b;
|
||||
while (*src) {
|
||||
if ((*src == '%') && ((a = src[1]) && (b = src[2])) && (isxdigit(a) && isxdigit(b))) {
|
||||
if (a >= 'a') {
|
||||
a -= 'a' - 'A';
|
||||
}
|
||||
|
||||
if (a >= 'A') {
|
||||
a -= ('A' - 10);
|
||||
} else {
|
||||
a -= '0';
|
||||
}
|
||||
|
||||
if (b >= 'a') {
|
||||
b -= 'a' - 'A';
|
||||
}
|
||||
|
||||
if (b >= 'A') {
|
||||
b -= ('A' - 10);
|
||||
} else {
|
||||
b -= '0';
|
||||
}
|
||||
*dst++ = 16 * a + b;
|
||||
src += 3;
|
||||
} else if (*src == '+') {
|
||||
*dst++ = ' ';
|
||||
src++;
|
||||
} else {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
*dst++ = '\0';
|
||||
}
|
||||
|
||||
int parse_uri_ext(char *value, char *scheme, char *user, char *password, char *host, int *port, char *path)
|
||||
{
|
||||
char *scheme_end = NULL;
|
||||
int field_len = 0;
|
||||
char *process_ptr = value;
|
||||
char host_name[PATH_MAX];
|
||||
char user_pass_host_part[PATH_MAX];
|
||||
char *user_password = NULL;
|
||||
char *host_part = NULL;
|
||||
|
||||
char *host_end = NULL;
|
||||
|
||||
@@ -413,24 +457,44 @@ int parse_uri(char *value, char *scheme, char *host, int *port, char *path)
|
||||
|
||||
host_end = strstr(process_ptr, "/");
|
||||
if (host_end == NULL) {
|
||||
return parse_ip(process_ptr, host, port);
|
||||
host_end = process_ptr + strlen(process_ptr);
|
||||
};
|
||||
|
||||
field_len = host_end - process_ptr;
|
||||
if (field_len >= (int)sizeof(host_name)) {
|
||||
if (field_len >= (int)sizeof(user_pass_host_part)) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(host_name, process_ptr, field_len);
|
||||
host_name[field_len] = 0;
|
||||
memcpy(user_pass_host_part, process_ptr, field_len);
|
||||
user_pass_host_part[field_len] = 0;
|
||||
|
||||
if (parse_ip(host_name, host, port) != 0) {
|
||||
host_part = strstr(user_pass_host_part, "@");
|
||||
if (host_part != NULL) {
|
||||
*host_part = '\0';
|
||||
host_part = host_part + 1;
|
||||
user_password = user_pass_host_part;
|
||||
char *sep = strstr(user_password, ":");
|
||||
if (sep != NULL) {
|
||||
*sep = '\0';
|
||||
sep = sep + 1;
|
||||
if (password) {
|
||||
urldecode(password, sep);
|
||||
}
|
||||
}
|
||||
if (user) {
|
||||
urldecode(user, user_password);
|
||||
}
|
||||
} else {
|
||||
host_part = user_pass_host_part;
|
||||
}
|
||||
|
||||
if (host != NULL && parse_ip(host_part, host, port) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
process_ptr += field_len;
|
||||
|
||||
if (path) {
|
||||
strncpy(path, process_ptr, PATH_MAX);
|
||||
strcpy(path, process_ptr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,10 @@ int check_is_ipaddr(const char *ip);
|
||||
|
||||
int parse_uri(char *value, char *scheme, char *host, int *port, char *path);
|
||||
|
||||
int parse_uri_ext(char *value, char *scheme, char *user, char *password, char *host, int *port, char *path);
|
||||
|
||||
void urldecode(char *dst, const char *src);
|
||||
|
||||
int set_fd_nonblock(int fd, int nonblock);
|
||||
|
||||
char *reverse_string(char *output, const char *input, int len, int to_lower_case);
|
||||
|
||||
Reference in New Issue
Block a user