# HG changeset patch # User Matti Hamalainen # Date 1400559348 -10800 # Node ID 399ce077b2a03801ec90a404f900ba7aa2ea3b40 # Parent 1fc22e8efd26bb2efd21893db85c695c65b48941 Factorize more proxy initialization stuff into separate functions. diff -r 1fc22e8efd26 -r 399ce077b2a0 network.c --- a/network.c Tue May 20 06:51:52 2014 +0300 +++ b/network.c Tue May 20 07:15:48 2014 +0300 @@ -240,6 +240,75 @@ } +static int nn_conn_socks4_negotiate(nn_conn_t *conn, const int port, const char *host) +{ + struct nn_socks4_res_t *sockres; + struct nn_socks4_t *socksh; + size_t bufsiz; + uint8_t *ptr, *buf; + + (void) host; + + nn_conn_msg(conn, "Initializing SOCKS 4/a proxy negotiation.\n"); + + bufsiz = sizeof(struct nn_socks4_t) + strlen(conn->proxy.userid) + 1; + if (conn->proxy.type == NN_PROXY_SOCKS4A) + bufsiz += strlen(conn->host) + 1; + + if ((ptr = buf = th_malloc(bufsiz)) == NULL) + { + nn_conn_err(conn, "Could not allocate memory for SOCKS negotiation buffer, %d bytes.\n", bufsiz); + return FALSE; + } + + // Create SOCKS 4 handshake + socksh = (struct nn_socks4_t *) buf; + socksh->version = 4; + socksh->command = NN_PROXY_CMD_CONNECT; + socksh->port = htons(port); + socksh->addr = (conn->proxy.type == NN_PROXY_SOCKS4A) ? htonl(0x00000032) : conn->addr.s_addr; + ptr += sizeof(struct nn_socks4_t); + + strcpy((char *) ptr, conn->proxy.userid); + + if (conn->proxy.type == NN_PROXY_SOCKS4A) + { + ptr += strlen(conn->proxy.userid) + 1; + strcpy((char *)ptr, conn->host); + } + + // Send request + if (!nn_conn_proxy_send(conn, buf, bufsiz)) + return FALSE; + + // Wait for SOCKS server to reply + if (nn_conn_proxy_wait(conn) != 0) + return FALSE; + + sockres = (struct nn_socks4_res_t *) &(conn->buf); + if (sockres->nb != 0) + { + nn_conn_err(conn, "Invalid SOCKS 4 server reply, does not begin with NUL byte (%d).\n", sockres->nb); + return FALSE; + } + if (sockres->result != 0x5a) + { + char *s = NULL; + switch (sockres->result) + { + case 0x5b: s = "Request rejected or failed"; break; + case 0x5c: s = "Request failed because client is not running identd (or not reachable from the server)"; break; + case 0x5d: s = "Request failed because client's identd could not confirm the user ID string in the request"; break; + default: s = "Unknown SOCKS 4 error response"; break; + } + nn_conn_err(conn, "SOCKS 4 setup failed, 0x%02x: %s.\n", sockres->result, s); + return FALSE; + } + + return TRUE; +} + + int nn_conn_open(nn_conn_t *conn, const int port, const char *host) { struct sockaddr_in dest; @@ -261,6 +330,7 @@ if (conn->proxy.type > NN_PROXY_NONE && conn->proxy.type < NN_PROXY_LAST) { + // If using a proxy, we connect to the proxy server dest.sin_port = htons(conn->proxy.port); dest.sin_addr = conn->proxy.addr; @@ -295,71 +365,14 @@ FD_SET(conn->socket, &(conn->sockfds)); // Proxy-specific setup - if (conn->proxy.type == NN_PROXY_SOCKS4 || conn->proxy.type == NN_PROXY_SOCKS4A) + switch (conn->proxy.type) { - struct nn_socks4_res_t *sockres; - struct nn_socks4_t *socksh; - size_t bufsiz; - uint8_t *ptr, *buf; - - nn_conn_msg(conn, "Initializing SOCKS 4/a proxy negotiation.\n"); - - bufsiz = sizeof(struct nn_socks4_t) + strlen(conn->proxy.userid) + 1; - if (conn->proxy.type == NN_PROXY_SOCKS4A) - bufsiz += strlen(conn->host) + 1; - - if ((ptr = buf = th_malloc(bufsiz)) == NULL) - { - conn->err = -1; - nn_conn_err(conn, "Could not allocate memory for SOCKS negotiation buffer, %d bytes.\n", bufsiz); - goto error; - } - - // Create SOCKS 5 handshake - socksh = (struct nn_socks4_t *) buf; - socksh->version = 4; - socksh->command = NN_PROXY_CMD_CONNECT; - socksh->port = htons(port); - socksh->addr = (conn->proxy.type == NN_PROXY_SOCKS4A) ? htonl(0x00000032) : conn->addr.s_addr; - ptr += sizeof(struct nn_socks4_t); - - strcpy((char *) ptr, conn->proxy.userid); - - if (conn->proxy.type == NN_PROXY_SOCKS4A) - { - ptr += strlen(conn->proxy.userid) + 1; - strcpy((char *)ptr, conn->host); - } - - // Send request - if (!nn_conn_proxy_send(conn, buf, bufsiz)) - goto error; - - // Wait for SOCKS server to reply - if (nn_conn_proxy_wait(conn) != 0) - goto error; - - sockres = (struct nn_socks4_res_t *) &(conn->buf); - if (sockres->nb != 0) - { - nn_conn_err(conn, "Invalid SOCKS 4 server reply, does not begin with NUL byte (%d).\n", sockres->nb); - goto error; - } - if (sockres->result != 0x5a) - { - char *s = NULL; - switch (sockres->result) - { - case 0x5b: s = "Request rejected or failed"; break; - case 0x5c: s = "Request failed because client is not running identd (or not reachable from the server)"; break; - case 0x5d: s = "Request failed because client's identd could not confirm the user ID string in the request"; break; - default: s = "Unknown SOCKS 4 error response"; break; - } - nn_conn_err(conn, "SOCKS 4 setup failed, 0x%02x: %s.\n", sockres->result, s); - goto error; - } - - nn_conn_msg(conn, "SOCKS 4 connection established!\n"); + case NN_PROXY_SOCKS4: + case NN_PROXY_SOCKS4A: + if (!nn_conn_socks4_negotiate(conn, port, host)) + goto error; + nn_conn_msg(conn, "SOCKS 4 connection established!\n"); + break; } nn_conn_reset(conn);