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 /* }}} */