diff --git a/include/client.h b/include/client.h index 650f5810..f1a239c6 100644 --- a/include/client.h +++ b/include/client.h @@ -240,6 +240,7 @@ struct LocalUser time_t next_away; /* Don't allow next away before... */ time_t last; + uint32_t connid; /* clients allowed to talk through +g */ rb_dlink_list allow_list; @@ -278,6 +279,7 @@ struct LocalUser struct _ssl_ctl *ssl_ctl; /* which ssl daemon we're associate with */ struct _ssl_ctl *z_ctl; /* second ctl for ssl+zlib */ + uint32_t zconnid; uint32_t localflags; struct ZipStats *zipstats; /* zipstats */ uint16_t cork_count; /* used for corking/uncorking connections */ diff --git a/include/hash.h b/include/hash.h index 6dc2d4e9..d1da309d 100644 --- a/include/hash.h +++ b/include/hash.h @@ -45,8 +45,8 @@ extern struct Dictionary *nd_dict; #define U_MAX_BITS 17 #define U_MAX 131072 /* 2^17 */ -/* Client fd hash table size, used in hash.c */ -#define CLI_FD_MAX 4096 +/* Client connid hash table size, used in hash.c */ +#define CLI_CONNID_MAX 4096 /* Channel hash table size, hash.c/s_debug.c */ #define CH_MAX_BITS 16 @@ -101,9 +101,12 @@ extern void del_from_resv_hash(const char *name, struct ConfItem *aconf); extern struct ConfItem *hash_find_resv(const char *name); extern void clear_resv_hash(void); -void add_to_cli_fd_hash(struct Client *client_p); -void del_from_cli_fd_hash(struct Client *client_p); -struct Client *find_cli_fd_hash(int fd); +void add_to_cli_connid_hash(struct Client *client_p); +void del_from_cli_connid_hash(struct Client *client_p); +struct Client *find_cli_connid_hash(int connid); + +void add_to_zconnid_hash(struct Client *client_p); +void del_from_zconnid_hash(struct Client *client_p); extern void hash_stats(struct Client *); diff --git a/src/client.c b/src/client.c index b5765046..64ab07f1 100644 --- a/src/client.c +++ b/src/client.c @@ -79,6 +79,7 @@ static rb_bh *pclient_heap = NULL; static rb_bh *user_heap = NULL; static rb_bh *away_heap = NULL; static char current_uid[IDLEN]; +static int32_t current_connid = 0; struct Dictionary *nd_dict = NULL; @@ -162,6 +163,17 @@ make_client(struct Client *from) client_p->localClient->F = NULL; + if(current_connid+1 == 0) + current_connid++; + + client_p->localClient->connid = ++current_connid; + + if(current_connid+1 == 0) + current_connid++; + + client_p->localClient->zconnid = ++current_connid; + add_to_cli_connid_hash(client_p); + client_p->preClient = rb_bh_alloc(pclient_heap); /* as good a place as any... */ @@ -220,9 +232,9 @@ free_local_client(struct Client *client_p) client_p->localClient->listener = 0; } + del_from_cli_connid_hash(client_p); if(client_p->localClient->F != NULL) { - del_from_cli_fd_hash(client_p); rb_close(client_p->localClient->F); } @@ -1911,7 +1923,7 @@ close_connection(struct Client *client_p) if(!IsIOError(client_p)) send_queued(client_p); - del_from_cli_fd_hash(client_p); + del_from_cli_connid_hash(client_p); rb_close(client_p->localClient->F); client_p->localClient->F = NULL; } diff --git a/src/hash.c b/src/hash.c index ce57a522..74aa5551 100644 --- a/src/hash.c +++ b/src/hash.c @@ -40,9 +40,13 @@ #include "s_newconf.h" #include "s_assert.h" -#define hash_cli_fd(x) (x % CLI_FD_MAX) +#define ZCONNID_MAX 64 /* i doubt we'll have this many ziplinks ;) */ -static rb_dlink_list clientbyfdTable[U_MAX]; +#define hash_cli_connid(x) (x % CLI_CONNID_MAX) +#define hash_zconnid(x) (x % ZCONNID_MAX) + +static rb_dlink_list clientbyconnidTable[CLI_CONNID_MAX]; +static rb_dlink_list clientbyzconnidTable[ZCONNID_MAX]; rb_dlink_list *clientTable; rb_dlink_list *channelTable; @@ -666,34 +670,60 @@ clear_resv_hash(void) } void -add_to_cli_fd_hash(struct Client *client_p) -{ - rb_dlinkAddAlloc(client_p, &clientbyfdTable[hash_cli_fd(rb_get_fd(client_p->localClient->F))]); -} - - -void -del_from_cli_fd_hash(struct Client *client_p) +add_to_zconnid_hash(struct Client *client_p) { unsigned int hashv; - hashv = hash_cli_fd(rb_get_fd(client_p->localClient->F)); - rb_dlinkFindDestroy(client_p, &clientbyfdTable[hashv]); + hashv = hash_zconnid(client_p->localClient->zconnid); + rb_dlinkAddAlloc(client_p, &clientbyzconnidTable[hashv]); +} + +void +del_from_zconnid_hash(struct Client *client_p) +{ + unsigned int hashv; + hashv = hash_zconnid(client_p->localClient->zconnid); + rb_dlinkFindDestroy(client_p, &clientbyzconnidTable[hashv]); +} + +void +add_to_cli_connid_hash(struct Client *client_p) +{ + unsigned int hashv; + hashv = hash_cli_connid(client_p->localClient->connid); + rb_dlinkAddAlloc(client_p, &clientbyconnidTable[hashv]); +} + +void +del_from_cli_connid_hash(struct Client *client_p) +{ + unsigned int hashv; + hashv = hash_cli_connid(client_p->localClient->connid); + rb_dlinkFindDestroy(client_p, &clientbyconnidTable[hashv]); } struct Client * -find_cli_fd_hash(int fd) +find_cli_connid_hash(int connid) { struct Client *target_p; rb_dlink_node *ptr; unsigned int hashv; - hashv = hash_cli_fd(fd); - RB_DLINK_FOREACH(ptr, clientbyfdTable[hashv].head) + hashv = hash_cli_connid(connid); + RB_DLINK_FOREACH(ptr, clientbyconnidTable[hashv].head) { target_p = ptr->data; - if(rb_get_fd(target_p->localClient->F) == fd) + if(target_p->localClient->connid == connid) return target_p; } - return NULL; + + hashv = hash_zconnid(connid); + RB_DLINK_FOREACH(ptr, clientbyzconnidTable[hashv].head) + { + target_p = ptr->data; + if(target_p->localClient->zconnid == connid) + return target_p; + } + + return NULL; } static void @@ -770,4 +800,6 @@ hash_stats(struct Client *source_p) count_hash(source_p, idTable, U_MAX, "ID"); sendto_one_numeric(source_p, RPL_STATSDEBUG, "B :--"); count_hash(source_p, hostTable, HOST_MAX, "Hostname"); + sendto_one_numeric(source_p, RPL_STATSDEBUG, "B :--"); + count_hash(source_p, clientbyconnidTable, CLI_CONNID_MAX, "Client by connection id"); } diff --git a/src/listener.c b/src/listener.c index c513645e..caea7d39 100644 --- a/src/listener.c +++ b/src/listener.c @@ -464,7 +464,7 @@ close_listeners() * any client list yet. */ static void -add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, struct sockaddr *lai, void *ssl_ctl) +add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, struct sockaddr *lai) { struct Client *new_client; s_assert(NULL != listener); @@ -475,6 +475,24 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, str */ new_client = make_client(NULL); + if (listener->ssl) + { + rb_fde_t *xF[2]; + if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming ssld Connection") == -1) + { + free_client(new_client); + return; + } + new_client->localClient->ssl_ctl = start_ssld_accept(F, xF[1], new_client->localClient->connid); /* this will close F for us */ + if(new_client->localClient->ssl_ctl == NULL) + { + free_client(new_client); + return; + } + F = xF[0]; + SetSSL(new_client); + } + memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage)); memcpy(&new_client->preClient->lip, lai, sizeof(struct rb_sockaddr_storage)); @@ -489,11 +507,7 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, str rb_strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host)); new_client->localClient->F = F; - add_to_cli_fd_hash(new_client); new_client->localClient->listener = listener; - new_client->localClient->ssl_ctl = ssl_ctl; - if(ssl_ctl != NULL || rb_fd_ssl(F)) - SetSSL(new_client); ++listener->ref_count; @@ -577,21 +591,6 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi return 1; } -static void -accept_ssld(rb_fde_t *F, struct sockaddr *addr, struct sockaddr *laddr, struct Listener *listener) -{ - ssl_ctl_t *ctl; - rb_fde_t *xF[2]; - if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming ssld Connection") == -1) - { - ilog_error("creating SSL/TLS socket pairs"); - rb_close(F); - return; - } - ctl = start_ssld_accept(F, xF[1], rb_get_fd(xF[0])); /* this will close F for us */ - add_connection(listener, xF[0], addr, laddr, ctl); -} - static void accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data) { @@ -608,8 +607,5 @@ accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t add return; } - if(listener->ssl) - accept_ssld(F, addr, (struct sockaddr *)&lip, listener); - else - add_connection(listener, F, addr, (struct sockaddr *)&lip, NULL); + add_connection(listener, F, addr, (struct sockaddr *)&lip); } diff --git a/src/s_serv.c b/src/s_serv.c index cf0dd391..cf1a2b66 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -1164,7 +1164,7 @@ serv_connect(struct server_conf *server_p, struct Client *by) rb_strlcpy(client_p->host, server_p->host, sizeof(client_p->host)); rb_strlcpy(client_p->sockhost, server_p->host, sizeof(client_p->sockhost)); client_p->localClient->F = F; - add_to_cli_fd_hash(client_p); + add_to_cli_connid_hash(client_p); /* * Set up the initial server evilness, ripped straight from @@ -1263,9 +1263,9 @@ serv_connect_ssl_callback(rb_fde_t *F, int status, void *data) return; } - del_from_cli_fd_hash(client_p); + del_from_cli_connid_hash(client_p); client_p->localClient->F = xF[0]; - add_to_cli_fd_hash(client_p); + add_to_cli_connid_hash(client_p); client_p->localClient->ssl_ctl = start_ssld_connect(F, xF[1], rb_get_fd(xF[0])); SetSSL(client_p); diff --git a/src/sslproc.c b/src/sslproc.c index 0aec7a3d..31d24fcf 100644 --- a/src/sslproc.c +++ b/src/sslproc.c @@ -365,7 +365,7 @@ ssl_process_dead_fd(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf) fd = buf_to_uint32(&ctl_buf->buf[1]); rb_strlcpy(reason, &ctl_buf->buf[5], sizeof(reason)); - client_p = find_cli_fd_hash(fd); + client_p = find_cli_connid_hash(fd); if(client_p == NULL) return; if(IsAnyServer(client_p) || IsRegistered(client_p)) @@ -401,7 +401,7 @@ ssl_process_cipher_string(ssl_ctl_t *ctl, ssl_ctl_buf_t *ctl_buf) if(EmptyString(cstring)) return; - client_p = find_cli_fd_hash(fd); + client_p = find_cli_connid_hash(fd); if(client_p != NULL && client_p->localClient != NULL) { rb_free(client_p->localClient->cipher_string); @@ -426,7 +426,7 @@ ssl_process_certfp(ssl_ctl_t * ctl, ssl_ctl_buf_t * ctl_buf) fd = buf_to_uint32(&ctl_buf->buf[1]); len = buf_to_uint32(&ctl_buf->buf[5]); certfp = (uint8_t *)&ctl_buf->buf[9]; - client_p = find_cli_fd_hash(fd); + client_p = find_cli_connid_hash(fd); if(client_p == NULL) return; rb_free(client_p->certfp); @@ -821,11 +821,11 @@ start_zlib_session(void *data) F[0] = server->localClient->F; F[1] = xF1; - del_from_cli_fd_hash(server); + del_from_cli_connid_hash(server); server->localClient->F = xF2; /* need to redo as what we did before isn't valid now */ uint32_to_buf(&buf[1], rb_get_fd(server->localClient->F)); - add_to_cli_fd_hash(server); + add_to_cli_connid_hash(server); server->localClient->z_ctl = which_ssld(); server->localClient->z_ctl->cli_count++;