diff options
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | blabouncer.c | 53 | ||||
| -rw-r--r-- | blabouncer.conf | 9 | ||||
| -rw-r--r-- | config.c | 103 | ||||
| -rw-r--r-- | config.h | 12 | 
5 files changed, 158 insertions, 25 deletions
| @@ -1,8 +1,8 @@  CC=gcc -DEPS = functions.h sockets.h +DEPS = functions.h sockets.h config.h  %.o: %.c $(DEPS)  	$(CC) -Wall -Wextra -c -o $@ $< -blabouncer: blabouncer.o functions.o sockets.o -	$(CC) -Wall -Wextra -o blabouncer blabouncer.o functions.o sockets.o +blabouncer: blabouncer.o functions.o sockets.o config.o +	$(CC) -Wall -Wextra -o blabouncer blabouncer.o functions.o sockets.o config.o diff --git a/blabouncer.c b/blabouncer.c index 80d6940..ba9dca0 100644 --- a/blabouncer.c +++ b/blabouncer.c @@ -8,6 +8,7 @@  // - Add blabouncer MOTD (375, 372, 376)  // - "01:53:47 -!- ServerMode/#test [b] by irc.tghost.co.uk" on existing clients when new client connects  // - Keep track of changing user nicks/modes +// - Relay log can just be "log/resend everything that ever hit sendto[all]client[s]()"  //  // Example WHOIS reply:  // BOUNCER-SERVER RECEIVED: :irc.tghost.co.uk 307 blabounce l_bratch :is identified for this nick @@ -30,6 +31,7 @@  #include "functions.h"  #include "sockets.h" +#include "config.h"  #define SOURCE_SERVER 0  #define SOURCE_CLIENT 1 @@ -44,10 +46,8 @@  #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 IRCNICK "blabounce" // TODO: change this to a config option! -#define IRCUSER "blabounce" // TODO: change this to a config option! -#define IRCREALNAME "Mr Bla Bouncer" // TODO: change this to a config option! +#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?)  struct channel {    char name[MAXCHANLENGTH]; @@ -68,6 +68,9 @@ struct ircdstrings {    char greeting004[MAXDATASIZE];    char ircdname[MAXDATASIZE];    char nickuserhost[MAXDATASIZE]; // TODO - Make sure this changes when nick changes, if that's meant to happen. +  char ircnick[MAXNICKLENGTH]; // TODO - Make sure this changes when nick changes +  char ircusername[MAXUSERNAMELEN]; +  char ircrealname[MAXREALNAMELEN];  };  int debugmode = 0; @@ -589,7 +592,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc            // If there isn't one set (we guess this if topic timestamp is 0), send 331 RPL_NOTOPIC            if (strncmp(channels[i].topicwhen, "0", 1) == 0) {              // Prepare the no topic message... -            if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 331 %s %s :No topic is set.", ircdstrings->ircdname, IRCNICK, channels[i].name)) { +            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);              } @@ -598,7 +601,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc            // If there is one set, send 332 RPL_TOPIC and 333 RPL_TOPICWHOTIME            } else {              // Prepare the topic message... -            if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 332 %s %s :%s", ircdstrings->ircdname, IRCNICK, channels[i].name, channels[i].topic)) { +            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);              } @@ -606,7 +609,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc              sendtoclient(sourcefd, outgoingmsg);              // Next prepare the topic who/when message... -            if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 333 %s %s %s %s", ircdstrings->ircdname, IRCNICK, channels[i].name, channels[i].topicwho, channels[i].topicwhen)) { +            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);              } @@ -627,7 +630,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc                continue;              }              // If there was a nick found, send it to the client (one per line at the moment - TODO - batch them up into fewer lines) -            if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 353 %s %s %s :%s", ircdstrings->ircdname, IRCNICK, channels[i].namestype, channels[i].name, channels[i].nicks[j])) { +            if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 353 %s %s %s :%s", ircdstrings->ircdname, ircdstrings->ircnick, channels[i].namestype, channels[i].name, channels[i].nicks[j])) {                fprintf(stderr, "Error while preparing USER just connected, channel NAMES responses!\n");                exit(1);              } @@ -635,7 +638,7 @@ int processircmessage(int *serversockfd, int *clientsockfd, char *str, int sourc            }            // Once all names are sent, send the "end of /NAMES" 366 (RPL_ENDOFNAMES) message -          if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 366 %s %s :End of /NAMES list.", ircdstrings->ircdname, IRCNICK, channels[i].name)) { +          if (!snprintf(outgoingmsg, MAXDATASIZE, ":%s 366 %s %s :End of /NAMES list.", ircdstrings->ircdname, ircdstrings->ircnick, channels[i].name)) {              fprintf(stderr, "Error while preparing USER just connected, end of NAMES response!\n");              exit(1);            } @@ -852,29 +855,35 @@ void dochat(int *serversockfd, int *clientsockfd) {    // Registered with the IRCd yet?  //////////////  int registered = 0; +  // 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; +  // Set them to zero-length strings for now +  ircdstrings.greeting001[0] = '\0'; +  ircdstrings.greeting002[0] = '\0'; +  ircdstrings.greeting003[0] = '\0'; +  ircdstrings.greeting004[0] = '\0'; +  ircdstrings.ircdname[0] = '\0'; +  ircdstrings.nickuserhost[0] = '\0'; +  ircdstrings.ircnick[0] = '\0'; +  ircdstrings.ircusername[0] = '\0'; +  ircdstrings.ircrealname[0] = '\0'; + +  // Read required things from configuration file +  readnames(ircdstrings.ircnick, ircdstrings.ircusername, ircdstrings.ircrealname); +    // Send our NICK -  snprintf(outgoingmsg, MAXDATASIZE, "NICK %s", IRCNICK); // TODO - Check for success (with return code) +  snprintf(outgoingmsg, MAXDATASIZE, "NICK %s", ircdstrings.ircnick); // TODO - Check for success (with return code)    sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg));    // Send our USER -  snprintf(outgoingmsg, MAXDATASIZE, "USER %s 8 * : %s", IRCUSER, IRCREALNAME); // TODO - Check for success (with return code) +  snprintf(outgoingmsg, MAXDATASIZE, "USER %s 8 * : %s", ircdstrings.ircusername, ircdstrings.ircrealname); // TODO - Check for success (with return code)                                                                                  // TODO - Send a more intelligent/correct USER string    sendtoserver(serversockfd, outgoingmsg, strlen(outgoingmsg));    // Struct of channels we're in    struct channel *channels;    channels = malloc(sizeof(struct channel) * MAXCHANNELS); - -  // Struct of various strings from the real IRCd (such as the greeting strings, the real IRCd's name, our nick!user@host string, etc.) -  struct ircdstrings ircdstrings; -  // Set them to zero-length strings for now -  ircdstrings.greeting001[0] = '\0'; -  ircdstrings.greeting002[0] = '\0'; -  ircdstrings.greeting003[0] = '\0'; -  ircdstrings.greeting004[0] = '\0'; -  ircdstrings.ircdname[0] = '\0'; -  ircdstrings.nickuserhost[0] = '\0'; -    // =============================================>    while (1) { diff --git a/blabouncer.conf b/blabouncer.conf new file mode 100644 index 0000000..4f569dd --- /dev/null +++ b/blabouncer.conf @@ -0,0 +1,9 @@ +# blabouncer configuration file +# Entries must be in the form: +# option name, space, equals sign, space, double quote, option value, double quote +# e.g. +# realname = "Mr Bla Bouncer" + +nick = "blabounce" +username = "blabounce" +realname = "Mr Bla Bouncer" diff --git a/config.c b/config.c new file mode 100644 index 0000000..ca6b158 --- /dev/null +++ b/config.c @@ -0,0 +1,103 @@ +#include "config.h" + +// Check to see if a line is the configuration option specified by +// checking to see if str starts with conf followed by a space, a tab, +// or an equals sign. +// Returns the length of the name of the requested option if found, or +// zero if not. +long int isconf(char *str, char *conf) { +  char *ret; +  char substr[MAXCHAR]; +  long int len = strlen(conf); + +  // Ensure the next character is an equals sign, a space, or a tab +  if (str[len] != '=' && str[len] != ' ' && str[len] != ' ') { +    return 0; +  } + +  strncpy(substr, str, len); +  substr[len] = '\0'; + + +  if (!(ret = strstr(substr, conf)) == 0) { +    return len; +  } + +  return 0; +} + +// Extracts the value of a configuration option from a string.  Expects +// to receive the string and the number of characters long that the +// configuration option name is. +void getconf(char *str, long int start) { +  long int len = strlen(str); +  long int pos; +  char conf[MAXCHAR]; + +  for (long int i = start; i < len; i++) { +    if (str[i] == '=' || str[i] == ' ' || str[i] == ' ') { +      continue; +    } else { +      pos = i; +      break; +    } +  } + +  strncpy(conf, str + pos, len - pos - 1); // Copy remainder to new string and lop off the newline +  conf[len - pos - 1] = '\0'; // Null terminate + +   // Check for start and end quotes +  if (conf[0] != '"' || conf[strlen(conf) - 1] != '"') { +    printf("Error reading configuration option, not enclosed in double quotes!\n"); +    exit(1); +  } + +  strncpy(str, conf + 1, strlen(conf) - 2); // Copy result back to original string without quotes +  str[strlen(conf) - 2] = '\0'; // Null terminate +} + +int readnames(char *nick, char *username, char *realname) { +  FILE *fp; +  char str[MAXCHAR]; +  char* filename = "blabouncer.conf"; + +  // Set all strings to zero-length to begin +  nick[0] = '\0'; +  username[0] = '\0'; +  realname[0] = '\0'; + +  fp = fopen(filename, "r"); + +  if (fp == NULL) { +    printf("error: could not open configuration file '%s.'", filename); +    return 1; +  } +  while (fgets(str, MAXCHAR, fp) != NULL) { +    long int len; +    if ((len = isconf(str, "nick"))) { +      getconf(str, len); +      strncpy(nick, str, strlen(str)); +      nick[strlen(str)] = '\0'; +      printf("Nick is: '%s', length '%ld'.\n", nick, strlen(nick)); +    } else if ((len = isconf(str, "username"))) { +      getconf(str, len); +      strncpy(username, str, strlen(str)); +      username[strlen(str)] = '\0'; +      printf("Username is: '%s', length '%ld'.\n", username, strlen(username)); +    } else if ((len = isconf(str, "realname"))) { +      getconf(str, len); +      strncpy(realname, str, strlen(str)); +      realname[strlen(str)] = '\0'; +      printf("Real name is: '%s', length '%ld'.\n", realname, strlen(realname)); +    } +  } + +  // Ensure we have everything required +  if (!strlen(nick) || !strlen(username) || !strlen(realname)) { +    printf("Failed to read nick and/or username and/or real name from configuration file.\n"); +    exit(1); +  } + +  fclose(fp); +  return 1; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..5307178 --- /dev/null +++ b/config.h @@ -0,0 +1,12 @@ +#ifndef CONFIG_H_INCLUDED +#define CONFIG_H_INCLUDED + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define MAXCHAR 1000 + +int readnames(char *nick, char *username, char *realname); + +#endif | 
