void translate_connect (struct trans_conn *trans) { int s, r; struct SOCKADDR_IN saddr; s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s < 0) { hx_printf_prefix(&hx_htlc, 0, INFOPREFIX, "translate: socket: %s\n", strerror(errno)); return; } trans->s = s; fd_blocking(s, 0); fd_closeonexec(s, 1); saddr.sin_port = htons(80); saddr.sin_family = AFINET; inet_aton(BABELFISH_IPADDRESS, &saddr.sin_addr); r = connect(s, (struct sockaddr *)&saddr, sizeof(saddr)); if (r < 0) { switch (errno) { case EINPROGRESS: break; default: hx_printf_prefix(&hx_htlc, 0, INFOPREFIX, "translate: connect: %s\n", strerror(errno)); trans_close(trans); return; break; } } else { TRANS_TOGGLE(trans, TRANS_FLAG_CONNECTED); } hxd_files[s].ready_read = translate_read; hxd_files[s].ready_write = translate_write; hxd_files[s].conn.ptr = (void *)trans; hxd_fd_add(s); hxd_fd_set(s, FDW); }
static void listen_ready_read (int fd) { int s; struct SOCKADDR_IN saddr; int siz = sizeof(saddr); #ifdef CONFIG_IPV6 char buf[HOSTLEN+1]; #else char buf[16]; #endif struct htlc_conn *htlc; s = accept(fd, (struct SOCKADDR *)&saddr, &siz); if (s < 0) { hxd_log("htls: accept: %s", strerror(errno)); return; } if (s >= hxd_open_max) { hxd_log("%s:%d: %d >= hxd_open_max (%d)", __FILE__, __LINE__, s, hxd_open_max); close(s); return; } fd_closeonexec(s, 1); fd_blocking(s, 0); #ifdef CONFIG_IPV6 inet_ntop(AFINET, (char *)&saddr.SIN_ADDR, buf, sizeof(buf)); #else inet_ntoa_r(saddr.SIN_ADDR, buf, sizeof(buf)); #endif hxd_log("%s:%u -- htlc connection accepted", buf, ntohs(saddr.SIN_PORT)); htlc = xmalloc(sizeof(struct htlc_conn)); memset(htlc, 0, sizeof(struct htlc_conn)); htlc->sockaddr = saddr; hxd_files[s].ready_read = htlc_read; hxd_files[s].ready_write = htlc_write; hxd_files[s].conn.htlc = htlc; htlc->fd = s; htlc->rcv = rcv_magic; htlc->trans = 1; htlc->chattrans = 1; htlc->put_limit = hxd_cfg.limits.individual_uploads > HTXF_PUT_MAX ? HTXF_PUT_MAX : hxd_cfg.limits.individual_uploads; htlc->get_limit = hxd_cfg.limits.individual_downloads > HTXF_GET_MAX ? HTXF_GET_MAX : hxd_cfg.limits.individual_downloads; htlc->limit_out_Bps = hxd_cfg.limits.out_Bps; INITLOCK_HTXF(htlc); if (high_fd < s) high_fd = s; htlc->flags.visible = 1; htlc->identfd = -1; if (check_banlist(htlc)) return; htlc->access_extra.can_login = 1; timer_add_secs(14, login_timeout, htlc); if (hxd_cfg.options.ident) { start_ident(htlc); } else { qbuf_set(&htlc->in, 0, HTLC_MAGIC_LEN); FD_SET(s, &hxd_rfds); } }
void hx_connect (struct htlc_conn *htlc, const char *serverstr, u_int16_t port, const char *name, u_int16_t icon, const char *login, const char *pass, int secure) { int s; struct SOCKADDR_IN saddr; char abuf[HOSTLEN+1]; #if !defined(__WIN32__) if (serverstr[0] == '|' && serverstr[1]) { int pfds[2]; int r; if (htlc->fd) hx_htlc_close(htlc); r = fd_popen(pfds, serverstr+1); if (r < 0) { hx_printf_prefix(htlc, 0, INFOPREFIX, "fd_popen(%s): %s\n", serverstr+1, strerror(errno)); return; } hx_printf_prefix(htlc, 0, INFOPREFIX, "connecting through pipe %s\n", serverstr+1); htlc->fd = pfds[0]; htlc->wfd = pfds[1]; s = htlc->fd; fd_blocking(s, 0); fd_closeonexec(s, 1); hxd_files[s].ready_write = 0; hxd_files[s].ready_read = htlc_read; hxd_files[s].conn.htlc = htlc; hxd_fd_add(s); hxd_fd_set(s, FDR); if (high_fd < s) high_fd = s; s = htlc->wfd; fd_blocking(s, 0); fd_closeonexec(s, 1); hxd_files[s].ready_read = 0; hxd_files[s].ready_write = htlc_write; hxd_files[s].conn.htlc = htlc; hxd_fd_add(s); hxd_fd_set(s, FDW); if (high_fd < s) high_fd = s; goto is_pipe; } #endif #if defined(CONFIG_UNIXSOCKETS) else if (serverstr[0] == '!' && serverstr[1]) { struct sockaddr_un usaddr; s = socket(AF_UNIX, SOCK_STREAM, 0); if (s < 0) { hx_printf_prefix(htlc, 0, INFOPREFIX, "socket: %s\n", strerror(errno)); return; } usaddr.sun_family = AF_UNIX; snprintf(usaddr.sun_path, sizeof(usaddr.sun_path), "%s", serverstr+1); if (htlc->fd) hx_htlc_close(htlc); if (connect(s, (struct sockaddr *)&usaddr, sizeof(usaddr))) { switch (errno) { case EINPROGRESS: break; default: hx_printf_prefix(htlc, 0, INFOPREFIX, "connect: %s\n", strerror(errno)); socket_close(s); return; } } htlc->usockaddr = usaddr; socket_blocking(s, 0); fd_closeonexec(s, 1); goto is_unix; } #endif s = socket(AFINET, SOCK_STREAM, IPPROTO_TCP); if (s < 0) { hx_printf_prefix(htlc, 0, INFOPREFIX, "socket: %s\n", strerror(errno)); return; } if (s >= hxd_open_max) { hx_printf_prefix(htlc, 0, INFOPREFIX, "%s:%d: %d >= hxd_open_max (%d)", __FILE__, __LINE__, s, hxd_open_max); close(s); return; } socket_blocking(s, 0); fd_closeonexec(s, 1); if (hx_hostname[0]) { #ifdef CONFIG_IPV6 if (!inet_pton(AFINET, hx_hostname, &saddr.SIN_ADDR)) { #else if (!inet_aton(hx_hostname, &saddr.SIN_ADDR)) { #endif struct hostent *he; if ((he = gethostbyname(hx_hostname))) { size_t len = (unsigned int)he->h_length > sizeof(struct IN_ADDR) ? sizeof(struct IN_ADDR) : (unsigned int)he->h_length; memcpy(&saddr.SIN_ADDR, he->h_addr, len); } else { #ifndef HAVE_HSTRERROR hx_printf_prefix(htlc, 0, INFOPREFIX, "DNS lookup for %s failed\n", hx_hostname); #else hx_printf_prefix(htlc, 0, INFOPREFIX, "DNS lookup for %s failed: %s\n", hx_hostname, hstrerror(h_errno)); #endif socket_close(s); return; } } saddr.SIN_PORT = 0; saddr.SIN_FAMILY = AFINET; if (bind(s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { inaddr2str(abuf, &saddr); hx_printf_prefix(htlc, 0, INFOPREFIX, "bind %s (%s): %s\n", hx_hostname, abuf, strerror(errno)); socket_close(s); return; } } #ifdef CONFIG_IPV6 if (!inet_pton(AFINET, serverstr, &saddr.SIN_ADDR)) { #else if (!inet_aton(serverstr, &saddr.SIN_ADDR)) { #endif struct hostent *he; if ((he = gethostbyname(serverstr))) { size_t len = (unsigned int)he->h_length > sizeof(struct IN_ADDR) ? sizeof(struct IN_ADDR) : (unsigned int)he->h_length; memcpy(&saddr.SIN_ADDR, he->h_addr, len); } else { #ifndef HAVE_HSTRERROR hx_printf_prefix(htlc, 0, INFOPREFIX, "DNS lookup for %s failed\n", serverstr); #else hx_printf_prefix(htlc, 0, INFOPREFIX, "DNS lookup for %s failed: %s\n", serverstr, hstrerror(h_errno)); #endif socket_close(s); return; } } saddr.SIN_PORT = htons(port); saddr.SIN_FAMILY = AFINET; if (htlc->fd) hx_htlc_close(htlc); if (connect(s, (struct sockaddr *)&saddr, sizeof(saddr))) { #if !defined(__WIN32__) switch (errno) { case EINPROGRESS: break; default: hx_printf_prefix(htlc, 0, INFOPREFIX, "connect: %s\n", strerror(errno)); socket_close(s); return; } #else int wsaerr; wsaerr = WSAGetLastError(); if (wsaerr != WSAEWOULDBLOCK) { hx_printf_prefix(htlc, 0, INFOPREFIX, "connect: WSA error %d\n", wsaerr); socket_close(s); return; } #endif } htlc->sockaddr = saddr; inaddr2str(abuf, &saddr); hx_printf_prefix(htlc, 0, INFOPREFIX, "connecting to %s:%u\n", abuf, ntohs(saddr.SIN_PORT)); is_unix: hxd_files[s].ready_read = htlc_read; hxd_files[s].ready_write = htlc_write_connect; hxd_files[s].conn.htlc = htlc; hxd_fd_add(s); hxd_fd_set(s, FDR|FDW); htlc->fd = s; is_pipe: hx_output.status(); if (name) strlcpy(htlc->name, name, sizeof(htlc->name)); if (icon) htlc->icon = icon; if (login) strlcpy(htlc->login, login, sizeof(htlc->login)); if (pass) strlcpy(htlc->password, pass, sizeof(htlc->password)); else htlc->password[0] = 0; htlc->secure = secure; htlc->flags.in_login = 1; htlc->rcv = hx_rcv_magic; htlc->trans = 1; memset(&htlc->in, 0, sizeof(struct qbuf)); memset(&htlc->out, 0, sizeof(struct qbuf)); qbuf_set(&htlc->in, 0, HTLS_MAGIC_LEN); qbuf_add(&htlc->out, HTLC_MAGIC, HTLC_MAGIC_LEN); } void hx_connect_finish (struct htlc_conn *htlc) { char enclogin[64], encpass[64]; char abuf[HOSTLEN+1]; u_int16_t icon16; u_int16_t llen, plen; int secure; u_int8_t *login, *pass; secure = htlc->secure; login = htlc->login; pass = htlc->password; inaddr2str(abuf, &htlc->sockaddr); #ifdef CONFIG_HOPE if (secure) { #ifdef CONFIG_CIPHER u_int8_t cipheralglist[64]; u_int16_t cipheralglistlen; u_int8_t cipherlen; #endif #ifdef CONFIG_COMPRESS u_int8_t compressalglist[64]; u_int16_t compressalglistlen; u_int8_t compresslen; #endif u_int16_t hc; u_int8_t macalglist[64]; u_int16_t macalglistlen; abuf[0] = 0; task_new(htlc, rcv_task_login, htlc, 0, "login"); strcpy(htlc->macalg, "HMAC-SHA1"); S16HTON(2, macalglist); macalglistlen = 2; macalglist[macalglistlen] = 9; macalglistlen++; memcpy(macalglist+macalglistlen, htlc->macalg, 9); macalglistlen += 9; macalglist[macalglistlen] = 8; macalglistlen++; memcpy(macalglist+macalglistlen, "HMAC-MD5", 8); macalglistlen += 8; hc = 4; #ifdef CONFIG_COMPRESS if (htlc->compressalg[0]) { compresslen = strlen(htlc->compressalg); S16HTON(1, compressalglist); compressalglistlen = 2; compressalglist[compressalglistlen] = compresslen; compressalglistlen++; memcpy(compressalglist+compressalglistlen, htlc->compressalg, compresslen); compressalglistlen += compresslen; hc++; } else compressalglistlen = 0; #endif #ifdef CONFIG_CIPHER if (htlc->cipheralg[0]) { cipherlen = strlen(htlc->cipheralg); S16HTON(1, cipheralglist); cipheralglistlen = 2; cipheralglist[cipheralglistlen] = cipherlen; cipheralglistlen++; memcpy(cipheralglist+cipheralglistlen, htlc->cipheralg, cipherlen); cipheralglistlen += cipherlen; hc++; } else cipheralglistlen = 0; #endif hlwrite(htlc, HTLC_HDR_LOGIN, 0, hc, HTLC_DATA_LOGIN, 1, abuf, HTLC_DATA_PASSWORD, 1, abuf, HTLC_DATA_MAC_ALG, macalglistlen, macalglist, #ifdef CONFIG_CIPHER HTLC_DATA_CIPHER_ALG, cipheralglistlen, cipheralglist, #endif #ifdef CONFIG_COMPRESS HTLC_DATA_COMPRESS_ALG, compressalglistlen, compressalglist, #endif HTLC_DATA_SESSIONKEY, 0, 0); return; } #endif /* HOPE */ task_new(htlc, rcv_task_login, 0, 0, "login"); icon16 = htons(htlc->icon); if (login) { llen = strlen(login); if (llen > 32) llen = 32; hl_encode(enclogin, login, llen); } else llen = 0; htlc->clientversion = g_clientversion; if (htlc->clientversion >= 150) { if (pass) { u_int16_t cv = htons(185); plen = strlen(pass); if (plen > 32) plen = 32; hl_encode(encpass, pass, plen); hlwrite(htlc, HTLC_HDR_LOGIN, 0, 3, HTLC_DATA_LOGIN, llen, enclogin, HTLC_DATA_PASSWORD, plen, encpass, HTLC_DATA_CLIENTVERSION, 2, &cv); } else { u_int16_t cv = htons(185); hlwrite(htlc, HTLC_HDR_LOGIN, 0, 2, HTLC_DATA_LOGIN, llen, enclogin, HTLC_DATA_CLIENTVERSION, 2, &cv); } } else { /* 123 */ if (pass) { plen = strlen(pass); if (plen > 32) plen = 32; hl_encode(encpass, pass, plen); hlwrite(htlc, HTLC_HDR_LOGIN, 0, 4, HTLC_DATA_ICON, 2, &icon16, HTLC_DATA_LOGIN, llen, enclogin, HTLC_DATA_PASSWORD, plen, encpass, HTLC_DATA_NAME, strlen(htlc->name), htlc->name); } else { hlwrite(htlc, HTLC_HDR_LOGIN, 0, 3, HTLC_DATA_ICON, 2, &icon16, HTLC_DATA_LOGIN, llen, enclogin, HTLC_DATA_NAME, strlen(htlc->name), htlc->name); } } memset(htlc->password, 0, sizeof(htlc->password)); }