/* Connect to specified IP address using the correct own_ip. */ GIOChannel *dcc_connect_ip(IPADDR *ip, int port) { IPADDR *own_ip, temp_ip; const char *own_ip_str; GIOChannel *handle; own_ip_str = settings_get_str("dcc_own_ip"); own_ip = NULL; if (*own_ip_str != '\0') { /* use the specified interface for connecting */ net_host2ip(own_ip_str, &temp_ip); if (IPADDR_IS_V6(ip) == IPADDR_IS_V6(&temp_ip)) own_ip = &temp_ip; } if (own_ip == NULL) own_ip = IPADDR_IS_V6(ip) ? source_host_ip6 : source_host_ip4; handle = net_connect_ip(ip, port, own_ip); if (handle == NULL && errno == EADDRNOTAVAIL && own_ip != NULL) { /* dcc_own_ip is external address */ own_ip = IPADDR_IS_V6(ip) ? source_host_ip6 : source_host_ip4; handle = net_connect_ip(ip, port, own_ip); } return handle; }
/* Connect to socket */ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip) { IPADDR ip4, ip6, *ip; int family; g_return_val_if_fail(addr != NULL, NULL); family = my_ip == NULL ? 0 : my_ip->family; if (net_gethostbyname(addr, &ip4, &ip6) == -1) return NULL; if (my_ip == NULL) { /* prefer IPv4 addresses */ ip = ip4.family != 0 ? &ip4 : &ip6; } else if (IPADDR_IS_V6(my_ip)) { /* my_ip is IPv6 address, use it if possible */ if (ip6.family != 0) ip = &ip6; else { my_ip = NULL; ip = &ip4; } } else { /* my_ip is IPv4 address, use it if possible */ if (ip4.family != 0) ip = &ip4; else { my_ip = NULL; ip = &ip6; } } return net_connect_ip(ip, port, my_ip); }
const char *client_get_session_id(struct client *client) { buffer_t *buf, *base64_buf; struct timeval tv; uint64_t timestamp; unsigned int i; if (client->session_id != NULL) return client->session_id; buf = buffer_create_dynamic(pool_datastack_create(), 24); base64_buf = buffer_create_dynamic(pool_datastack_create(), 24*2); if (gettimeofday(&tv, NULL) < 0) i_fatal("gettimeofday(): %m"); timestamp = tv.tv_usec + (long long)tv.tv_sec * 1000ULL*1000ULL; /* add lowest 48 bits of the timestamp. this gives us a bit less than 9 years until it wraps */ for (i = 0; i < 48; i += 8) buffer_append_c(buf, (timestamp >> i) & 0xff); buffer_append_c(buf, client->remote_port & 0xff); buffer_append_c(buf, (client->remote_port >> 16) & 0xff); #ifdef HAVE_IPV6 if (IPADDR_IS_V6(&client->ip)) buffer_append(buf, &client->ip.u.ip6, sizeof(client->ip.u.ip6)); else #endif buffer_append(buf, &client->ip.u.ip4, sizeof(client->ip.u.ip4)); base64_encode(buf->data, buf->used, base64_buf); client->session_id = p_strdup(client->pool, str_c(base64_buf)); return client->session_id; }
static void server_real_connect(SERVER_REC *server, IPADDR *ip, const char *unix_socket) { GIOChannel *handle; IPADDR *own_ip = NULL; const char *errmsg; char *errmsg2; char ipaddr[MAX_IP_LEN]; int port, protonum; g_return_if_fail(ip != NULL || unix_socket != NULL); signal_emit("server connecting", 2, server, ip); if (server->connrec->no_connect) return; if (ip != NULL) { own_ip = IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4; port = server->connrec->proxy != NULL ? server->connrec->proxy_port : server->connrec->port; protonum = server->connrec->use_sctp ? 132 : 0; handle = server->connrec->use_ssl ? net_connect_ip_ssl(ip, port, own_ip, server, protonum) : net_connect_ip(ip, port, own_ip, protonum); } else { handle = net_connect_unix(unix_socket); } if (handle == NULL) { /* failed */ errmsg = g_strerror(errno); errmsg2 = NULL; if (errno == EADDRNOTAVAIL) { if (own_ip != NULL) { /* show the IP which is causing the error */ net_ip2host(own_ip, ipaddr); errmsg2 = g_strconcat(errmsg, ": ", ipaddr, NULL); } server->no_reconnect = TRUE; } if (server->connrec->use_ssl && errno == ENOSYS) server->no_reconnect = TRUE; server->connection_lost = TRUE; server_connect_failed(server, errmsg2 ? errmsg2 : errmsg); g_free(errmsg2); } else { server->handle = net_sendbuffer_create(handle, 0); #ifdef HAVE_OPENSSL if (server->connrec->use_ssl) server_connect_callback_init_ssl(server, handle); else #endif server->connect_tag = g_input_add(handle, G_INPUT_WRITE | G_INPUT_READ, (GInputFunction) server_connect_callback_init, server); } }
/* Start listening for incoming connections */ static GIOChannel *dcc_listen_port(GIOChannel *iface, IPADDR *ip, int port) { if (net_getsockname(iface, ip, NULL) == -1) return NULL; if (IPADDR_IS_V6(ip)) return net_listen(NULL, &port); else return net_listen(&ip4_any, &port); }
/* Start listening for incoming connections */ GIOChannel *dcc_listen(GIOChannel *iface, IPADDR *ip, int *port) { GIOChannel *handle; IPADDR *listen_ip = NULL; const char *dcc_port, *p, *own_ip; int first, last; if (net_getsockname(iface, ip, NULL) == -1) return NULL; /* figure out if we want to listen in IPv4 address or in "any" address, which may mean IPv4+IPv6 or just IPv6 depending on OS. */ own_ip = settings_get_str("dcc_own_ip"); if (*own_ip != '\0') { if (is_ipv4_address(own_ip)) listen_ip = &ip4_any; } else { if (!IPADDR_IS_V6(ip)) listen_ip = &ip4_any; } /* get first port */ dcc_port = settings_get_str("dcc_port"); first = atoi(dcc_port); if (first == 0) { /* random port */ *port = 0; return net_listen(listen_ip, port); } /* get last port */ p = strchr(dcc_port, ' '); if (p == NULL) p = strchr(dcc_port, '-'); dcc_port = p; if (dcc_port == NULL) last = first; else { last = atoi(dcc_port+1); if (last == 0) last = first; } /* use the first available port */ for (*port = first; *port <= last; (*port)++) { handle = net_listen(listen_ip, port); if (handle != NULL) return handle; } return NULL; }
static void server_real_connect(SERVER_REC *server, IPADDR *ip, const char *unix_socket) { GIOChannel *handle; IPADDR *own_ip; int port; g_return_if_fail(ip != NULL || unix_socket != NULL); signal_emit("server connecting", 2, server, ip); if (server->connrec->no_connect) return; if (ip != NULL) { own_ip = ip == NULL ? NULL : (IPADDR_IS_V6(ip) ? server->connrec->own_ip6 : server->connrec->own_ip4); port = server->connrec->proxy != NULL ? server->connrec->proxy_port : server->connrec->port; handle = server->connrec->use_ssl ? net_connect_ip_ssl(ip, port, own_ip, server->connrec->ssl_cert, server->connrec->ssl_pkey, server->connrec->ssl_cafile, server->connrec->ssl_capath, server->connrec->ssl_verify) : net_connect_ip(ip, port, own_ip); } else { handle = net_connect_unix(unix_socket); } if (handle == NULL) { /* failed */ if (errno == EADDRNOTAVAIL || (server->connrec->use_ssl && errno == ENOSYS)) server->no_reconnect = TRUE; server->connection_lost = TRUE; server_connect_failed(server, g_strerror(errno)); } else { server->handle = net_sendbuffer_create(handle, 0); server->connect_tag = g_input_add(handle, G_INPUT_WRITE | G_INPUT_READ, (GInputFunction) server_connect_callback_init, server); } }
void dcc_ip2str(IPADDR *ip, char *host) { IPADDR temp_ip; guint32 addr; if (*settings_get_str("dcc_own_ip") != '\0') { /* overridden IP address */ net_host2ip(settings_get_str("dcc_own_ip"), &temp_ip); ip = &temp_ip; } if (IPADDR_IS_V6(ip)) { /* IPv6 */ net_ip2host(ip, host); } else { memcpy(&addr, &ip->ip, sizeof(addr)); g_snprintf(host, MAX_IP_LEN, "%lu", (unsigned long) htonl(addr)); } }