/** Send a byte on socket <b>fd</b>t. Return 0 on success or EAGAIN, * -1 on error. */ static int sock_alert(tor_socket_t fd) { ssize_t r = send_ni(fd, "x", 1, 0); if (r < 0 && !ERRNO_IS_EAGAIN(tor_socket_errno(fd))) return -1; return 0; }
static int socks5_connect(wsocks_ctx_t *wc, const struct sockaddr *serv_addr, socklen_t addrlen) { wsocks_prot_socks5_t *wp; struct sockaddr_in *serv_addr_in; unsigned char buf[4096]; unsigned char *ptr; int slen, retval; wp = WSOCKS_PROT_SOCKS5_PTR(wc->prot); serv_addr_in = (struct sockaddr_in *)serv_addr; /* get the auth method */ dprintf("get AUTH method\n"); buf[0] = 0x05; buf[1] = wp->auth ? 2 : 1; buf[2] = 0x00; buf[3] = 0x02; /* set it no harm */ slen = wp->auth ? 4 : 3; ptr = buf; while(slen > 0){ retval = send_ni(wc->fd, ptr, slen, 0); if(retval <= 0){ goto err; } ptr += retval; slen -= retval; } slen = 2; ptr = buf; while(slen > 0){ retval = recv_ni(wc->fd, ptr, slen, 0); if(retval <= 0){ goto err; } slen -= retval; ptr += retval; } if (buf[0] != 0x05) goto err; /* send user and password if needed */ if (buf[1] == 0x02) { if (!wp->auth) goto err; dprintf("send USER and PASSWORD\n"); slen = wp->auth_len; ptr = (unsigned char*)wp->auth; while(slen > 0){ retval = send_ni(wc->fd, ptr, slen, 0); if(retval <= 0){ goto err; } ptr += retval; slen -= retval; } slen = 2; ptr = buf; while(slen > 0){ retval = recv_ni(wc->fd, ptr, slen, 0); if(retval <= 0){ goto err; } slen -= retval; ptr += retval; } if (buf[0] != 0x05 || buf[1] != 0x00) goto err; } else if (buf[1] != 0x00) goto err; /* send CONNECT command */ dprintf("send CONNECT command\n"); memcpy(buf, "\x05\x01\x00\x01", 4); *(u_int32_t*)&buf[4] = serv_addr_in->sin_addr.s_addr; *(u_int16_t*)&buf[8] = serv_addr_in->sin_port; slen = 10; ptr = buf; while(slen > 0){ retval = send_ni(wc->fd, ptr, slen, 0); if(retval <= 0){ goto err; } ptr += retval; slen -= retval; } /* parse the reply */ dprintf("get the reply.\n"); ptr = buf; slen = 10; while(slen > 0){ retval = recv_ni(wc->fd, ptr, slen, 0); if(retval <= 0){ goto err; } slen -= retval; ptr += retval; } if (memcmp(buf, "\x05\x00\x00\x01", 4) != 0) goto err; wc->local.sin_family = AF_INET; wc->local.sin_addr.s_addr = *(u_int32_t*)&buf[4]; wc->local.sin_port = *(u_int16_t*)&buf[8]; wc->state |= WSOCKS_STATE_BINDED; retval = 0; done: return retval; err: errno = ECONNREFUSED; retval = -1; goto done; }