muhstik

- irc flooding solution
git clone git://git.acid.vegas/muhstik.git
Log | Files | Refs | Archive | README

muhstik.c (11289B)

      1 /* Muhstik, Copyright (C) 2001-2002, Louis Bavoil <mulder@gmx.fr>       */
      2 /*                        2009-2011, Leon Kaiser <literalka@gnaa.eu>    */
      3 /*                                                                      */
      4 /* This program is free software; you can redistribute it and/or        */
      5 /* modify it under the terms of the GNU Library General Public License  */
      6 /* as published by the Free Software Foundation; either version 2       */
      7 /* of the License, or (at your option) any later version.               */
      8 /*                                                                      */
      9 /* This program is distributed in the hope that it will be useful,      */
     10 /* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
     11 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
     12 /* GNU Library General Public License for more details.                 */
     13 
     14 /* {{{ Header includes */
     15 #include <pthread.h>
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 #include <unistd.h>
     19 #include <signal.h>
     20 #include <string.h>
     21 #include <errno.h>
     22 #include <sys/time.h>
     23 #include <time.h>
     24 
     25 #include "../include/muhstik.h"
     26 #include "../include/clone.h"
     27 #include "../include/proxy.h"
     28 #include "../include/control.h"
     29 #include "../include/print.h"
     30 #include "../include/load.h"
     31 #include "../include/string.h"
     32 /* }}} */
     33 /* {{{ Variables */
     34 /* {{{ External variables */
     35 extern clone_t *cl[];
     36 extern const char *strtype[];
     37 extern char *channel[];
     38 extern pthread_mutex_t mutex[];
     39 extern pthread_attr_t attr;
     40 extern int mass_ch;
     41 extern int maxsock;
     42 extern config_t conf;
     43 extern char *hostname;
     44 /* }}} */
     45 /* {{{ Global Variables */
     46 time_t t0;
     47 pid_t pid;
     48 /* }}} */
     49 /* }}} */
     50 /* {{{ save_list() */
     51 void save_list(char *filename, char **list, int max)
     52 {
     53      int i;
     54      FILE *f;
     55 
     56      if ((f = fopen(filename, "w")))
     57      {
     58           for (i = 0; i < max; ++i)
     59           {
     60                if (list[i])
     61                {
     62                     fprintf(f, "%s\n", list[i]);
     63                }
     64           }
     65           fclose(f);
     66      }
     67 }
     68 /* }}} */
     69 /* {{{ main() functions */
     70 void main_exit()
     71 {
     72      if (conf.userlist[AOP])
     73      {
     74           save_list(conf.userlist[AOP], conf.aop, MAX_AOPS);
     75      }
     76      if (conf.userlist[JUPE])
     77      {
     78           save_list(conf.userlist[JUPE], conf.jupe, MAX_JUPES);
     79      }
     80      if (conf.userlist[PROT])
     81      {
     82           save_list(conf.userlist[PROT], conf.prot, MAX_PROTS);
     83      }
     84      if (conf.userlist[SHIT])
     85      {
     86           save_list(conf.userlist[SHIT], conf.shit, MAX_SHITS);
     87      }
     88 
     89      exit(EXIT_SUCCESS);
     90 }
     91 
     92 void segfault(int sig)
     93 {
     94      puts("Segmentation fault: blog it.");
     95      exit(EXIT_FAILURE);
     96 }
     97 
     98 int main(int argc, char **argv)
     99 {
    100      pthread_t tid;
    101 
    102      printf("muhstik %s, Copyright (C) 2001-2003, Louis Bavoil\n", VERSION);
    103      printf("               Copyright (C) 2009-2011, Leon Kaiser\n");
    104      printf("This is free software. See the LICENSE file for more details.\n");
    105 
    106      if (argc < 2)
    107      {
    108           printf("Usage: %s <config file>\n", argv[0]);
    109           exit(EXIT_FAILURE);
    110      }
    111 
    112      signal(SIGTTIN, SIG_IGN);
    113      signal(SIGTTOU, SIG_IGN);
    114      signal(SIGALRM, SIG_IGN);
    115      signal(SIGPIPE, SIG_IGN);
    116      signal(SIGUSR1, SIG_IGN);
    117      signal(SIGSEGV, &segfault);
    118      signal(SIGINT, SIG_IGN);
    119 
    120      t0 = time(NULL);
    121      pid = getpid();
    122      srandom(pid);
    123 
    124      init_options(argv);
    125      check_options();
    126      init_threads();
    127      init_hostname();
    128 
    129      if (conf.motd)
    130      {
    131           print_motd(1);
    132      }
    133      if (conf.help)
    134      {
    135           usage(1);
    136      }
    137 
    138      if (pthread_create(&tid, &attr, load_all, NULL))
    139      {
    140           puts("pthread_create() failed");
    141           main_exit();
    142      }
    143 
    144      if (conf.batch)
    145      {
    146           read_batch();
    147      }
    148 
    149      main_loop();
    150 
    151      return 0;
    152 }
    153 /* }}} */
    154 /* {{{ read_batch() */
    155 void read_batch()
    156 {
    157      FILE *f;
    158      char buffer[BIGBUF];
    159 
    160      if (!(f = fopen(conf.batch, "r")))
    161      {
    162           print(1, 0, 0, "Cannot open the file `%s.'", conf.batch);
    163           return;
    164      }
    165      while (1)
    166      {
    167           if (!fgets(buffer, sizeof(buffer), f))
    168           {
    169                return;
    170           }
    171           interpret(buffer, 0);
    172      }
    173      fclose(f);
    174 }
    175 /* }}} */
    176 /* {{{ sock2clone() */
    177 clone_t *sock2clone(int sock)
    178 {
    179      register int i;
    180      clone_t **pcl;
    181 
    182      for (i = 0, pcl = cl; i < MAX_CLONES; ++i, ++pcl)
    183      {
    184           if (*pcl && (*pcl)->sock == sock)
    185           {
    186                return *pcl;
    187           }
    188      }
    189 
    190      return NULL;
    191 }
    192 /* }}} */
    193 /* {{{ init_gateway() */
    194 int init_gateway(clone_t *clone)
    195 {
    196      int ret = EXIT;
    197 
    198      clone->host = clone->server;
    199      clone->port = clone->server_port;
    200 
    201      switch (clone->type)
    202      {
    203           case SOCKS4:
    204                ret = init_socks4(clone);
    205                break;
    206           case SOCKS5:
    207                ret = init_socks5(clone);
    208                break;
    209           case PROXY:
    210                ret = init_proxy(clone);
    211                break;
    212           case CISCO:
    213                ret = WAIT_CISCO;
    214                break;
    215      }
    216      return ret;
    217 }
    218 /* }}} */
    219 /* {{{ Read/write functions */
    220 void write_ready(int sok)
    221 {
    222      clone_t *clone;
    223      unsigned int len = sizeof(int);
    224 
    225      if ((clone = sock2clone(sok)))
    226      {
    227           if (getsockopt(sok, SOL_SOCKET, SO_ERROR, &errno, &len))
    228           {
    229                print_error("getsockopt");
    230                clone->status = EXIT;
    231                return;
    232           }
    233           if (errno != 0)
    234           {
    235                print_error("connect");
    236                clone->status = EXIT;
    237                return;
    238           }
    239           if (clone->type != NOSPOOF)
    240           {
    241                print(1, 0, 0, "%s connect()ed: host=%s server=%s", strtype[clone->type], clone->proxy, clone->server);
    242           }
    243           else
    244           {
    245                print(1, 0, 0, "direct connect()ed: server=%s", clone->server);
    246           }
    247 
    248           if (clone->type == NOSPOOF || clone->type == VHOST)
    249           {
    250                clone->status = init_irc(clone);
    251           }
    252           else
    253           {
    254                clone->status = init_gateway(clone);
    255           }
    256 
    257           return;
    258      }
    259 }
    260 
    261 int read_irc(clone_t *clone)
    262 {
    263      char *buf;
    264      char *line;
    265      int i;
    266      int n;
    267 
    268      i = strlen(clone->buffer);
    269      n = sizeof(clone->buffer) - 1 - i;
    270 
    271      if (recv(clone->sock, clone->buffer + i, n, 0) <= 0)
    272      {
    273           buf = clone->lastbuffer;
    274           if (buf[strlen(buf)-1] != '\n')
    275           {
    276                StrCat(buf, "\n", sizeof(clone->lastbuffer));
    277           }
    278           if (parse_deco(clone, buf))
    279           {
    280                return EXIT;
    281           }
    282           return WAIT_CONNECT;
    283      }
    284      else
    285      {
    286           buf = clone->buffer;
    287           while (strchr(buf,'\n'))
    288           {
    289                line = strsep(&buf, "\r\n");
    290                if (buf == NULL)
    291                {
    292                     buf = "";
    293                }
    294                snprintf(clone->lastbuffer, sizeof(clone->lastbuffer), "%s\n", line);
    295                parse_irc(clone, clone->lastbuffer);
    296           }
    297           StrCopy(clone->lastbuffer, clone->buffer, sizeof(clone->lastbuffer));
    298           StrCopy(clone->buffer, buf, sizeof(clone->buffer));
    299      }
    300      if (conf.no_restricted && clone->restricted)
    301      {
    302           return EXIT;
    303      }
    304      return WAIT_IRC;
    305 }
    306 
    307 void read_stdin()
    308 {
    309      char buffer[BIGBUF];
    310 
    311      memset(buffer, 0, sizeof(buffer));
    312      if (!fgets(buffer, sizeof(buffer), stdin))
    313      {
    314           return;
    315      }
    316 
    317      interpret(buffer, 1);
    318 }
    319 
    320 void read_ready(int sok)
    321 {
    322      clone_t *clone;
    323      int ret = EXIT;
    324 
    325      if (sok == 0)
    326      {
    327           read_stdin();
    328           return;
    329      }
    330 
    331      if ((clone = sock2clone(sok)))
    332      {
    333           switch (clone->status)
    334           {
    335                case WAIT_SOCKS4:
    336                     ret = read_socks4(clone);
    337                     break;
    338                case WAIT_SOCKS5_1:
    339                     ret = init_read_socks5(clone);
    340                     break;
    341                case WAIT_SOCKS5_2:
    342                     ret = read_socks5(clone);
    343                     break;
    344                case WAIT_PROXY:
    345                     ret = read_proxy(clone);
    346                     break;
    347                case WAIT_CISCO:
    348                     ret = read_cisco(clone);
    349                     break;
    350                case WAIT_IRC:
    351                     ret = read_irc(clone);
    352                     break;
    353           }
    354 
    355           if (ret == WAIT_IDENT)
    356           {
    357                ret = init_irc(clone);
    358           }
    359 
    360           clone->status = ret;
    361           return;
    362      }
    363 }
    364 /* }}} */
    365 /* {{{ fill_fds() */
    366 void fill_fds(fd_set *rfds, fd_set *wfds)
    367 {
    368      clone_t **pcl;
    369      register int i;
    370      time_t now;
    371 
    372      now = time(NULL);
    373      FD_SET(0, rfds);
    374 
    375      for (i = 0, pcl = cl; i < MAX_CLONES; ++i, ++pcl)
    376      {
    377           if (*pcl)
    378           {
    379                if ((*pcl)->rejoin_time > 0)
    380                {
    381                     if (!channel[mass_ch])
    382                     {
    383                          (*pcl)->rejoin_time = 0;
    384                     }
    385                     else if ((*pcl)->rejoin_time <= now)
    386                     {
    387                          join(*pcl, channel[mass_ch]);
    388                          (*pcl)->rejoin_time = 0;
    389                     }
    390                }
    391                if ((*pcl)->alarm > 0)
    392                {
    393                     if ((*pcl)->alarm > now)
    394                     {
    395                          continue;
    396                     }
    397                     (*pcl)->alarm = 0;
    398                }
    399                switch ((*pcl)->status)
    400                {
    401                     case EXIT:
    402                          /* Connection closed */
    403                          free_clone(*pcl);
    404                          break;
    405                     case WAIT_CONNECT:
    406                          if (now-(*pcl)->start > conf.timeout)
    407                          {
    408                               /* Connection timeout */
    409                               free_clone(*pcl);
    410                               break;
    411                          }
    412                          FD_SET((*pcl)->sock, wfds);
    413                          break;
    414                     default:
    415                          FD_SET((*pcl)->sock, rfds);
    416                          break;
    417                }
    418           }
    419      }
    420 }
    421 /* }}} */
    422 /* {{{ main_loop() */
    423 void main_loop()
    424 {
    425      fd_set rfds;
    426      fd_set wfds;
    427      register int sok;
    428      struct timeval tv;
    429 
    430      while (1)
    431      {
    432           FD_ZERO(&rfds);
    433           FD_ZERO(&wfds);
    434 
    435           pthread_mutex_lock(&mutex[0]);
    436           fill_fds(&rfds, &wfds);
    437           pthread_mutex_unlock(&mutex[0]);
    438 
    439           tv.tv_sec = 1;
    440           tv.tv_usec = 0;
    441 
    442           if (select(maxsock + 1, &rfds, &wfds, NULL, &tv) == -1)
    443           {
    444                print_error("select");
    445                main_exit();
    446           }
    447 
    448           for (sok = 0; sok <= maxsock; ++sok)
    449           {
    450                if (FD_ISSET(sok, &wfds))
    451                {
    452                     pthread_mutex_lock(&mutex[0]);
    453                     write_ready(sok);
    454                     pthread_mutex_unlock(&mutex[0]);
    455                }
    456           }
    457 
    458           for (sok = maxsock; sok >= 0; --sok)
    459           {
    460                if (FD_ISSET(sok, &rfds))
    461                {
    462                     pthread_mutex_lock(&mutex[0]);
    463                     read_ready(sok);
    464                     pthread_mutex_unlock(&mutex[0]);
    465                }
    466           }
    467      }
    468 }
    469 /* }}} */