diff options
| -rw-r--r-- | TODO | 2 | ||||
| -rw-r--r-- | blabouncer.c | 105 | 
2 files changed, 84 insertions, 23 deletions
@@ -1,7 +1,5 @@  Move debug output into some debug function that can be enabled/disabled. -Automatically try new nicks if there's no more configured nicks to try (e.g. if foo is in use, try foo1, foo2, etc.) -  Add various auto replay options:   - All logs since the final client disconnected   - All logs since the most recent client connect/disconnect diff --git a/blabouncer.c b/blabouncer.c index 07bee1a..e837977 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -47,6 +47,7 @@  #define MAXCHANLENGTH 50 // 50 according to RFC 2811 and RFC 2822  #define MAXCHANUSERS 8192 // Randomly picked (TODO - is there an actual maximum number of users per channel?)  #define MAXNICKLENGTH 64 // Randomly picked (TODO - is there an actual maximum number (ignoring the RFC preference of 9)?) +#define MAXRFCNICKLEN 9 // From RFC 1459  #define MAXUSERNAMELEN 64 // Randomly picked (TODO - is there an actual maximum username length?)  #define MAXREALNAMELEN 128 // Randomly picked (TODO - is there an actual maximum real name length?)  #define MAXPORTLEN 6 // Up to 65535, so 5 characters + 1 for null @@ -77,6 +78,7 @@ struct ircdstrings {    char currentmsg[MAXDATASIZE]; // Holding area for the current server-received IRC message being processed in case it needs building across multiple reads (i.e. a truncated/split message)    char mode[MAXDATASIZE];    int capmultiprefix; // Whether the server approved our CAP multi-prefix request +  int autonicknum; // Number of attempts made at automatically setting a nick if all configured nicks were in use  };  // Structure of settings either to be read from the configuration file or set/changed at runtime @@ -627,6 +629,46 @@ int joinautochannels(SSL *server_ssl, struct client *clients, struct settings *s    return 1;  } +// Try to make a new nick if no configured are available or liked by the server +// Do this by sticking a number on the end of the current nick and trying numbers +// 1 through to 9. +void tryautonick(struct ircdstrings *ircdstrings) { +  // Increment the attempts counter +  ircdstrings->autonicknum++; + +  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"); +    exit(1); +  } + +  int oldlen = strlen(ircdstrings->ircnick); + +  // If we've already started trying autonick, just replace the last character a the new number +  if (ircdstrings->autonicknum > 1) { +    printf("tryautonick(): already started autonick, starting with '%s' length '%ld'.\n", ircdstrings->ircnick, strlen(ircdstrings->ircnick)); +    ircdstrings->ircnick[oldlen - 1] = ircdstrings->autonicknum + '0'; +    // And null terminate +    ircdstrings->ircnick[oldlen] = '\0'; +  // If the nick is longer than or equal to the RFC 1459 max nick +  // length then try sticking the number at the end +  } else if (oldlen >= MAXRFCNICKLEN) { +    printf("tryautonick(): long old nick, starting with '%s' length '%ld'.\n", ircdstrings->ircnick, strlen(ircdstrings->ircnick)); +    // (+ '0' to make char from int) +    ircdstrings->ircnick[MAXRFCNICKLEN] = ircdstrings->autonicknum + '0'; +    // And null terminate +    ircdstrings->ircnick[MAXRFCNICKLEN + 1] = '\0'; +  // Otherwise, just stick it on the end (+ '0' to make char from int) +  } else { +    printf("tryautonick(): short old nick, starting with '%s' length '%ld'.\n", ircdstrings->ircnick, strlen(ircdstrings->ircnick)); +    ircdstrings->ircnick[oldlen] = ircdstrings->autonicknum + '0'; +    // And null terminate +    ircdstrings->ircnick[oldlen + 1] = '\0'; +  } + +  printf("tryautonick(): set irdstrings->ircnick to '%s'.\n", ircdstrings->ircnick); +} +  // Figure out what to do with each CRLF-split IRC message (if anything)  // by splitting out the different components by space character (ASCII 0x20).  // @@ -1226,32 +1268,52 @@ int processircmessage(SSL *server_ssl, char *str, int source, struct client *cli          if ((strncmp(tokens[1], "432", strlen(tokens[1])) == 0 || strncmp(tokens[1], "433", strlen(tokens[1])) == 0) && !strlen(ircdstrings->greeting004)) {            printf("Server 432 (ERR_ERRONEUSNICKNAME) or 433 (ERR_NICKNAMEINUSE) found and it is: %s with length %zd!  Trying another nick...\n", tokens[1], strlen(tokens[1])); -          // Make sure nick3 hasn't already been tried -          if (getconfstr("nick3", settings->conffile, settings->ircnick)) { -            // If it's the current nick already then... -            if (strncmp(ircdstrings->ircnick, settings->ircnick, strlen(settings->ircnick)) == 0) { -              // ...give up -              printf("error: server doesn't like any configured nicks, giving up.\n"); -              exit(1); -            } +          // Try to get nick2 and nick3 from the configuration file +          char nick2[MAXNICKLENGTH]; +          char nick3[MAXNICKLENGTH]; +          if (!getconfstr("nick2", settings->conffile, nick2)) { +            nick2[0] = '\0';            } - -          // Try nick2 -          if (!getconfstr("nick2", settings->conffile, settings->ircnick)) { -            printf("error: server doesn't like nick and can't get 'nick2' from configuration file.\n"); -            exit(1); +          if (!getconfstr("nick3", settings->conffile, nick3)) { +            nick3[0] = '\0';            } -          // Have we already tried this one?  (i.e. is it the current nick) -          if (strncmp(ircdstrings->ircnick, settings->ircnick, strlen(settings->ircnick)) == 0) { -            // Then try nick3 -            if (!getconfstr("nick3", settings->conffile, settings->ircnick)) { -              printf("error: server doesn't like nick or nick2 and can't get 'nick3' from configuration file.\n"); -              exit(1); + +          // Do we have both a nick2 and a nick3?  (And not tried autonick yet.) +          if (nick2[0] && nick3[0] && !ircdstrings->autonicknum) { +            // Has nick3 already been tried? +            if (strncmp(ircdstrings->ircnick, nick3, strlen(settings->ircnick)) == 0) { +              // Then try autonick +              tryautonick(ircdstrings); +            // Has nick2 already been tried? +            } else if (strncmp(ircdstrings->ircnick, nick2, strlen(settings->ircnick)) == 0) { +              // Then try nick3 +              printf("Trying nick3, nick2 was already tried.\n"); +              strcpy(ircdstrings->ircnick, nick3); +            // Have neither been tried? +            } else { +              // Then try nick2 +              printf("Trying nick2, nick3 is also configured.\n"); +              strcpy(ircdstrings->ircnick, nick2); +            } +          // Do we only have a nick2?  (And not tried autonick yet.) +          } else if (nick2[0] && !ircdstrings->autonicknum) { +            // Has it already been tried? +            if (strncmp(ircdstrings->ircnick, nick2, strlen(settings->ircnick)) == 0) { +              // Then try autonick +              tryautonick(ircdstrings); +            } else { +              // Then try it +              printf("Trying nick2, nick3 is not configured.\n"); +              strcpy(ircdstrings->ircnick, nick2);              } +          // Do we have neither?  (Or have already started autonick.) +          } else { +            // Then try autonick +              tryautonick(ircdstrings);            } -          // Set whichever one we settled on as the current nick -          strcpy(ircdstrings->ircnick, settings->ircnick); +          // Set whichever one we settled on in the settings in case we reference settings later +          strcpy(settings->ircnick, ircdstrings->ircnick);            // Try it with the server            char outgoingmsg[MAXDATASIZE]; @@ -1922,6 +1984,7 @@ void dochat(int *serversockfd, int *clientsockfd, struct settings *settings) {    ircdstrings.mode[0] = '\0';    // 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;    // 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);  | 
