Refine buffer handling

This commit is contained in:
Max Lv
2015-11-30 15:03:04 +08:00
committed by Max Lv
parent f4fa30da5c
commit b0600a8784
29 changed files with 2616 additions and 1397 deletions
+87 -80
View File
@@ -92,7 +92,7 @@ static char *hash_key(const int af, const struct sockaddr_storage *addr);
static void query_resolve_cb(struct sockaddr *addr, void *data);
#endif
static void close_and_free_remote(EV_P_ remote_ctx_t *ctx);
static remote_ctx_t * new_remote(int fd, server_ctx_t * server_ctx);
static remote_ctx_t *new_remote(int fd, server_ctx_t *server_ctx);
extern int verbose;
extern int vpn;
@@ -101,7 +101,7 @@ extern uint64_t tx;
extern uint64_t rx;
#endif
static int server_num = 0;
static int server_num = 0;
static server_ctx_t *server_ctx_list[MAX_REMOTE_NUM] = { NULL };
#ifndef __MINGW32__
@@ -113,10 +113,11 @@ static int setnonblocking(int fd)
}
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}
#endif
#ifdef SET_INTERFACE
static int setinterface(int socket_fd, const char * interface_name)
static int setinterface(int socket_fd, const char *interface_name)
{
struct ifreq interface;
memset(&interface, 0, sizeof(interface));
@@ -125,6 +126,7 @@ static int setinterface(int socket_fd, const char * interface_name)
sizeof(struct ifreq));
return res;
}
#endif
#if defined(UDPRELAY_REMOTE) && defined(SO_BROADCAST)
@@ -133,6 +135,7 @@ static int set_broadcast(int socket_fd)
int opt = 1;
return setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));
}
#endif
#ifdef SO_NOSIGPIPE
@@ -141,6 +144,7 @@ static int set_nosigpipe(int socket_fd)
int opt = 1;
return setsockopt(socket_fd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
}
#endif
#ifdef UDPRELAY_REDIR
@@ -162,7 +166,6 @@ static int get_dstaddr(struct msghdr *msg, struct sockaddr_storage *dstaddr)
memcpy(dstaddr, CMSG_DATA(cmsg), sizeof(struct sockaddr_in));
dstaddr->ss_family = AF_INET;
return 0;
} else if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IP_RECVORIGDSTADDR) {
memcpy(dstaddr, CMSG_DATA(cmsg), sizeof(struct sockaddr_in6));
dstaddr->ss_family = AF_INET6;
@@ -172,6 +175,7 @@ static int get_dstaddr(struct msghdr *msg, struct sockaddr_storage *dstaddr)
return 1;
}
#endif
#define HASH_KEY_LEN sizeof(struct sockaddr_storage) + sizeof(int)
@@ -191,11 +195,10 @@ static char *hash_key(const int af, const struct sockaddr_storage *addr)
static int construct_udprealy_header(const struct sockaddr_storage *in_addr,
char *addr_header)
{
int addr_header_len = 0;
if (in_addr->ss_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *)in_addr;
size_t addr_len = sizeof(struct in_addr);
size_t addr_len = sizeof(struct in_addr);
addr_header[addr_header_len++] = 1;
memcpy(addr_header + addr_header_len, &addr->sin_addr, addr_len);
addr_header_len += addr_len;
@@ -203,7 +206,7 @@ static int construct_udprealy_header(const struct sockaddr_storage *in_addr,
addr_header_len += 2;
} else if (in_addr->ss_family == AF_INET6) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)in_addr;
size_t addr_len = sizeof(struct in6_addr);
size_t addr_len = sizeof(struct in6_addr);
addr_header[addr_header_len++] = 4;
memcpy(addr_header + addr_header_len, &addr->sin6_addr, addr_len);
addr_header_len += addr_len;
@@ -214,15 +217,15 @@ static int construct_udprealy_header(const struct sockaddr_storage *in_addr,
}
return addr_header_len;
}
#endif
static int parse_udprealy_header(const char * buf, const int buf_len,
static int parse_udprealy_header(const char *buf, const int buf_len,
int *auth, char *host, char *port,
struct sockaddr_storage *storage)
{
const uint8_t atyp = *(uint8_t *)buf;
int offset = 1;
int offset = 1;
if (auth != NULL) {
*auth |= (atyp & ONETIMEAUTH_FLAG);
@@ -236,8 +239,8 @@ static int parse_udprealy_header(const char * buf, const int buf_len,
if (storage != NULL) {
struct sockaddr_in *addr = (struct sockaddr_in *)storage;
addr->sin_family = AF_INET;
addr->sin_addr = *(struct in_addr *)(buf + offset);
addr->sin_port = *(uint16_t *)(buf + offset + in_addr_len);
addr->sin_addr = *(struct in_addr *)(buf + offset);
addr->sin_port = *(uint16_t *)(buf + offset + in_addr_len);
}
if (host != NULL) {
dns_ntop(AF_INET, (const void *)(buf + offset),
@@ -257,12 +260,12 @@ static int parse_udprealy_header(const char * buf, const int buf_len,
if (ip.version == 4) {
struct sockaddr_in *addr = (struct sockaddr_in *)storage;
dns_pton(AF_INET, tmp, &(addr->sin_addr));
addr->sin_port = *(uint16_t *)(buf + offset + 1 + name_len);
addr->sin_port = *(uint16_t *)(buf + offset + 1 + name_len);
addr->sin_family = AF_INET;
} else if (ip.version == 6) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage;
dns_pton(AF_INET, tmp, &(addr->sin6_addr));
addr->sin6_port = *(uint16_t *)(buf + offset + 1 + name_len);
addr->sin6_port = *(uint16_t *)(buf + offset + 1 + name_len);
addr->sin6_family = AF_INET6;
}
}
@@ -279,8 +282,8 @@ static int parse_udprealy_header(const char * buf, const int buf_len,
if (storage != NULL) {
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)storage;
addr->sin6_family = AF_INET6;
addr->sin6_addr = *(struct in6_addr *)(buf + offset);
addr->sin6_port = *(uint16_t *)(buf + offset + in6_addr_len);
addr->sin6_addr = *(struct in6_addr *)(buf + offset);
addr->sin6_port = *(uint16_t *)(buf + offset + in6_addr_len);
}
if (host != NULL) {
dns_ntop(AF_INET6, (const void *)(buf + offset),
@@ -308,7 +311,7 @@ static char *get_addr_str(const struct sockaddr *sa)
static char s[SS_ADDRSTRLEN];
memset(s, 0, SS_ADDRSTRLEN);
char addr[INET6_ADDRSTRLEN] = { 0 };
char port[PORTSTRLEN] = { 0 };
char port[PORTSTRLEN] = { 0 };
uint16_t p;
switch (sa->sa_family) {
@@ -339,7 +342,6 @@ static char *get_addr_str(const struct sockaddr *sa)
return s;
}
int create_remote_socket(int ipv6)
{
int remote_sock;
@@ -349,9 +351,9 @@ int create_remote_socket(int ipv6)
struct sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_port = 0;
remote_sock = socket(AF_INET6, SOCK_DGRAM, 0);
addr.sin6_addr = in6addr_any;
addr.sin6_port = 0;
remote_sock = socket(AF_INET6, SOCK_DGRAM, 0);
if (remote_sock == -1) {
ERROR("[udp] cannot create socket");
return -1;
@@ -364,10 +366,10 @@ int create_remote_socket(int ipv6)
// Or else bind to IPv4
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 0;
remote_sock = socket(AF_INET, SOCK_DGRAM, 0);
addr.sin_port = 0;
remote_sock = socket(AF_INET, SOCK_DGRAM, 0);
if (remote_sock == -1) {
ERROR("[udp] cannot create socket");
return -1;
@@ -388,9 +390,9 @@ int create_server_socket(const char *host, const char *port)
int s, server_sock;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
hints.ai_family = AF_UNSPEC; /* Return IPv4 and IPv6 choices */
hints.ai_socktype = SOCK_DGRAM; /* We want a UDP socket */
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */
hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* For wildcard IP address */
hints.ai_protocol = IPPROTO_UDP;
s = getaddrinfo(host, port, &hints, &result);
@@ -402,10 +404,10 @@ int create_server_socket(const char *host, const char *port)
rp = result;
/*
On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with
AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to
return a list of addresses to listen on, but it is impossible to listen on
0.0.0.0 and :: at the same time, if :: implies dualstack mode.
* On Linux, with net.ipv6.bindv6only = 0 (the default), getaddrinfo(NULL) with
* AI_PASSIVE returns 0.0.0.0 and :: (in this order). AI_PASSIVE was meant to
* return a list of addresses to listen on, but it is impossible to listen on
* 0.0.0.0 and :: at the same time, if :: implies dualstack mode.
*/
if (!host) {
ipv4v6bindall = result;
@@ -472,20 +474,25 @@ remote_ctx_t *new_remote(int fd, server_ctx_t *server_ctx)
remote_ctx_t *ctx = malloc(sizeof(remote_ctx_t));
memset(ctx, 0, sizeof(remote_ctx_t));
ctx->fd = fd;
ctx->fd = fd;
ctx->server_ctx = server_ctx;
ev_io_init(&ctx->io, remote_recv_cb, fd, EV_READ);
ev_timer_init(&ctx->watcher, remote_timeout_cb, server_ctx->timeout,
server_ctx->timeout);
return ctx;
}
server_ctx_t * new_server_ctx(int fd)
server_ctx_t *new_server_ctx(int fd)
{
server_ctx_t *ctx = malloc(sizeof(server_ctx_t));
memset(ctx, 0, sizeof(server_ctx_t));
ctx->fd = fd;
ev_io_init(&ctx->io, server_recv_cb, fd, EV_READ);
return ctx;
}
@@ -497,6 +504,7 @@ struct query_ctx *new_query_ctx(char *buf, size_t len)
ctx->buf = malloc(sizeof(buffer_t));
balloc(ctx->buf, len);
memcpy(ctx->buf->array, buf, len);
ctx->buf->len = len;
return ctx;
}
@@ -530,7 +538,7 @@ void close_and_free_remote(EV_P_ remote_ctx_t *ctx)
static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents)
{
remote_ctx_t *remote_ctx = (remote_ctx_t *)(((void *)watcher)
- sizeof(ev_io));
- sizeof(ev_io));
if (verbose) {
LOGI("[udp] connection timeout");
@@ -544,7 +552,7 @@ static void remote_timeout_cb(EV_P_ ev_timer *watcher, int revents)
static void query_resolve_cb(struct sockaddr *addr, void *data)
{
struct query_ctx *query_ctx = (struct query_ctx *)data;
struct ev_loop *loop = query_ctx->server_ctx->loop;
struct ev_loop *loop = query_ctx->server_ctx->loop;
if (verbose) {
LOGI("[udp] udns resolved");
@@ -556,7 +564,7 @@ static void query_resolve_cb(struct sockaddr *addr, void *data)
LOGE("[udp] udns returned an error");
} else {
remote_ctx_t *remote_ctx = query_ctx->remote_ctx;
int cache_hit = 0;
int cache_hit = 0;
// Lookup in the conn cache
if (remote_ctx == NULL) {
@@ -579,9 +587,9 @@ static void query_resolve_cb(struct sockaddr *addr, void *data)
setinterface(remotefd, query_ctx->server_ctx->iface);
}
#endif
remote_ctx = new_remote(remotefd, query_ctx->server_ctx);
remote_ctx->src_addr = query_ctx->src_addr;
remote_ctx->server_ctx = query_ctx->server_ctx;
remote_ctx = new_remote(remotefd, query_ctx->server_ctx);
remote_ctx->src_addr = query_ctx->src_addr;
remote_ctx->server_ctx = query_ctx->server_ctx;
remote_ctx->addr_header_len = query_ctx->addr_header_len;
memcpy(remote_ctx->addr_header, query_ctx->addr_header,
query_ctx->addr_header_len);
@@ -594,8 +602,8 @@ static void query_resolve_cb(struct sockaddr *addr, void *data)
if (remote_ctx != NULL) {
size_t addr_len = get_sockaddr_len(addr);
int s = sendto(remote_ctx->fd, query_ctx->buf->array, query_ctx->buf->len,
0, addr, addr_len);
int s = sendto(remote_ctx->fd, query_ctx->buf->array, query_ctx->buf->len,
0, addr, addr_len);
if (s == -1) {
ERROR("[udp] sendto_remote");
@@ -612,12 +620,12 @@ static void query_resolve_cb(struct sockaddr *addr, void *data)
}
}
}
}
// clean up
close_and_free_query(EV_A_ query_ctx);
}
#endif
static void remote_recv_cb(EV_P_ ev_io *w, int revents)
@@ -705,12 +713,12 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
rx += buf->len;
char addr_header_buf[256];
char *addr_header = remote_ctx->addr_header;
char *addr_header = remote_ctx->addr_header;
int addr_header_len = remote_ctx->addr_header_len;
if (remote_ctx->af == AF_INET || remote_ctx->af == AF_INET6) {
addr_header_len = construct_udprealy_header(&src_addr, addr_header_buf);
addr_header = addr_header_buf;
addr_header = addr_header_buf;
}
// Construct packet
@@ -775,7 +783,7 @@ static void remote_recv_cb(EV_P_ ev_io *w, int revents)
// triger the timer
ev_timer_again(EV_A_ & remote_ctx->watcher);
CLEAN_UP:
CLEAN_UP:
bfree(buf);
free(buf);
@@ -791,7 +799,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
balloc(buf, BUF_SIZE);
socklen_t src_addr_len = sizeof(struct sockaddr_storage);
unsigned int offset = 0;
unsigned int offset = 0;
#ifdef UDPRELAY_REDIR
char control_buffer[64] = { 0 };
@@ -800,15 +808,15 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
struct sockaddr_storage dst_addr;
memset(&dst_addr, 0, sizeof(struct sockaddr_storage));
msg.msg_name = &src_addr;
msg.msg_namelen = src_addr_len;
msg.msg_control = control_buffer;
msg.msg_name = &src_addr;
msg.msg_namelen = src_addr_len;
msg.msg_control = control_buffer;
msg.msg_controllen = sizeof(control_buffer);
iov[0].iov_base = buf->array;
iov[0].iov_len = BUF_SIZE;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
iov[0].iov_len = BUF_SIZE;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
ssize_t buf_len = recvmsg(server_ctx->fd, &msg, 0);
if (buf_len == -1) {
@@ -824,7 +832,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
src_addr_len = msg.msg_namelen;
#else
buf->len = recvfrom(server_ctx->fd, buf->array, BUF_SIZE,
0, (struct sockaddr *)&src_addr, &src_addr_len);
0, (struct sockaddr *)&src_addr, &src_addr_len);
if (buf->len == -1) {
// error on recv
@@ -907,7 +915,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
#ifdef UDPRELAY_REDIR
char addr_header[256] = { 0 };
int addr_header_len = construct_udprealy_header(&dst_addr, addr_header);
int addr_header_len = construct_udprealy_header(&dst_addr, addr_header);
if (addr_header_len == 0) {
LOGE("[udp] failed to parse tproxy addr");
@@ -925,11 +933,11 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
#elif UDPRELAY_TUNNEL
char addr_header[256] = { 0 };
char *host = server_ctx->tunnel_addr.host;
char *port = server_ctx->tunnel_addr.port;
uint16_t port_num = (uint16_t)atoi(port);
char *host = server_ctx->tunnel_addr.host;
char *port = server_ctx->tunnel_addr.port;
uint16_t port_num = (uint16_t)atoi(port);
uint16_t port_net_num = htons(port_num);
int addr_header_len = 0;
int addr_header_len = 0;
struct cork_ip ip;
if (cork_ip_init(&ip, host) != -1) {
@@ -981,7 +989,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
#else
char host[256] = { 0 };
char port[64] = { 0 };
char port[64] = { 0 };
struct sockaddr_storage dst_addr;
memset(&dst_addr, 0, sizeof(struct sockaddr_storage));
@@ -994,7 +1002,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
}
char *addr_header = buf->array + offset;
char *key = hash_key(dst_addr.ss_family, &src_addr);
char *key = hash_key(dst_addr.ss_family, &src_addr);
#endif
struct cache *conn_cache = server_ctx->conn_cache;
@@ -1051,7 +1059,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
#endif
const struct sockaddr *remote_addr = server_ctx->remote_addr;
const int remote_addr_len = server_ctx->remote_addr_len;
const int remote_addr_len = server_ctx->remote_addr_len;
if (remote_ctx == NULL) {
// Bind to any port
@@ -1082,9 +1090,9 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
#endif
// Init remote_ctx
remote_ctx = new_remote(remotefd, server_ctx);
remote_ctx->src_addr = src_addr;
remote_ctx->af = remote_addr->sa_family;
remote_ctx = new_remote(remotefd, server_ctx);
remote_ctx->src_addr = src_addr;
remote_ctx->af = remote_addr->sa_family;
remote_ctx->addr_header_len = addr_header_len;
memcpy(remote_ctx->addr_header, addr_header, addr_header_len);
@@ -1094,7 +1102,6 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
// Start remote io
ev_io_start(EV_A_ & remote_ctx->io);
ev_timer_start(EV_A_ & remote_ctx->watcher);
}
if (offset > 0) {
@@ -1121,7 +1128,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
#else
int cache_hit = 0;
int cache_hit = 0;
int need_query = 0;
if (remote_ctx != NULL) {
@@ -1149,9 +1156,9 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
setinterface(remotefd, server_ctx->iface);
}
#endif
remote_ctx = new_remote(remotefd, server_ctx);
remote_ctx->src_addr = src_addr;
remote_ctx->server_ctx = server_ctx;
remote_ctx = new_remote(remotefd, server_ctx);
remote_ctx->src_addr = src_addr;
remote_ctx->server_ctx = server_ctx;
remote_ctx->addr_header_len = addr_header_len;
memcpy(remote_ctx->addr_header, addr_header, addr_header_len);
} else {
@@ -1163,9 +1170,9 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
if (remote_ctx != NULL && !need_query) {
size_t addr_len = get_sockaddr_len((struct sockaddr *)&dst_addr);
int s = sendto(remote_ctx->fd, buf->array + addr_header_len,
buf->len - addr_header_len, 0,
(struct sockaddr *)&dst_addr, addr_len);
int s = sendto(remote_ctx->fd, buf->array + addr_header_len,
buf->len - addr_header_len, 0,
(struct sockaddr *)&dst_addr, addr_len);
if (s == -1) {
ERROR("[udp] sendto_remote");
@@ -1186,15 +1193,15 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
} else {
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
struct query_ctx *query_ctx = new_query_ctx(buf->array + addr_header_len,
buf->len - addr_header_len);
query_ctx->server_ctx = server_ctx;
query_ctx->server_ctx = server_ctx;
query_ctx->addr_header_len = addr_header_len;
query_ctx->src_addr = src_addr;
query_ctx->src_addr = src_addr;
memcpy(query_ctx->addr_header, addr_header, addr_header_len);
if (need_query) {
@@ -1212,7 +1219,7 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents)
}
#endif
CLEAN_UP:
CLEAN_UP:
bfree(buf);
free(buf);
}
@@ -1258,13 +1265,13 @@ int init_udprelay(const char *server_host, const char *server_port,
#ifdef UDPRELAY_REMOTE
server_ctx->loop = loop;
#endif
server_ctx->auth = auth;
server_ctx->timeout = max(timeout, MIN_UDP_TIMEOUT);
server_ctx->method = method;
server_ctx->iface = iface;
server_ctx->auth = auth;
server_ctx->timeout = max(timeout, MIN_UDP_TIMEOUT);
server_ctx->method = method;
server_ctx->iface = iface;
server_ctx->conn_cache = conn_cache;
#ifdef UDPRELAY_LOCAL
server_ctx->remote_addr = remote_addr;
server_ctx->remote_addr = remote_addr;
server_ctx->remote_addr_len = remote_addr_len;
#ifdef UDPRELAY_TUNNEL
server_ctx->tunnel_addr = tunnel_addr;