diff options
Diffstat (limited to 'blabouncer.c')
-rw-r--r-- | blabouncer.c | 89 |
1 files changed, 61 insertions, 28 deletions
diff --git a/blabouncer.c b/blabouncer.c index 1ca16ea..f7e38a1 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -292,7 +292,8 @@ int disconnectclient(int fd, struct client *clients, struct ircdstrings *ircdstr char alertmsg[MAXDATASIZE]; if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: client with fd %d has disconnected.", ircdstrings->ircnick, fd)) { fprintf(stderr, "Error while preparing authentication failure NOTICE!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing authentication failure NOTICE!\n"); + alertmsg[0] = '\0'; } // Remove the client from the clients array for (int i = 0; i < MAXCLIENTS; i++) { @@ -545,7 +546,7 @@ int doreplay(int sourcefd, int replayseconds, struct client *clients, struct set for (int j = 0; j < 3; j++) { // Try to split if ((token = strsep(&strcopy, " ")) == NULL) { - debugprint(DEBUG_CRIT, "doreplay(): error splitting string on iteration '%d', exiting!\n", j); + debugprint(DEBUG_CRIT, "doreplay(): error splitting string on iteration '%d', returning!\n", j); return 0; } // Copy into the token array (strlen + 1 to get the NULL terminator) @@ -629,6 +630,7 @@ int joinautochannels(SSL *server_ssl, struct client *clients, struct settings *s strncpy(tokens[counter], token, strlen(token) + 1); if (strlen(tokens[counter]) > MAXCHANLENGTH) { printf("error: channel name '%s' from configuration file too long, max length is '%d'.\n", tokens[counter], MAXCHANLENGTH); + debugprint(DEBUG_CRIT, "error: channel name '%s' from configuration file too long, max length is '%d'.\n", tokens[counter], MAXCHANLENGTH); exit(1); } counter++; @@ -657,6 +659,7 @@ void tryautonick(struct ircdstrings *ircdstrings) { if (ircdstrings->autonicknum == 10) { // We've already tried 9 nicks and failed, give up printf("tryautonick(): Tried 9 automatic nicks and the server didn't like any, giving up.\n"); + debugprint(DEBUG_CRIT, "tryautonick(): Tried 9 automatic nicks and the server didn't like any, giving up.\n"); exit(1); } @@ -812,7 +815,8 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli char outgoingmsg[MAXDATASIZE]; // String to send to server if (!snprintf(outgoingmsg, MAXDATASIZE, "PONG %s", tokens[1])) { // TODO - Make sure tokens[1] actually has a token fprintf(stderr, "Error while preparing PONG response!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing PONG response!\n"); + outgoingmsg[0] = '\0'; } // sourcefd = 0 as this is a trusted response sendtoserver(server_ssl, outgoingmsg, strlen(outgoingmsg), 0, clients, settings); @@ -837,6 +841,7 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli // Prepend a colon (:) first since everything (so far) needs one if (!snprintf(ircdstrings->nickuserhost, MAXDATASIZE, ":%s", tokens[counter - 1])) { fprintf(stderr, "Error while preparing nickuserhost for storage!\n"); + debugprint(DEBUG_CRIT, "Error while preparing nickuserhost for storage!\n"); exit(1); } // Null the end of the new string @@ -1545,7 +1550,8 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli char alertmsg[MAXDATASIZE]; if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client with fd %d has successfully authenticated.", ircdstrings->ircnick, sourcefd)) { fprintf(stderr, "Error while preparing authentication success NOTICE!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing authentication success NOTICE!\n"); + alertmsg[0] = '\0'; } // "except" the current fd - we can use this as "except/sourcefd" since we set them as authed just above sendtoallclients(clients, alertmsg, sourcefd, settings); @@ -1558,7 +1564,8 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli char alertmsg[MAXDATASIZE]; if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client with fd %d has failed to authenticate.", ircdstrings->ircnick, sourcefd)) { fprintf(stderr, "Error while preparing authentication failure NOTICE!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing authentication failure NOTICE!\n"); + alertmsg[0] = '\0'; } // "except" 0 since we trust this message sendtoallclients(clients, alertmsg, 0, settings); @@ -1586,7 +1593,8 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli if (strncasecmp(tokens[1], "LS", strlen(tokens[1])) == 0) { if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s CAP * LS :multi-prefix", ircdstrings->ircdname)) { fprintf(stderr, "Error while preparing CAP LS response!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing CAP LS response!\n"); + outgoingmsg[0] = '\0'; } // ...even if unauthenticated sendtoclient(sourcefd, outgoingmsg, clients, settings, 1); @@ -1598,7 +1606,8 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli if (strncasecmp(tokens[2], ":multi-prefix", strlen(tokens[2])) == 0) { if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s CAP %s ACK :multi-prefix ", ircdstrings->ircdname, ircdstrings->ircnick)) { fprintf(stderr, "Error while preparing CAP ACK response!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing CAP ACK response!\n"); + outgoingmsg[0] = '\0'; } // ...even if unauthenticated sendtoclient(sourcefd, outgoingmsg, clients, settings, 1); @@ -1691,7 +1700,9 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli // Get client to join channels if (!snprintf(outgoingmsg, MAXDATASIZE, "%s JOIN :%s", ircdstrings->nickuserhost, channels[i].name)) { fprintf(stderr, "Error while preparing USER just connected, channel JOIN responses!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing USER just connected, channel JOIN responses!\n"); + free(strcopyPtr); + return 0; } sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); @@ -1701,7 +1712,9 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli // Prepare the no topic message... if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 331 %s %s :No topic is set.", ircdstrings->ircdname, ircdstrings->ircnick, channels[i].name)) { fprintf(stderr, "Error while preparing USER just connected, channel JOIN responses, 331 RPL_NOTOPIC!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing USER just connected, channel JOIN responses, 331 RPL_NOTOPIC!\n"); + free(strcopyPtr); + return 0; } // ..and send it to the client sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); @@ -1710,7 +1723,9 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli // Prepare the topic message... if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 332 %s %s :%s", ircdstrings->ircdname, ircdstrings->ircnick, channels[i].name, channels[i].topic)) { fprintf(stderr, "Error while preparing USER just connected, channel JOIN responses, 332 RPL_TOPIC!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing USER just connected, channel JOIN responses, 332 RPL_TOPIC!\n"); + free(strcopyPtr); + return 0; } // ..and send it to the client sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); @@ -1718,7 +1733,9 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli // Next prepare the topic who/when message... if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 333 %s %s %s %s", ircdstrings->ircdname, ircdstrings->ircnick, channels[i].name, channels[i].topicwho, channels[i].topicwhen)) { fprintf(stderr, "Error while preparing USER just connected, channel JOIN responses, 333 RPL_TOPICWHOTIME!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing USER just connected, channel JOIN responses, 333 RPL_TOPICWHOTIME!\n"); + free(strcopyPtr); + return 0; } // ..and send it to the client sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); @@ -1734,7 +1751,9 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli if (strlen(ircdstrings->mode) > 0) { if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s MODE %s %s", ircdstrings->ircnick, ircdstrings->ircnick, ircdstrings->mode)) { fprintf(stderr, "Error while preparing USER just connected, MODE response!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing USER just connected, MODE response!\n"); + free(strcopyPtr); + return 0; } sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); } @@ -1767,7 +1786,8 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli char outgoingmsg[MAXDATASIZE]; // String to send to client if (!snprintf(outgoingmsg, MAXDATASIZE, "PONG %s", tokens[1])) { // TODO - Make sure tokens[1] actually has a token fprintf(stderr, "Error while preparing PONG response!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing PONG response!\n"); + outgoingmsg[0] = '\0'; } sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); @@ -1809,7 +1829,9 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli if (!snprintf(outgoingmsg, MAXDATASIZE, "%s %s", ircdstrings->nickuserhost, str)) { fprintf(stderr, "Error while preparing PRIVMSG relay from another bouncer client.\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing PRIVMSG relay from another bouncer client.\n"); + free(strcopyPtr); + return 0; } // Send to all except source client sendtoallclients(clients, outgoingmsg, sourcefd, settings); @@ -1929,7 +1951,9 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli if (!snprintf(fullmsg, MAXDATASIZE, "%s %s", ircdstrings->nickuserhost, str)) { fprintf(stderr, "Error while preparing NOTICE string for logging.\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing NOTICE string for logging.\n"); + free(strcopyPtr); + return 0; } // Write to replay log if replay logging enabled @@ -2005,7 +2029,8 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli debugprint(DEBUG_SOME, "Invalid number '%s' requested by REPLAY command. Telling client.\n", timetokens[i]); if (!snprintf(outgoingmsg, MAXDATASIZE, "NOTICE %s :Invalid number '%s' requested by REPLAY command.", ircdstrings->ircnick, timetokens[i])) { fprintf(stderr, "Error while preparing REPLAY invalid number response!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing REPLAY invalid number response!\n"); + outgoingmsg[0] = '\0'; } sendtoclient(sourcefd, outgoingmsg, clients, settings, 0); free(timestrcopyPtr); @@ -2083,7 +2108,9 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli break; default: fprintf(stderr, "Unexpected raw IRC string source!\n"); - exit(1); + debugprint(DEBUG_CRIT, "Unexpected raw IRC string source!\n"); + free(strcopyPtr); + return 0; } // =============================================> @@ -2198,7 +2225,8 @@ int processrawstring(SSL *server_ssl, char *str, int source, struct client *clie break; default: fprintf(stderr, "Unexpected raw IRC string source for unprocessed message \"%s\", length %zd.!\n", messages[i], strlen(messages[i])); - exit(1); + debugprint(DEBUG_CRIT, "Unexpected raw IRC string source for unprocessed message \"%s\", length %zd.!\n", messages[i], strlen(messages[i])); + return 0; } } } @@ -2326,8 +2354,9 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { debugprint(DEBUG_FULL, "select()ing...\n"); // check to see if anything in the fd_set is waiting - waits here until one of the fds in the set does something if (select(fdmax + 1, &rfds, NULL, NULL, NULL) < 0) { // network socket + 1, rfds, no writes, no exceptions/errors, no timeout - printf("receive error, exiting!?\n"); perror("select"); + debugprint(DEBUG_CRIT, "select() error, errno '%d'.\n", errno); + continue; } // TODO - switch around the serversockfd and STDIN FD_ISSET if-statements? They feel the wrong way round. Are they like this on purpose? I can't remember. @@ -2338,13 +2367,14 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { debugprint(DEBUG_FULL, "reading server socket!\n"); if ((servernumbytes = sockread(server_ssl, serverbuf, MAXRCVSIZE - 1, settings->servertls)) == -1) { - printf("receive error (-1), exiting...\n"); perror("recv"); - debugprint(DEBUG_CRIT, "serversockfd receive error (-1), errno '%d'.\n"); + printf("receive error (-1), skipping loop iteration...\n"); + debugprint(DEBUG_CRIT, "serversockfd receive error (-1), skipping loop iteration, errno '%d'.\n"); + continue; } else if (servernumbytes == 0) { - printf("socket closed (or no data received) (0), exiting...\n"); perror("recv"); - debugprint(DEBUG_CRIT, "serversockfd socket closed (or no data received) (0), errno '%d'.\n"); + printf("socket closed (or no data received) (0), skipping loop iteration...\n"); + debugprint(DEBUG_CRIT, "serversockfd socket closed (or no data received) (0), skipping loop iteration, errno '%d'.\n"); } // If there was a socket error (receive error or socket closed) @@ -2382,7 +2412,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { // 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)) { fprintf(stderr, "Error: bouncer-server failed to process raw string.\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error: bouncer-server failed to process raw string.\n"); } } @@ -2443,8 +2473,10 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { debugprint(DEBUG_SOME, "...new connection!\n"); // handle new connections if (numclients(clients) >= MAXCLIENTS) { - fprintf(stderr, "too many clients!\n"); - exit(1); // TODO - handle cleanly instead of exiting! + 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); + continue; } addrlen = sizeof remoteaddr; newfd = accept(*clientsockfd, (struct sockaddr *)&remoteaddr, &addrlen); @@ -2489,7 +2521,8 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { if (!snprintf(alertmsg, MAXDATASIZE, "NOTICE %s :blabouncer: new client connected from %s with fd %d.", ircdstrings.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"); - exit(1); + debugprint(DEBUG_CRIT, "Error while preparing new client connection NOTICE!\n"); + alertmsg[0] = '\0'; } // "except" 0 since we trust this message sendtoallclients(clients, alertmsg, 0, settings); @@ -2526,7 +2559,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) { // 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)) { fprintf(stderr, "Error: bouncer-client failed to process raw string.\n"); - exit(1); + debugprint(DEBUG_CRIT, "Error: bouncer-client failed to process raw string.\n"); } } } |