diff options
Diffstat (limited to 'blabouncer.c')
-rw-r--r-- | blabouncer.c | 130 |
1 files changed, 65 insertions, 65 deletions
diff --git a/blabouncer.c b/blabouncer.c index 4986551..469eb68 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -85,7 +85,7 @@ void sighandler(int sig) { signum = sig; } -int connecttoircserver(SSL_CTX **serverctx, SSL **server_ssl, int *serversockfd, struct ircdstrings *ircdstrings, struct settings *settings, struct client *clients) { +int connecttoircserver(SSL_CTX **serverctx, SSL **server_ssl, int *serversockfd, struct ircdstate *ircdstate, struct settings *settings, struct client *clients) { char outgoingmsg[MAXDATASIZE]; // String to send to server if (settings->servertls) { @@ -108,31 +108,31 @@ int connecttoircserver(SSL_CTX **serverctx, SSL **server_ssl, int *serversockfd, // <============================================= // Initialise IRC connecting/registration state - // Set ircdstrings to zero-length strings for now - ircdstrings->greeting001[0] = '\0'; - ircdstrings->greeting002[0] = '\0'; - ircdstrings->greeting003[0] = '\0'; - ircdstrings->greeting004[0] = '\0'; - ircdstrings->greeting005a[0] = '\0'; - ircdstrings->greeting005b[0] = '\0'; - ircdstrings->greeting005c[0] = '\0'; - ircdstrings->ircdname[0] = '\0'; - ircdstrings->nickuserhost[0] = '\0'; - ircdstrings->ircnick[0] = '\0'; - ircdstrings->ircusername[0] = '\0'; - ircdstrings->currentmsg[0] = '\0'; - ircdstrings->mode[0] = '\0'; - // ircdstrings->oldnick is not set here as we want to track reconnections separately - // And set non-string things to zero (TODO - Rename this from ircdstrings since it's not all strings any more) - ircdstrings->capmultiprefix = 0; - ircdstrings->autonicknum = 0; - ircdstrings->lastmessagetime = time(NULL); - ircdstrings->timeoutcheck = 0; - // ircdstrings.reconnecting is not set here as we want to track reconnections separately + // Set ircdstate to zero-length strings for now + ircdstate->greeting001[0] = '\0'; + ircdstate->greeting002[0] = '\0'; + ircdstate->greeting003[0] = '\0'; + ircdstate->greeting004[0] = '\0'; + ircdstate->greeting005a[0] = '\0'; + ircdstate->greeting005b[0] = '\0'; + ircdstate->greeting005c[0] = '\0'; + ircdstate->ircdname[0] = '\0'; + ircdstate->nickuserhost[0] = '\0'; + ircdstate->ircnick[0] = '\0'; + ircdstate->ircusername[0] = '\0'; + ircdstate->currentmsg[0] = '\0'; + ircdstate->mode[0] = '\0'; + // ircdstate->oldnick is not set here as we want to track reconnections separately + // And set non-string things to zero + ircdstate->capmultiprefix = 0; + ircdstate->autonicknum = 0; + ircdstate->lastmessagetime = time(NULL); + ircdstate->timeoutcheck = 0; + // ircdstate.reconnecting is not set here as we want to track reconnections separately // Populate nick and username from our configuration file for now, real IRCd may change them later (TODO - Is this true of username?) - strcpy(ircdstrings->ircnick, settings->ircnick); - strcpy(ircdstrings->ircusername, settings->ircusername); + strcpy(ircdstate->ircnick, settings->ircnick); + strcpy(ircdstate->ircusername, settings->ircusername); // Send the server password if one was configured if (settings->ircserverpassword[0]) { @@ -142,12 +142,12 @@ int connecttoircserver(SSL_CTX **serverctx, SSL **server_ssl, int *serversockfd, } // Send our NICK - snprintf(outgoingmsg, MAXDATASIZE, "NICK %s", ircdstrings->ircnick); // TODO - Check for success (with return code) + snprintf(outgoingmsg, MAXDATASIZE, "NICK %s", ircdstate->ircnick); // TODO - Check for success (with return code) // sourcefd = 0 as this is a trusted message sendtoserver(*server_ssl, outgoingmsg, strlen(outgoingmsg), 0, clients, settings); // Send our USER - snprintf(outgoingmsg, MAXDATASIZE, "USER %s 8 * : %s", ircdstrings->ircusername, settings->ircrealname); // TODO - Check for success (with return code) + snprintf(outgoingmsg, MAXDATASIZE, "USER %s 8 * : %s", ircdstate->ircusername, settings->ircrealname); // TODO - Check for success (with return code) // TODO - Send a more intelligent/correct USER string // sourcefd = 0 as this is a trusted message sendtoserver(*server_ssl, outgoingmsg, strlen(outgoingmsg), 0, clients, settings); @@ -171,7 +171,7 @@ int connecttoircserver(SSL_CTX **serverctx, SSL **server_ssl, int *serversockfd, // Return 1 if we processed something and expect the caller to not need to do anything more // Return 0 if we didn't process it and the caller might want to do something //int processircmessage(int *serversockfd, int *clientsockfd, char *str, int source) { -int processircmessage(SSL *server_ssl, char *str, int source, struct client *clients, int sourcefd, struct ircdstrings *ircdstrings, struct channel *channels, struct settings *settings) { +int processircmessage(SSL *server_ssl, char *str, int source, struct client *clients, int sourcefd, struct ircdstate *ircdstate, struct channel *channels, struct settings *settings) { // Track which space-separated token within this response we're on int counter = 0; @@ -201,7 +201,7 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli switch(source) { case SOURCE_SERVER: // If message(s) were from the real IRC server - if (processservermessage(server_ssl, str, clients, sourcefd, ircdstrings, channels, settings, tokens, counter)) { + if (processservermessage(server_ssl, str, clients, sourcefd, ircdstate, channels, settings, tokens, counter)) { // We processed something so return true free(strcopyPtr); return 1; @@ -210,7 +210,7 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli // Don't return if we got here because this means we didn't process something in processservermessage() break; case SOURCE_CLIENT: // If message(s) were from a real IRC client - if (processclientmessage(server_ssl, str, clients, sourcefd, ircdstrings, channels, settings, tokens, counter)) { + if (processclientmessage(server_ssl, str, clients, sourcefd, ircdstate, channels, settings, tokens, counter)) { // We processed something so return true free(strcopyPtr); return 1; @@ -249,7 +249,7 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli // // Return 0 if something went wrong // Return 1 if everything OK -int processrawstring(SSL *server_ssl, char *str, int source, struct client *clients, int sourcefd, struct ircdstrings *ircdstrings, struct channel *channels, struct settings *settings) { +int processrawstring(SSL *server_ssl, char *str, int source, struct client *clients, int sourcefd, struct ircdstate *ircdstate, struct channel *channels, struct settings *settings) { // Copy to a temporary string so we still have the original in case it's not processed char *strcopy = strdup(str); // Keep track of initial pointer for free()ing later @@ -279,14 +279,14 @@ int processrawstring(SSL *server_ssl, char *str, int source, struct client *clie // If there is a previous possibly truncated message still in the holding area, the prepend that to the first message of this new lot // (Only if source was the server since we always strip \r\n from client messages when recving - TODO - Should we be doing that? - if (ircdstrings->currentmsg[0] && source == SOURCE_SERVER) { + if (ircdstate->currentmsg[0] && source == SOURCE_SERVER) { // Make a copy since we can't have source and destination the same with snprintf char *strtmp = strdup(messages[0]); - debugprint(DEBUG_FULL, "processrawstring(): Previous truncated message detected, combining old '%s' with new '%s'...\n", ircdstrings->currentmsg, strtmp); - snprintf(messages[0], strlen(ircdstrings->currentmsg) + strlen(strtmp) + 1, "%s%s", ircdstrings->currentmsg, strtmp); - messages[0][strlen(ircdstrings->currentmsg) + strlen(strtmp)] = '\0'; // Make sure it's null terminated + debugprint(DEBUG_FULL, "processrawstring(): Previous truncated message detected, combining old '%s' with new '%s'...\n", ircdstate->currentmsg, strtmp); + snprintf(messages[0], strlen(ircdstate->currentmsg) + strlen(strtmp) + 1, "%s%s", ircdstate->currentmsg, strtmp); + messages[0][strlen(ircdstate->currentmsg) + strlen(strtmp)] = '\0'; // Make sure it's null terminated debugprint(DEBUG_FULL, "...into new string '%s' and clearing currentmsg holding area.\n", messages[0]); - ircdstrings->currentmsg[0] = '\0'; + ircdstate->currentmsg[0] = '\0'; free(strtmp); } @@ -295,20 +295,20 @@ int processrawstring(SSL *server_ssl, char *str, int source, struct client *clie // (Only if source was the server since we always strip \r\n from client messages when recving - TODO - Should we be doing that? if ((str[strlen(str)-2] != 13 || str[strlen(str)-1] != 10) && source == SOURCE_SERVER) { debugprint(DEBUG_FULL, "processrawstring(): Truncated message detected, storing final token '%s' for later.\n", messages[messagecount - 1]); - strncpy(ircdstrings->currentmsg, messages[messagecount - 1], strlen(messages[messagecount - 1])); - ircdstrings->currentmsg[strlen(messages[messagecount - 1])] = '\0'; + strncpy(ircdstate->currentmsg, messages[messagecount - 1], strlen(messages[messagecount - 1])); + ircdstate->currentmsg[strlen(messages[messagecount - 1])] = '\0'; // Remove it from the message count so it's not processed time time messagecount--; } else { // Otherwise, clear the holding area - ircdstrings->currentmsg[0] = '\0'; + ircdstate->currentmsg[0] = '\0'; } // Go through each message, figure out what it is and if we're doing anything with it for (int i = 0; i < messagecount; i++) { // Copy to a temporary string so we still have the original in case it's not processed char *messagecopy = strdup(messages[i]); - if (processircmessage(server_ssl, messagecopy, source, clients, sourcefd, ircdstrings, channels, settings)) { + if (processircmessage(server_ssl, messagecopy, source, clients, sourcefd, ircdstate, channels, settings)) { debugprint(DEBUG_FULL, "Message processed: \"%s\", NULLing...\n", messages[i]); messages[i][0] = '\0'; } @@ -386,7 +386,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { // Struct of various strings from and for the real IRCd (such as the greeting strings, the real IRCd's name, // our nick!user@host string, our nick, username, real name, etc.) - struct ircdstrings ircdstrings; + struct ircdstate ircdstate; // Struct of channels we're in struct channel *channels; @@ -404,9 +404,9 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { SSL *server_ssl = NULL; // Need to create this either way as referenced later // Set reconnection things to null/zero for now (not used unless reconnecting to server) - ircdstrings.oldnick[0] = '\0'; - ircdstrings.reconnecting = 0; - connecttoircserver(&serverctx, &server_ssl, serversockfd, &ircdstrings, settings, clients); + ircdstate.oldnick[0] = '\0'; + ircdstate.reconnecting = 0; + connecttoircserver(&serverctx, &server_ssl, serversockfd, &ircdstate, settings, clients); // OpenSSL context for client side (that clients connect to) (need to create this whether or not using TLS as it is referenced later) SSL_CTX *ctx; @@ -461,11 +461,11 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { // Signal caught, do signal handling debugprint(DEBUG_CRIT, "signal '%d' happened, exiting!\n", signum); if (signum == SIGINT) { - cleanexit(server_ssl, clients, 0, &ircdstrings, settings, "SIGINT received"); + cleanexit(server_ssl, clients, 0, &ircdstate, settings, "SIGINT received"); } else if (signum == SIGTERM) { - cleanexit(server_ssl, clients, 0, &ircdstrings, settings, "SIGTERM received"); + cleanexit(server_ssl, clients, 0, &ircdstate, settings, "SIGTERM received"); } else { - cleanexit(server_ssl, clients, 0, &ircdstrings, settings, "Unexpected signal received"); + cleanexit(server_ssl, clients, 0, &ircdstate, settings, "Unexpected signal received"); } } else { // Some other error @@ -480,13 +480,13 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { debugprint(DEBUG_CRIT, "pselect() timed out.\n", errno); // SERVERTIMEOUT seconds have expired... - if (ircdstrings.lastmessagetime < time(NULL) - SERVERTIMEOUT && !FD_ISSET(*serversockfd, &rfds)) { - if (ircdstrings.timeoutcheck == 0) { + if (ircdstate.lastmessagetime < time(NULL) - SERVERTIMEOUT && !FD_ISSET(*serversockfd, &rfds)) { + if (ircdstate.timeoutcheck == 0) { // ...and we haven't tried a PING yet, so let's PING the server to see if things are still working - debugprint(DEBUG_CRIT, "Server might have timed out after %ld seconds, PINGing it...\n", time(NULL) - ircdstrings.lastmessagetime); - ircdstrings.timeoutcheck = 1; + debugprint(DEBUG_CRIT, "Server might have timed out after %ld seconds, PINGing it...\n", time(NULL) - ircdstate.lastmessagetime); + ircdstate.timeoutcheck = 1; char outgoingmsg[MAXDATASIZE]; - if (!snprintf(outgoingmsg, MAXDATASIZE, "PING %s", ircdstrings.ircdname)) { + if (!snprintf(outgoingmsg, MAXDATASIZE, "PING %s", ircdstate.ircdname)) { fprintf(stderr, "Error while preparing timeout testing PING message!\n"); debugprint(DEBUG_CRIT, "Error while preparing timeout testing PING message\n"); snprintf(outgoingmsg, MAXDATASIZE, "PING timeouttest"); @@ -495,10 +495,10 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { } else { // ...and we've already PINGed the server and haven't heard back yet, so let's assume we've timed out // TODO - Code duplication, make a function and share with socket error code below - debugprint(DEBUG_CRIT, "Server has timed out (%ld seconds), reconnecting!\n", time(NULL) - ircdstrings.lastmessagetime); + debugprint(DEBUG_CRIT, "Server has timed out (%ld seconds), reconnecting!\n", time(NULL) - ircdstate.lastmessagetime); // Tell all clients if we timed out char alertmsg[MAXDATASIZE]; - snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :Server has timed out (%ld seconds), reconnecting!", ircdstrings.ircnick, time(NULL) - ircdstrings.lastmessagetime); + snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :Server has timed out (%ld seconds), reconnecting!", ircdstate.ircnick, time(NULL) - ircdstate.lastmessagetime); sendtoallclients(clients, alertmsg, 0, settings); if (settings->servertls) { // Finish up with OpenSSL if using server TLS @@ -510,10 +510,10 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { *serversockfd = createserversocket(settings->ircserver, settings->ircserverport); // Set reconnection marker for other functions to know we're reconnecting - ircdstrings.reconnecting = 1; + ircdstate.reconnecting = 1; // Set oldnick in case we change nick when reconnecting so we can inform existing clients - strcpy(ircdstrings.oldnick, ircdstrings.ircnick); - connecttoircserver(&serverctx, &server_ssl, serversockfd, &ircdstrings, settings, clients); + strcpy(ircdstate.oldnick, ircdstate.ircnick); + connecttoircserver(&serverctx, &server_ssl, serversockfd, &ircdstate, settings, clients); } // Back to top of loop continue; @@ -546,7 +546,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { printf("Server socket had an error (sockread return code %d), reconnecting!\n", servernumbytes); // Tell all clients if we timed out char alertmsg[MAXDATASIZE]; - snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :Server socket had an error (sockread return code %d), reconnecting!", ircdstrings.ircnick, servernumbytes); + snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :Server socket had an error (sockread return code %d), reconnecting!", ircdstate.ircnick, servernumbytes); sendtoallclients(clients, alertmsg, 0, settings); if (settings->servertls) { // Finish up with OpenSSL if using server TLS @@ -558,10 +558,10 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { *serversockfd = createserversocket(settings->ircserver, settings->ircserverport); // Set reconnection marker for other functions to know we're reconnecting - ircdstrings.reconnecting = 1; + ircdstate.reconnecting = 1; // Set oldnick in case we change nick when reconnecting so we can inform existing clients - strcpy(ircdstrings.oldnick, ircdstrings.ircnick); - connecttoircserver(&serverctx, &server_ssl, serversockfd, &ircdstrings, settings, clients); + strcpy(ircdstate.oldnick, ircdstate.ircnick); + connecttoircserver(&serverctx, &server_ssl, serversockfd, &ircdstate, settings, clients); // Back to top of loop continue; @@ -573,7 +573,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { // Try to process received string (which should contain one or more server responses/commands) // TODO - What if there were two server respones/commands and only one didn't need relaying? - if (!processrawstring(server_ssl, serverbuf, SOURCE_SERVER, clients, EXCEPT_NONE, &ircdstrings, channels, settings)) { + if (!processrawstring(server_ssl, serverbuf, SOURCE_SERVER, clients, EXCEPT_NONE, &ircdstate, channels, settings)) { fprintf(stderr, "Error: bouncer-server failed to process raw string.\n"); debugprint(DEBUG_CRIT, "Error: bouncer-server failed to process raw string.\n"); } @@ -638,7 +638,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { if (numclients(clients) >= MAXCLIENTS) { fprintf(stderr, "too many clients, disconnecting and skipping loop iteration!\n"); debugprint(DEBUG_CRIT, "too many clients, disconnecting and skipping loop iteration!\n"); - disconnectclient(i, clients, &ircdstrings, settings); + disconnectclient(i, clients, &ircdstate, settings); continue; } addrlen = sizeof remoteaddr; @@ -681,7 +681,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { remoteIP, INET6_ADDRSTRLEN), newfd); // Alert other clients about the new connection char alertmsg[MAXDATASIZE]; - if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client connected from %s with fd %d.", ircdstrings.ircnick, + if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client connected from %s with fd %d.", ircdstate.ircnick, inet_ntop(remoteaddr.ss_family, get_in_addr((struct sockaddr*)&remoteaddr), remoteIP, INET6_ADDRSTRLEN), newfd)) { fprintf(stderr, "Error while preparing new client connection NOTICE!\n"); debugprint(DEBUG_CRIT, "Error while preparing new client connection NOTICE!\n"); @@ -704,7 +704,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { debugprint(DEBUG_CRIT, "bouncer-client: socket error, clientnum bytes '%d', errno '%d'.\n", clientnumbytes, errno); } // Disconnect the client - disconnectclient(i, clients, &ircdstrings, settings); + disconnectclient(i, clients, &ircdstate, settings); FD_CLR(i, &rfds); // remove from master set - TODO is this needed at the moment since we just add everything from *clientsockfd to fdmax to rfds // TODO - Handle the "remove the client" loop not finding the old fd debugprint(DEBUG_FULL, "bouncer-client: total client connections: %d\n", numclients(clients)); @@ -720,7 +720,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { // Try to process received string (which should contain one or more client responses/commands) // TODO - What if there were two server respones/commands and only one didn't need relaying? - if (!processrawstring(server_ssl, clientbuf, SOURCE_CLIENT, clients, i, &ircdstrings, channels, settings)) { + if (!processrawstring(server_ssl, clientbuf, SOURCE_CLIENT, clients, i, &ircdstate, channels, settings)) { fprintf(stderr, "Error: bouncer-client failed to process raw string.\n"); debugprint(DEBUG_CRIT, "Error: bouncer-client failed to process raw string.\n"); } |