Browse Source

fix some weird data corruptions caused by optimized memcpy

pull/4/merge
Max Lv 12 years ago
parent
commit
db6b156808
4 changed files with 43 additions and 25 deletions
  1. 41
      src/local.c
  2. 19
      src/server.c
  3. 7
      src/utils.c
  4. 1
      src/utils.h

41
src/local.c

@ -63,10 +63,11 @@ int create_and_bind(const char *port) {
continue; continue;
int opt = 1; int opt = 1;
int err = setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if (err) {
ERROR("setsocket");
}
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
setsockopt(listen_sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen); s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) { if (s == 0) {
@ -141,7 +142,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
} }
} else if(s < r) { } else if(s < r) {
remote->buf_len = r - s; remote->buf_len = r - s;
memcpy(remote->buf, remote->buf + s, remote->buf_len);
bufcpy(remote->buf, remote->buf + s, remote->buf_len);
ev_io_stop(EV_A_ &server_recv_ctx->io); ev_io_stop(EV_A_ &server_recv_ctx->io);
ev_io_start(EV_A_ &remote->send_ctx->io); ev_io_start(EV_A_ &remote->send_ctx->io);
return; return;
@ -179,14 +180,14 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
if (request->atyp == 1) { if (request->atyp == 1) {
// IP V4 // IP V4
size_t in_addr_len = sizeof(struct in_addr); size_t in_addr_len = sizeof(struct in_addr);
memcpy(addr_to_send + addr_len, remote->buf + 4, in_addr_len + 2);
bufcpy(addr_to_send + addr_len, remote->buf + 4, in_addr_len + 2);
addr_len += in_addr_len + 2; addr_len += in_addr_len + 2;
} else if (request->atyp == 3) { } else if (request->atyp == 3) {
// Domain name // Domain name
uint8_t name_len = *(uint8_t *)(remote->buf + 4); uint8_t name_len = *(uint8_t *)(remote->buf + 4);
addr_to_send[addr_len++] = name_len; addr_to_send[addr_len++] = name_len;
memcpy(addr_to_send + addr_len, remote->buf + 4 + 1, name_len);
bufcpy(addr_to_send + addr_len, remote->buf + 4 + 1, name_len);
addr_len += name_len; addr_len += name_len;
// get port // get port
@ -196,7 +197,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
} else if (request->atyp == 4) { } else if (request->atyp == 4) {
// IP V6 // IP V6
size_t in6_addr_len = sizeof(struct in6_addr); size_t in6_addr_len = sizeof(struct in6_addr);
memcpy(addr_to_send + addr_len, remote->buf + 4, in6_addr_len + 2);
bufcpy(addr_to_send + addr_len, remote->buf + 4, in6_addr_len + 2);
addr_len += in6_addr_len + 2; addr_len += in6_addr_len + 2;
} else { } else {
@ -225,10 +226,10 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
struct in_addr sin_addr; struct in_addr sin_addr;
inet_aton("0.0.0.0", &sin_addr); inet_aton("0.0.0.0", &sin_addr);
memcpy(server->buf, &response, 4);
memset(server->buf + 4, 0, sizeof(struct in_addr) + sizeof(uint16_t));
bufcpy(server->buf, &response, sizeof(struct socks5_response));
memset(server->buf + sizeof(struct socks5_response), 0, sizeof(struct in_addr) + sizeof(uint16_t));
int reply_size = 4 + sizeof(struct in_addr) + sizeof(uint16_t);
int reply_size = sizeof(struct socks5_response) + sizeof(struct in_addr) + sizeof(uint16_t);
s = send(server->fd, server->buf, reply_size, 0); s = send(server->fd, server->buf, reply_size, 0);
if (s < reply_size) { if (s < reply_size) {
LOGE("failed to send fake reply."); LOGE("failed to send fake reply.");
@ -238,6 +239,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
} }
server->stage = 5; server->stage = 5;
ev_io_start(EV_A_ &remote->recv_ctx->io);
} }
} }
@ -264,7 +266,7 @@ static void server_send_cb (EV_P_ ev_io *w, int revents) {
} else if (s < server->buf_len) { } else if (s < server->buf_len) {
// partly sent, move memory, wait for the next time to send // partly sent, move memory, wait for the next time to send
server->buf_len -= s; server->buf_len -= s;
memcpy(server->buf, server->buf + s, server->buf_len);
bufcpy(server->buf, server->buf + s, server->buf_len);
return; return;
} else { } else {
// all sent out, wait for reading // all sent out, wait for reading
@ -349,7 +351,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) {
} }
} else if (s < r) { } else if (s < r) {
server->buf_len = r - s; server->buf_len = r - s;
memcpy(server->buf, server->buf + s, server->buf_len);
bufcpy(server->buf, server->buf + s, server->buf_len);
ev_io_stop(EV_A_ &remote_recv_ctx->io); ev_io_stop(EV_A_ &remote_recv_ctx->io);
ev_io_start(EV_A_ &server->send_ctx->io); ev_io_start(EV_A_ &server->send_ctx->io);
return; return;
@ -371,7 +373,6 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) {
ev_io_stop(EV_A_ &remote_send_ctx->io); ev_io_stop(EV_A_ &remote_send_ctx->io);
ev_timer_stop(EV_A_ &remote_send_ctx->watcher); ev_timer_stop(EV_A_ &remote_send_ctx->watcher);
ev_io_start(EV_A_ &server->recv_ctx->io); ev_io_start(EV_A_ &server->recv_ctx->io);
ev_io_start(EV_A_ &remote->recv_ctx->io);
return; return;
} else { } else {
ERROR("getpeername"); ERROR("getpeername");
@ -401,7 +402,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) {
} else if (s < remote->buf_len) { } else if (s < remote->buf_len) {
// partly sent, move memory, wait for the next time to send // partly sent, move memory, wait for the next time to send
remote->buf_len -= s; remote->buf_len -= s;
memcpy(remote->buf, remote->buf + s, remote->buf_len);
bufcpy(remote->buf, remote->buf + s, remote->buf_len);
return; return;
} else { } else {
// all sent out, wait for reading // all sent out, wait for reading
@ -515,6 +516,11 @@ static void accept_cb (EV_P_ ev_io *w, int revents) {
return; return;
} }
setnonblocking(serverfd); setnonblocking(serverfd);
int opt = 1;
setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
setsockopt(serverfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
struct addrinfo hints, *res; struct addrinfo hints, *res;
int sockfd; int sockfd;
@ -536,6 +542,11 @@ static void accept_cb (EV_P_ ev_io *w, int revents) {
return; return;
} }
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
#ifdef SO_NOSIGPIPE
setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif
struct timeval timeout; struct timeval timeout;
timeout.tv_sec = listener->timeout; timeout.tv_sec = listener->timeout;
timeout.tv_usec = 0; timeout.tv_usec = 0;

19
src/server.c

@ -72,7 +72,6 @@ int create_and_bind(const char *host, const char *port) {
setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt)); setsockopt(listen_sock, SOL_SOCKET, SO_NOSIGPIPE, &opt, sizeof(opt));
#endif #endif
s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen); s = bind(listen_sock, rp->ai_addr, rp->ai_addrlen);
if (s == 0) { if (s == 0) {
/* We managed to bind successfully! */ /* We managed to bind successfully! */
@ -173,7 +172,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
} }
} else if (s < r) { } else if (s < r) {
remote->buf_len = r - s; remote->buf_len = r - s;
memcpy(remote->buf, remote->buf + s, remote->buf_len);
bufcpy(remote->buf, remote->buf + s, remote->buf_len);
ev_io_stop(EV_A_ &server_recv_ctx->io); ev_io_stop(EV_A_ &server_recv_ctx->io);
ev_io_start(EV_A_ &remote->send_ctx->io); ev_io_start(EV_A_ &remote->send_ctx->io);
} }
@ -203,14 +202,14 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
size_t in_addr_len = sizeof(struct in_addr); size_t in_addr_len = sizeof(struct in_addr);
if (r > in_addr_len) { if (r > in_addr_len) {
char *a = inet_ntoa(*(struct in_addr*)(server->buf + offset)); char *a = inet_ntoa(*(struct in_addr*)(server->buf + offset));
memcpy(host, a, strlen(a));
bufcpy(host, a, strlen(a));
offset += in_addr_len; offset += in_addr_len;
} }
} else if (atyp == 3) { } else if (atyp == 3) {
// Domain name // Domain name
uint8_t name_len = *(uint8_t *)(server->buf + offset); uint8_t name_len = *(uint8_t *)(server->buf + offset);
memcpy(host, server->buf + offset + 1, name_len);
bufcpy(host, server->buf + offset + 1, name_len);
offset += name_len + 1; offset += name_len + 1;
} else if (atyp == 4) { } else if (atyp == 4) {
@ -220,7 +219,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
char a[INET6_ADDRSTRLEN]; char a[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, (const void*)(server->buf + offset), inet_ntop(AF_INET6, (const void*)(server->buf + offset),
a, sizeof(a)); a, sizeof(a));
memcpy(host, a, strlen(a));
bufcpy(host, a, strlen(a));
offset += in6_addr_len; offset += in6_addr_len;
} }
@ -258,7 +257,7 @@ static void server_recv_cb (EV_P_ ev_io *w, int revents) {
// XXX: should handel buffer carefully // XXX: should handel buffer carefully
if (r > offset) { if (r > offset) {
server->buf_len = r - offset; server->buf_len = r - offset;
memcpy(server->buf, server->buf + offset, server->buf_len);
bufcpy(server->buf, server->buf + offset, server->buf_len);
} }
server->stage = 4; server->stage = 4;
@ -306,7 +305,7 @@ static void server_send_cb (EV_P_ ev_io *w, int revents) {
} else if (s < server->buf_len) { } else if (s < server->buf_len) {
// partly sent, move memory, wait for the next time to send // partly sent, move memory, wait for the next time to send
server->buf_len -= s; server->buf_len -= s;
memcpy(server->buf, server->buf + s, server->buf_len);
bufcpy(server->buf, server->buf + s, server->buf_len);
return; return;
} else { } else {
// all sent out, wait for reading // all sent out, wait for reading
@ -396,7 +395,7 @@ static void server_resolve_cb(EV_P_ ev_timer *watcher, int revents) {
// XXX: should handel buffer carefully // XXX: should handel buffer carefully
if (server->buf_len > 0) { if (server->buf_len > 0) {
memcpy(remote->buf, server->buf, server->buf_len);
bufcpy(remote->buf, server->buf, server->buf_len);
remote->buf_len = server->buf_len; remote->buf_len = server->buf_len;
server->buf_len = 0; server->buf_len = 0;
} }
@ -473,7 +472,7 @@ static void remote_recv_cb (EV_P_ ev_io *w, int revents) {
return; return;
} else if (s < r) { } else if (s < r) {
server->buf_len = r - s; server->buf_len = r - s;
memcpy(server->buf, server->buf + s, server->buf_len);
bufcpy(server->buf, server->buf + s, server->buf_len);
ev_io_stop(EV_A_ &remote_recv_ctx->io); ev_io_stop(EV_A_ &remote_recv_ctx->io);
ev_io_start(EV_A_ &server->send_ctx->io); ev_io_start(EV_A_ &server->send_ctx->io);
return; return;
@ -543,7 +542,7 @@ static void remote_send_cb (EV_P_ ev_io *w, int revents) {
} else if (s < remote->buf_len) { } else if (s < remote->buf_len) {
// partly sent, move memory, wait for the next time to send // partly sent, move memory, wait for the next time to send
remote->buf_len -= s; remote->buf_len -= s;
memcpy(remote->buf, remote->buf + s, remote->buf_len);
bufcpy(remote->buf, remote->buf + s, remote->buf_len);
return; return;
} else { } else {
// all sent out, wait for reading // all sent out, wait for reading

7
src/utils.c

@ -22,6 +22,13 @@ void ERROR(const char *s) {
} }
void bufcpy(char *dest, const char *src, size_t n) {
int i;
for (i = 0; i < n; i++) {
*dest++ = *src++;
}
}
char *itoa(int i) { char *itoa(int i) {
/* Room for INT_DIGITS digits, - and '\0' */ /* Room for INT_DIGITS digits, - and '\0' */
static char buf[INT_DIGITS + 2]; static char buf[INT_DIGITS + 2];

1
src/utils.h

@ -24,5 +24,6 @@ void ERROR(const char *s);
void usage(void); void usage(void);
void demonize(const char* path); void demonize(const char* path);
char *itoa(int i); char *itoa(int i);
void bufcpy(char *dest, const char *src, size_t n);
#endif // _UTILS_H #endif // _UTILS_H
Loading…
Cancel
Save