diff --git a/src/acl.c b/src/acl.c index 740fbc56..aa1da28c 100644 --- a/src/acl.c +++ b/src/acl.c @@ -33,6 +33,7 @@ #endif #include "rule.h" +#include "netutils.h" #include "utils.h" #include "cache.h" #include "acl.h" @@ -193,7 +194,8 @@ init_acl(const char *path) return -1; } - char buf[257]; + char buf[MAX_HOSTNAME_LEN]; + while (!feof(f)) if (fgets(buf, 256, f)) { // Discards the whole line if longer than 255 characters @@ -256,7 +258,7 @@ init_acl(const char *path) continue; } - char host[257]; + char host[MAX_HOSTNAME_LEN]; int cidr; parse_addr_cidr(line, host, &cidr); diff --git a/src/netutils.h b/src/netutils.h index 25c5dd92..075f1dd1 100644 --- a/src/netutils.h +++ b/src/netutils.h @@ -52,6 +52,9 @@ #endif #endif +#define MAX_HOSTNAME_LEN 256 // FQCN <= 255 characters +#define MAX_PORT_STR_LEN 6 // PORT < 65536 + typedef struct { char *host; char *port; diff --git a/src/server.c b/src/server.c index e336b698..36ca409a 100644 --- a/src/server.c +++ b/src/server.c @@ -966,7 +966,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents) memset(query, 0, sizeof(query_t)); query->server = server; server->query = query; - snprintf(query->hostname, 257, "%s", host); + snprintf(query->hostname, MAX_HOSTNAME_LEN, "%s", host); server->stage = STAGE_RESOLVE; resolv_start(host, port, resolv_cb, resolv_free_cb, query); diff --git a/src/server.h b/src/server.h index 714878b1..9f5f6814 100644 --- a/src/server.h +++ b/src/server.h @@ -39,6 +39,7 @@ #include "crypto.h" #include "jconf.h" #include "resolv.h" +#include "netutils.h" #include "common.h" @@ -97,7 +98,7 @@ typedef struct server { typedef struct query { server_t *server; - char hostname[257]; + char hostname[MAX_HOSTNAME_LEN]; } query_t; typedef struct remote_ctx { diff --git a/src/udprelay.c b/src/udprelay.c index a3273ae8..df49d9ef 100644 --- a/src/udprelay.c +++ b/src/udprelay.c @@ -200,14 +200,17 @@ hash_key(const int af, const struct sockaddr_storage *addr) } #if defined(MODULE_REDIR) || defined(MODULE_REMOTE) + static int construct_udprelay_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); + addr_header[addr_header_len++] = 1; memcpy(addr_header + addr_header_len, &addr->sin_addr, addr_len); addr_header_len += addr_len; @@ -216,6 +219,7 @@ construct_udprelay_header(const struct sockaddr_storage *in_addr, } 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); + addr_header[addr_header_len++] = 4; memcpy(addr_header + addr_header_len, &addr->sin6_addr, addr_len); addr_header_len += addr_len; @@ -224,6 +228,7 @@ construct_udprelay_header(const struct sockaddr_storage *in_addr, } else { return 0; } + return addr_header_len; } @@ -258,7 +263,7 @@ parse_udprelay_header(const char *buf, const size_t buf_len, uint8_t name_len = *(uint8_t *)(buf + offset); if (name_len + 4 <= buf_len) { if (storage != NULL) { - char tmp[257] = { 0 }; + char tmp[MAX_HOSTNAME_LEN] = { 0 }; struct cork_ip ip; memcpy(tmp, buf + offset + 1, name_len); if (cork_ip_init(&ip, tmp) != -1) { @@ -655,9 +660,6 @@ resolv_cb(struct sockaddr *addr, void *data) 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); } else { ERROR("[udp] bind() error"); } @@ -785,7 +787,7 @@ remote_recv_cb(EV_P_ ev_io *w, int revents) rx += buf->len; // Reconstruct UDP response header - char addr_header[512]; + char addr_header[MAX_ADDR_HEADER_SIZE]; int addr_header_len = construct_udprelay_header(&src_addr, addr_header); // Construct packet @@ -1002,7 +1004,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents) */ #ifdef MODULE_REDIR - char addr_header[512] = { 0 }; + char addr_header[MAX_ADDR_HEADER_SIZE] = { 0 }; int addr_header_len = construct_udprelay_header(&dst_addr, addr_header); if (addr_header_len == 0) { @@ -1018,7 +1020,7 @@ server_recv_cb(EV_P_ ev_io *w, int revents) #elif MODULE_TUNNEL - char addr_header[512] = { 0 }; + char addr_header[MAX_ADDR_HEADER_SIZE] = { 0 }; char *host = server_ctx->tunnel_addr.host; char *port = server_ctx->tunnel_addr.port; uint16_t port_num = (uint16_t)atoi(port); @@ -1074,8 +1076,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents) #else - char host[257] = { 0 }; - char port[64] = { 0 }; + char host[MAX_HOSTNAME_LEN] = { 0 }; + char port[MAX_PORT_STR_LEN] = { 0 }; struct sockaddr_storage dst_addr; memset(&dst_addr, 0, sizeof(struct sockaddr_storage)); @@ -1086,7 +1088,6 @@ server_recv_cb(EV_P_ ev_io *w, int revents) goto CLEAN_UP; } - char *addr_header = buf->data + offset; #endif #ifdef MODULE_LOCAL @@ -1198,9 +1199,6 @@ server_recv_cb(EV_P_ ev_io *w, int revents) ev_timer_start(EV_A_ & remote_ctx->watcher); } - remote_ctx->addr_header_len = addr_header_len; - memcpy(remote_ctx->addr_header, addr_header, addr_header_len); - if (offset > 0) { buf->len -= offset; memmove(buf->data, buf->data + offset, buf->len); @@ -1230,6 +1228,8 @@ server_recv_cb(EV_P_ ev_io *w, int revents) int cache_hit = 0; int need_query = 0; + char *addr_header = buf->data + offset; + if (buf->len - addr_header_len > packet_size) { if (verbose) { LOGI("[udp] server_recv_sendto fragmentation, MTU at least be: " SSIZE_FMT, @@ -1267,8 +1267,6 @@ server_recv_cb(EV_P_ ev_io *w, int revents) 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); memcpy(&remote_ctx->dst_addr, &dst_addr, sizeof(struct sockaddr_storage)); } else { ERROR("[udp] bind() error"); diff --git a/src/udprelay.h b/src/udprelay.h index 46e27368..72424918 100644 --- a/src/udprelay.h +++ b/src/udprelay.h @@ -46,6 +46,7 @@ #define PACKET_HEADER_SIZE (1 + 28 + 2 + 64) #define DEFAULT_PACKET_SIZE 1397 // 1492 - PACKET_HEADER_SIZE = 1397, the default MTU for UDP relay +#define MAX_ADDR_HEADER_SIZE (1 + 256 + 2) // 1-byte atyp + 256-byte hostname + 2-byte port typedef struct server_ctx { ev_io io; @@ -71,7 +72,7 @@ typedef struct query_ctx { struct sockaddr_storage src_addr; buffer_t *buf; int addr_header_len; - char addr_header[384]; + char addr_header[MAX_ADDR_HEADER_SIZE]; struct server_ctx *server_ctx; struct remote_ctx *remote_ctx; } query_ctx_t; @@ -82,8 +83,6 @@ typedef struct remote_ctx { ev_timer watcher; int af; int fd; - int addr_header_len; - char addr_header[384]; struct sockaddr_storage src_addr; #ifdef MODULE_REMOTE struct sockaddr_storage dst_addr;