listener: use exit_client instead of free_client
As well as leaking a connid and leaving the connection open, these calls to free_client() leave the client in the unknown_list causing check_unknowns_list() to crash when either ptr->data (ptr being the freed client_p->localClient->tnode) is NULL or when client_p->localClient is NULL. Flag the client as an IO error so that we don't try to send it any data (as this is not a normal plaintext connection).
This commit is contained in:
parent
4381284e72
commit
50b1e5987c
3 changed files with 45 additions and 41 deletions
|
@ -585,7 +585,6 @@ extern int is_remote_connect(struct Client *);
|
||||||
extern void init_client(void);
|
extern void init_client(void);
|
||||||
extern struct Client *make_client(struct Client *from);
|
extern struct Client *make_client(struct Client *from);
|
||||||
extern void free_pre_client(struct Client *client);
|
extern void free_pre_client(struct Client *client);
|
||||||
extern void free_client(struct Client *client);
|
|
||||||
|
|
||||||
extern int exit_client(struct Client *, struct Client *, struct Client *, const char *);
|
extern int exit_client(struct Client *, struct Client *, struct Client *, const char *);
|
||||||
|
|
||||||
|
|
|
@ -328,7 +328,7 @@ free_local_client(struct Client *client_p)
|
||||||
client_p->localClient = NULL;
|
client_p->localClient = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
free_client(struct Client *client_p)
|
free_client(struct Client *client_p)
|
||||||
{
|
{
|
||||||
s_assert(NULL != client_p);
|
s_assert(NULL != client_p);
|
||||||
|
|
|
@ -457,43 +457,7 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, str
|
||||||
* the client has already been checked out in accept_connection
|
* the client has already been checked out in accept_connection
|
||||||
*/
|
*/
|
||||||
new_client = make_client(NULL);
|
new_client = make_client(NULL);
|
||||||
|
new_client->localClient->F = F;
|
||||||
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_callback = accept_sslcallback;
|
|
||||||
defer = true;
|
|
||||||
new_client->localClient->ssl_ctl = start_ssld_accept(F, xF[1], connid_get(new_client)); /* this will close F for us */
|
|
||||||
if(new_client->localClient->ssl_ctl == NULL)
|
|
||||||
{
|
|
||||||
free_client(new_client);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
F = xF[0];
|
|
||||||
SetSSL(new_client);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listener->wsock)
|
|
||||||
{
|
|
||||||
rb_fde_t *xF[2];
|
|
||||||
if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming wsockd Connection") == -1)
|
|
||||||
{
|
|
||||||
free_client(new_client);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
new_client->localClient->ws_ctl = start_wsockd_accept(F, xF[1], connid_get(new_client)); /* this will close F for us */
|
|
||||||
if(new_client->localClient->ws_ctl == NULL)
|
|
||||||
{
|
|
||||||
free_client(new_client);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
F = xF[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage));
|
memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage));
|
||||||
memcpy(&new_client->preClient->lip, lai, sizeof(struct rb_sockaddr_storage));
|
memcpy(&new_client->preClient->lip, lai, sizeof(struct rb_sockaddr_storage));
|
||||||
|
@ -505,10 +469,51 @@ add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, str
|
||||||
rb_inet_ntop_sock((struct sockaddr *)&new_client->localClient->ip, new_client->sockhost,
|
rb_inet_ntop_sock((struct sockaddr *)&new_client->localClient->ip, new_client->sockhost,
|
||||||
sizeof(new_client->sockhost));
|
sizeof(new_client->sockhost));
|
||||||
|
|
||||||
|
|
||||||
rb_strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));
|
rb_strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));
|
||||||
|
|
||||||
|
if (listener->ssl)
|
||||||
|
{
|
||||||
|
rb_fde_t *xF[2];
|
||||||
|
if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming ssld Connection") == -1)
|
||||||
|
{
|
||||||
|
SetIOError(new_client);
|
||||||
|
exit_client(new_client, new_client, new_client, "Fatal Error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new_client->localClient->ssl_callback = accept_sslcallback;
|
||||||
|
defer = true;
|
||||||
|
new_client->localClient->ssl_ctl = start_ssld_accept(F, xF[1], connid_get(new_client)); /* this will close F for us */
|
||||||
|
if(new_client->localClient->ssl_ctl == NULL)
|
||||||
|
{
|
||||||
|
SetIOError(new_client);
|
||||||
|
exit_client(new_client, new_client, new_client, "Service Unavailable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
F = xF[0];
|
||||||
new_client->localClient->F = F;
|
new_client->localClient->F = F;
|
||||||
|
SetSSL(new_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listener->wsock)
|
||||||
|
{
|
||||||
|
rb_fde_t *xF[2];
|
||||||
|
if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming wsockd Connection") == -1)
|
||||||
|
{
|
||||||
|
SetIOError(new_client);
|
||||||
|
exit_client(new_client, new_client, new_client, "Fatal Error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new_client->localClient->ws_ctl = start_wsockd_accept(F, xF[1], connid_get(new_client)); /* this will close F for us */
|
||||||
|
if(new_client->localClient->ws_ctl == NULL)
|
||||||
|
{
|
||||||
|
SetIOError(new_client);
|
||||||
|
exit_client(new_client, new_client, new_client, "Service Unavailable");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
F = xF[0];
|
||||||
|
new_client->localClient->F = F;
|
||||||
|
}
|
||||||
|
|
||||||
new_client->localClient->listener = listener;
|
new_client->localClient->listener = listener;
|
||||||
|
|
||||||
++listener->ref_count;
|
++listener->ref_count;
|
||||||
|
|
Loading…
Reference in a new issue