1 /*
2 * server.c: Things dealing with server connections, etc.
3 *
4 * Written By Michael Sandrof
5 *
6 * Copyright (c) 1990 Michael Sandrof.
7 * Copyright (c) 1991, 1992 Troy Rollo.
8 * Copyright (c) 1992-2018 Matthew R. Green.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #include "irc.h"
36 IRCII_RCSID("@(#)$eterna: server.c,v 1.249 2021/03/14 18:22:31 mrg Exp $");
37
38 #ifdef HAVE_SYS_UN_H
39 # include <sys/un.h>
40
41 int connect_to_unix(int, u_char *);
42 #endif /* HAVE_SYS_UN_H */
43
44 #include "server.h"
45 #include "screen.h"
46 #include "ircaux.h"
47 #include "whois.h"
48 #include "lastlog.h"
49 #include "exec.h"
50 #include "window.h"
51 #include "output.h"
52 #include "names.h"
53 #include "parse.h"
54 #include "list.h"
55 #include "newio.h"
56 #include "vars.h"
57 #include "hook.h"
58 #include "icb.h"
59 #include "server.h"
60 #include "notice.h"
61 #include "ssl.h"
62 #include "sl_irc.h"
63
64 #include <assert.h>
65
66 /* Server: a structure for the server_list */
67 typedef struct
68 {
69 u_char *name; /* the name of the server */
70 u_char *itsname; /* the server's idea of its name */
71 u_char *password; /* password for that server */
72 int port; /* port number on that server */
73 u_char *proxy_name; /* HTTP proxy server to use */
74 int proxy_port; /* port number for proxy server */
75 u_char *nickname; /* nickname for this server */
76 u_char *away; /* away message for this server */
77 int operator; /* true if operator */
78 int oper_command; /* true just after an oper() command is
79 given. Used to tell the difference
80 between an incorrect password
81 generated by an oper() command and
82 one generated when connecting to a
83 new server */
84 int version; /* the version of the server -
85 defined above */
86 u_char *version_string; /* what is says */
87 int whois; /* true if server sends numeric 318 */
88 int flags; /* Various flags */
89 int connected; /* true if connection is assured */
90 int write; /* write descriptor */
91 int read; /* read descriptior */
92 pid_t pid; /* process id of server */
93 int eof; /* eof flag for server */
94 int motd; /* motd flag (used in notice.c) */
95 int sent; /* set if something has been sent,
96 used for redirect */
97 u_char *buffer; /* buffer of what dgets() doesn't get */
98 WhoisQueue *WQ_head; /* WHOIS Queue head */
99 WhoisQueue *WQ_tail; /* WHOIS Queue tail */
100 WhoisStuff whois_stuff; /* Whois Queue current collection buf */
101 WhoInfo *who_info; /* /who command info */
102 int close_serv; /* Server to close when LOGGED_IN */
103 CtcpFlood *ctcp_flood; /* flood info for CTCP */
104 u_char *group; /* ICB group */
105 u_char *icbmode; /* ICB initial mode */
106 ChannelList *chan_list; /* list of channels for this server */
107 void (*parse_server)(u_char *); /* pointer to parser for this
108 server */
109 int server_group; /* group this server belongs to */
110 int attempting_to_connect; /* are we trying to connect this
111 server? */
112 struct addrinfo *res, *res0; /* current lookup; for non blocking
113 support */
114 SOCKADDR_STORAGE *localaddr; /* currently bound local port */
115 int localaddrlen; /* length of above */
116 SslInfo *ssl_info; /* handle for ssl routines */
117 server_ssl_level ssl_level; /* what sort of SSL to do */
118 void *server_private; /* private data per protocol */
119 server_private_cb_type server_private_cb; /* callback to free
120 server_private */
121 } Server;
122
123 /* default SSL for IRC connections */
124 static server_ssl_level irc_ssl_level = SSL_OFF;
125
126 /* SGroup: a structure for server groups. */
127 typedef struct ser_group_list SGroup;
128 struct ser_group_list
129 {
130 SGroup *next;
131 u_char *name;
132 int number;
133 };
134
135 static void add_to_server_buffer(int, u_char *);
136 static void login_to_server(int);
137 static int connect_to_server_direct(u_char *, int, u_char *, int);
138 static int connect_to_server_process(u_char *, int, u_char *, int);
139 static void irc2_login_to_server(int);
140 static void server_group_get_connected_next(int);
141 static int reconnect_to_server(int, int);
142 static void parse_server(u_char *);
143 static ssl_init_status server_check_ssl(int);
144 static void reestablish_close_server(int, int);
145
146 /* server_list: the list of servers that the user can connect to,etc */
147 static Server *server_list = NULL;
148
149 /* number_of_servers_count: in the server list */
150 static int number_of_servers_count = 0;
151
152 /* server_group_list: list of server groups */
153 static SGroup *server_group_list = NULL;
154
155 static int primary_server = -1;
156
157 /*
158 * from_server: server we're currently interested in; set for window
159 * operations or pretending to be on another server.
160 */
161 static int from_server = -1;
162
163 static int never_connected_local = 1; /* true until first connection
164 * is made */
165 static int connected_to_server_local = 0; /* true when connection is
166 * confirmed */
167 static int parsing_server_index = -1; /* set to the server we last
168 got a message from */
169
170 static u_char *default_proxy_name;
171 static int default_proxy_port;
172
173 #define DEFAULT_SERVER_VERSION Server2_8
174
175 #define DEFAULT_PROXY_PORT 3128
176
177 /*
178 * close_server: Given an index into the server list, this closes the
179 * connection to the corresponding server. It does no checking on the
180 * validity of the index. It also first sends a "QUIT" to the server being
181 * closed
182 */
183 void
close_server(int server_index,u_char * message)184 close_server(int server_index, u_char *message)
185 {
186 int i,
187 min,
188 max;
189
190 Debug(DB_SERVER, "entered. server %d: '%s'", server_index, message);
191 if (server_index == -1)
192 {
193 min = 0;
194 max = number_of_servers();
195 }
196 else
197 {
198 min = server_index;
199 max = server_index + 1;
200 }
201 for (i = min; i < max; i++)
202 {
203 int old_server = from_server;
204
205 Debug(DB_SERVER, "server %d: '%s'", i, message);
206 if (server_list[i].flags & CLOSE_PENDING)
207 continue;
208
209 if (i == primary_server)
210 clean_whois_queue();
211
212 from_server = -1;
213 mark_not_connected(i);
214 from_server = old_server;
215
216 if (server_list[i].server_private)
217 server_list[i].server_private_cb(
218 &server_list[i].server_private);
219
220 server_list[i].operator = 0;
221 server_list[i].connected = 0;
222 server_list[i].buffer = NULL;
223 server_list[i].flags = SERVER_2_6_2;
224 if (-1 != server_list[i].write)
225 {
226 if (message && *message)
227 {
228 u_char *buffer = NULL;
229
230 malloc_snprintf(&buffer, "QUIT :%s\n", message);
231 /* XXX retval */
232 ssl_write(server_list[i].ssl_info,
233 server_list[i].write, CP(buffer),
234 my_strlen(buffer));
235 new_free(&buffer);
236 }
237 new_close(server_list[i].write);
238 if (server_list[i].write == server_list[i].read)
239 server_list[i].read = -1;
240 server_list[i].write = -1;
241 }
242
243 if (server_list[i].ssl_info)
244 {
245 dgets_clear_ssl_info(server_list[i].read);
246 ssl_close_connection(&server_list[i].ssl_info);
247 }
248
249 if (-1 != server_list[i].read)
250 {
251 new_close(server_list[i].read);
252 server_list[i].read = -1;
253 }
254 if (-1 != server_list[i].pid)
255 {
256 kill(server_list[i].pid, SIGKILL);
257 server_list[i].pid = (pid_t) -1;
258 }
259 }
260 }
261
262 /*
263 * server_set_bits: Sets the proper bits in the fd_set structure according to
264 * which servers in the server list have currently active read descriptors.
265 */
266
267 void
server_set_bits(fd_set * rd,fd_set * wd)268 server_set_bits(fd_set *rd, fd_set *wd)
269 {
270 int i;
271
272 for (i = 0; i < number_of_servers(); i++)
273 {
274 if (server_list[i].read != -1)
275 FD_SET(server_list[i].read, rd);
276 #ifdef NON_BLOCKING_CONNECTS
277 if (server_list[i].write != -1 &&
278 !(server_list[i].flags & (LOGGED_IN|CLOSE_PENDING|CONNECTED)))
279 FD_SET(server_list[i].write, wd);
280 #endif /* NON_BLOCKING_CONNECTS */
281 }
282 }
283
284 static int
reconnect_to_server(int si,int fi)285 reconnect_to_server(int si, int fi)
286 {
287 return connect_to_server(server_list[si].name, server_list[si].port, server_list[si].nickname, fi);
288 }
289
290 static void
reestablish_close_server(int server,int old_server)291 reestablish_close_server(int server, int old_server)
292 {
293 if (server_list[old_server].flags & CLOSE_PENDING)
294 {
295 Win_Trav wt;
296 Window *tmp;
297
298 say("Connection to server %s resumed...", server_list[old_server].name);
299 server_list[server].close_serv = -1;
300 server_list[old_server].flags &= ~(CLOSE_PENDING|CLEAR_PENDING);
301 server_list[old_server].flags |= LOGGED_IN;
302 server_list[old_server].connected = 1;
303 wt.init = 1;
304 while ((tmp = window_traverse(&wt)))
305 if (window_get_server(tmp) == server)
306 {
307 window_set_server(window_get_refnum(tmp), old_server, WIN_ALL);
308 break;
309 }
310 }
311 window_check_servers();
312 }
313
314 /*
315 * do_server: check the given fd_set against the currently open servers in
316 * the server list. If one have information available to be read, it is read
317 * and and parsed appropriately. If an EOF is detected from an open server,
318 * one of two things occurs. 1) If the server was the primary server,
319 * get_connected() is called to maintain the connection status of the user.
320 * 2) If the server wasn't a primary server, connect_to_server() is called to
321 * try to keep that connection alive.
322 */
323 void
do_server(fd_set * rd,fd_set * wd)324 do_server(fd_set *rd, fd_set *wd)
325 {
326 u_char lbuf[BIG_BUFFER_SIZE];
327 int des, j;
328 static int times = 0;
329 int old_timeout;
330 u_char *close_msg;
331
332 for (j = 0; j < number_of_servers(); j++)
333 {
334 close_msg = empty_string();
335 #ifdef NON_BLOCKING_CONNECTS
336 /*
337 * deraadt@theos.com suggests that every fd awaiting connection
338 * should be run at this point.
339 */
340 if ((des = server_list[j].write) != -1 && /*FD_ISSET(des, wd) &&*/
341 !(server_list[j].flags & (LOGGED_IN|CONNECTED))) {
342 SOCKADDR_STORAGE sa;
343 socklen_t salen = sizeof sa;
344
345 if (getpeername(server_list[j].write, (struct sockaddr *) &sa, &salen) != -1)
346 login_to_server((from_server = j));
347 }
348 #endif /* NON_BLOCKING_CONNECTS */
349 if ((des = server_list[j].read) != -1 && FD_ISSET(des, rd))
350 {
351 int junk;
352 u_char *bufptr;
353 u_char *s;
354 int i = j; /* i is always j? */
355 int old_sep = -1;
356 int is_icb;
357 size_t len;
358
359 from_server = i;
360 is_icb = server_get_version(from_server) == ServerICB;
361
362 if (!(server_list[j].flags & LOGGED_IN))
363 {
364 /* If we're not logged in, try again, or keep going. */
365 login_to_server((from_server = j));
366 if (!(server_list[j].flags & LOGGED_IN))
367 goto real_continue;
368 }
369 #if 0
370 Debug(DB_SERVER, "ssl_info[%d] = %p (des = %d)", j,
371 server_list[j].ssl_info, des);
372 #endif
373
374 if (is_icb)
375 old_sep = dgets_set_separator('\0');
376
377 old_timeout = dgets_timeout(1);
378 s = server_list[from_server].buffer;
379 bufptr = lbuf;
380 if (s && *s)
381 {
382 len = my_strlen(s);
383 my_strncpy(lbuf, s, len);
384 bufptr += len;
385 }
386 else
387 len = 0;
388 if (len >= sizeof(lbuf))
389 goto buffer_is_full_hack; /* XXX */
390 junk = dgets(bufptr, (sizeof(lbuf) - len), des);
391 (void) dgets_timeout(old_timeout);
392
393 switch (junk)
394 {
395 case -2:
396 /* SSL retry */
397 goto real_continue;
398 case -1:
399 add_to_server_buffer(from_server, lbuf);
400 goto real_continue;
401 case 0:
402 {
403 #ifdef NON_BLOCKING_CONNECTS
404 int old_serv = server_list[i].close_serv;
405 /* Get this here before close_server() clears it -Sol */
406 int logged_in = server_list[i].flags & LOGGED_IN;
407 #endif /* NON_BLOCKING_CONNECTS */
408
409 close_server(i, close_msg);
410 say("Connection closed from %s: %s", server_list[i].name,
411 dgets_errno() == -1 ? "Remote end closed connection" : strerror(dgets_errno()));
412 #ifdef NON_BLOCKING_CONNECTS
413 if (!logged_in && server_list[i].res0)
414 {
415 say("Trying next IP address for %s...", server_list[i].name);
416 if (reconnect_to_server(i, -1)) {
417 say("Connection to server %s failed...", server_list[i].name);
418 clean_whois_queue();
419 window_check_servers();
420 }
421 goto real_continue;
422 }
423
424 if (!logged_in && old_serv != -1)
425 {
426 if (old_serv == i) /* a hack? you bet */
427 goto a_hack;
428 reestablish_close_server(i, old_serv);
429 break;
430 }
431 a_hack:
432 #endif /* NON_BLOCKING_CONNECTS */
433 if (i == primary_server)
434 {
435 if (server_list[i].eof)
436 {
437 say("Unable to connect to server %s",
438 server_list[i].name);
439 if (i == number_of_servers() - 1)
440 {
441 clean_whois_queue();
442 window_check_servers();
443 if (!connected_to_server())
444 say("Use /SERVER to connect to a server");
445 times = 0;
446 }
447 else
448 server_group_get_connected_next(i);
449 }
450 else
451 {
452 if (times++ > 1)
453 {
454 clean_whois_queue();
455 window_check_servers();
456 if (!connected_to_server())
457 say("Use /SERVER to connect to a server");
458 times = 0;
459 }
460 else
461 get_connected(i);
462 }
463 }
464 else if (server_list[i].eof)
465 {
466 say("Connection to server %s lost.", server_list[i].name);
467 clean_whois_queue();
468 window_check_servers();
469 }
470 else
471 {
472 if (reconnect_to_server(i, -1)) {
473 say("Connection to server %s lost.", server_list[i].name);
474 clean_whois_queue();
475 window_check_servers();
476 }
477 }
478 server_list[i].eof = 1;
479 break;
480 }
481 default:
482 buffer_is_full_hack:
483 {
484 int old_psi = parsing_server_index;
485
486 parsing_server_index = i;
487 parse_server(lbuf);
488 new_free(&server_list[i].buffer);
489 parsing_server_index = old_psi;
490 break;
491 }
492 }
493 real_continue:
494 from_server = primary_server;
495 if (is_icb && old_sep != -1)
496 (void)dgets_set_separator(old_sep);
497 }
498 }
499 }
500
501 /*
502 * find_in_server_list: given a server name, this tries to match it against
503 * names in the server list, returning the index into the list if found, or
504 * -1 if not found
505 */
506 int
find_in_server_list(u_char * server,int port,u_char * nick)507 find_in_server_list(u_char *server, int port, u_char *nick)
508 {
509 int i, maybe = -1;
510 size_t len;
511
512 len = my_strlen(server);
513 for (i = 0; i < number_of_servers(); i++)
514 {
515 if (port && server_list[i].port &&
516 port != server_list[i].port)
517 continue;
518
519 if (my_strnicmp(server, server_list[i].name, len) != 0)
520 continue;
521
522 if (nick)
523 {
524 if (server_list[i].nickname == NULL)
525 {
526 maybe = i;
527 continue;
528 }
529 if (my_stricmp(server_list[i].nickname, nick))
530 continue;
531 }
532 maybe = i;
533 break;
534 }
535 return (maybe);
536 }
537
538 /*
539 * parse_server_index: given a string, this checks if it's a number, and if
540 * so checks it validity as a server index. Otherwise -1 is returned
541 */
542 int
parse_server_index(u_char * str)543 parse_server_index(u_char *str)
544 {
545 int i;
546
547 if (is_number(str))
548 {
549 i = my_atoi(str);
550 if (i >= 0 && i < number_of_servers())
551 return i;
552 }
553 return -1;
554 }
555
556 /*
557 * add_to_server_list: adds the given server to the server_list. If the
558 * server is already in the server list it is not re-added... however, if the
559 * SL_ADD_OVERWRITE flag is true, the port and passwords are updated to the
560 * values passes. If the server is not on the list, it is added to the end.
561 * In either case, the server is made the current server.
562 */
563 void
add_to_server_list(u_char * server,int port,u_char * proxy_name,int proxy_port,u_char * password,u_char * nick,int group,int type,int flags)564 add_to_server_list(u_char *server, int port, u_char *proxy_name, int proxy_port,
565 u_char *password, u_char *nick,
566 int group, int type, int flags)
567 {
568 Debug(DB_SERVER, "server '%s' port %d pass '%s' nick '%s' group %d "
569 "type %d flags %x proxy %s:%d", server, port, password,
570 nick, group, type, flags,
571 proxy_name ? proxy_name : UP("<>"), proxy_port);
572 if (port == -1)
573 port = CHOOSE_PORT(type);
574 if ((from_server = find_in_server_list(server, port, nick)) == -1)
575 {
576 from_server = number_of_servers_count++;
577 if (server_list)
578 server_list = new_realloc(server_list, number_of_servers_count * sizeof(*server_list));
579 else
580 server_list = new_malloc(number_of_servers_count * sizeof(*server_list));
581 server_list[from_server].name = NULL;
582 server_list[from_server].proxy_name = NULL;
583 server_list[from_server].itsname = NULL;
584 server_list[from_server].password = NULL;
585 server_list[from_server].away = NULL;
586 server_list[from_server].version_string = NULL;
587 server_list[from_server].operator = 0;
588 server_list[from_server].read = -1;
589 server_list[from_server].write = -1;
590 server_list[from_server].pid = -1;
591 server_list[from_server].whois = 0;
592 server_list[from_server].flags = SERVER_2_6_2;
593 server_list[from_server].nickname = NULL;
594 server_list[from_server].connected = 0;
595 server_list[from_server].eof = 0;
596 server_list[from_server].motd = 1;
597 server_list[from_server].group = NULL;
598 server_list[from_server].icbmode = NULL;
599 server_list[from_server].chan_list = NULL;
600 malloc_strcpy(&server_list[from_server].name, server);
601 if (password && *password)
602 malloc_strcpy(&server_list[from_server].password, password);
603 if (nick && *nick)
604 malloc_strcpy(&server_list[from_server].nickname, nick);
605 server_list[from_server].port = port;
606 if (proxy_name)
607 malloc_strcpy(&server_list[from_server].proxy_name, proxy_name);
608 server_list[from_server].proxy_port = proxy_port;
609 server_list[from_server].WQ_head = NULL;
610 server_list[from_server].WQ_tail = NULL;
611 server_list[from_server].whois_stuff.nick = NULL;
612 server_list[from_server].whois_stuff.user = NULL;
613 server_list[from_server].whois_stuff.host = NULL;
614 server_list[from_server].whois_stuff.channel = NULL;
615 server_list[from_server].whois_stuff.channels = NULL;
616 server_list[from_server].whois_stuff.name = NULL;
617 server_list[from_server].whois_stuff.server = NULL;
618 server_list[from_server].whois_stuff.server_stuff = NULL;
619 server_list[from_server].whois_stuff.away = NULL;
620 server_list[from_server].whois_stuff.oper = 0;
621 server_list[from_server].whois_stuff.chop = 0;
622 server_list[from_server].whois_stuff.not_on = 0;
623 server_list[from_server].who_info = alloc_who_info();
624 server_list[from_server].buffer = NULL;
625 server_list[from_server].close_serv = -1;
626 server_list[from_server].localaddr = 0;
627 server_list[from_server].localaddrlen = 0;
628 server_list[from_server].ssl_info = NULL;
629 server_list[from_server].server_private = NULL;
630 if (flags & SL_ADD_DO_SSL_VERIFY)
631 server_list[from_server].ssl_level = SSL_VERIFY;
632 else if (flags & SL_ADD_DO_SSL)
633 server_list[from_server].ssl_level = SSL_ON;
634 else
635 server_list[from_server].ssl_level = SSL_OFF;
636 switch (type)
637 {
638 case ServerICB:
639 server_list[from_server].parse_server = icb_parse_server;
640 break;
641 case -1:
642 /* default */
643 if (client_default_is_icb())
644 {
645 type = ServerICB;
646 server_list[from_server].parse_server = icb_parse_server;
647 break;
648 }
649 type = DEFAULT_SERVER_VERSION;
650 /* FALLTHROUGH */
651 default:
652 server_list[from_server].parse_server = irc2_parse_server;
653 }
654 server_list[from_server].version = type;
655
656 server_list[from_server].ctcp_flood = ctcp_new_flood();
657
658 if (group == -1)
659 server_list[from_server].server_group = 0;
660 else
661 server_list[from_server].server_group = group;
662 server_list[from_server].res = 0;
663 server_list[from_server].res0 = 0;
664 }
665 else
666 {
667 if (flags & SL_ADD_OVERWRITE)
668 {
669 server_list[from_server].port = port;
670 if (password)
671 {
672 if (*password)
673 malloc_strcpy(&(server_list[from_server].password), password);
674 else
675 new_free(&(server_list[from_server].password));
676 }
677 if (nick && *nick)
678 malloc_strcpy(&(server_list[from_server].nickname), nick);
679 if (group != -1)
680 server_list[from_server].server_group = group;
681 }
682 if (server_list[from_server].res0)
683 {
684 freeaddrinfo(server_list[from_server].res0);
685 server_list[from_server].res0 = 0;
686 }
687 server_list[from_server].res = 0;
688 if ((int) my_strlen(server) > (int) my_strlen(server_list[from_server].name))
689 malloc_strcpy(&(server_list[from_server].name), server);
690 }
691 }
692
693 void
ctcp_reply_backlog_change(int size)694 ctcp_reply_backlog_change(int size)
695 {
696 int i;
697
698 if (size <= 0)
699 size = 1;
700 for (i = 0; i < number_of_servers(); i++)
701 ctcp_refresh_flood(server_list[i].ctcp_flood, size);
702 }
703
704 void
remove_from_server_list(int i)705 remove_from_server_list(int i)
706 {
707 int old_server = from_server;
708
709 from_server = i;
710 clean_whois_queue();
711 from_server = old_server;
712
713 close_server(i, NULL);
714
715 if (server_list[i].name)
716 new_free(&server_list[i].name);
717 if (server_list[i].itsname)
718 new_free(&server_list[i].itsname);
719 if (server_list[i].password)
720 new_free(&server_list[i].password);
721 if (server_list[i].away)
722 new_free(&server_list[i].away);
723 if (server_list[i].version_string)
724 new_free(&server_list[i].version_string);
725 if (server_list[i].nickname)
726 new_free(&server_list[i].nickname);
727 if (server_list[i].group)
728 new_free(&server_list[i].group);
729 if (server_list[i].icbmode)
730 new_free(&server_list[i].icbmode);
731 if (server_list[i].whois_stuff.nick)
732 new_free(&server_list[i].whois_stuff.nick);
733 if (server_list[i].whois_stuff.user)
734 new_free(&server_list[i].whois_stuff.user);
735 if (server_list[i].whois_stuff.host)
736 new_free(&server_list[i].whois_stuff.host);
737 if (server_list[i].whois_stuff.channel)
738 new_free(&server_list[i].whois_stuff.channel);
739 if (server_list[i].whois_stuff.channels)
740 new_free(&server_list[i].whois_stuff.channels);
741 if (server_list[i].whois_stuff.name)
742 new_free(&server_list[i].whois_stuff.name);
743 if (server_list[i].whois_stuff.server)
744 new_free(&server_list[i].whois_stuff.server);
745 if (server_list[i].whois_stuff.server_stuff)
746 new_free(&server_list[i].whois_stuff.server_stuff);
747 if (server_list[i].ctcp_flood)
748 ctcp_clear_flood(&server_list[i].ctcp_flood);
749 if (server_list[i].res0)
750 freeaddrinfo(server_list[i].res0);
751
752 /* update all the structs with server in them */
753 window_server_delete(i);
754 channel_server_delete(i); /* fix `higher' servers */
755 clear_channel_list(i);
756 exec_server_delete(i);
757 if (i < primary_server)
758 --primary_server;
759 if (i < from_server)
760 --from_server;
761
762 memmove(&server_list[i], &server_list[i + 1], (number_of_servers() - i - 1) * sizeof(*server_list));
763 server_list = new_realloc(server_list, --number_of_servers_count * sizeof(*server_list));
764
765 if (from_server >= number_of_servers_count)
766 from_server = -1;
767 }
768
769 int
ssl_level_to_sa_flags(server_ssl_level level)770 ssl_level_to_sa_flags(server_ssl_level level)
771 {
772 assert(level != SSL_UNKNOWN);
773 if (level == SSL_VERIFY)
774 return SL_ADD_DO_SSL_VERIFY;
775 else if (level == SSL_ON)
776 return SL_ADD_DO_SSL;
777 return 0;
778 }
779
780 static void
server_split_proxy_port(u_char * proxy_and_port,u_char ** name,int * port)781 server_split_proxy_port(u_char *proxy_and_port, u_char **name, int *port)
782 {
783 u_char *sport;
784
785 if ((sport = my_index(proxy_and_port, ':')) == NULL)
786 {
787 *port = DEFAULT_PROXY_PORT;
788 }
789 else
790 {
791 *sport++ = '\0';
792 *port = my_atoi(sport);
793 }
794
795 *name = proxy_and_port;
796 }
797
798 /*
799 * parse_server_info: This parses a single string of the form
800 * "server:portnum:password:nickname[:icbgroup]". It the points port to the portnum
801 * portion and password to the password portion. This chews up the original
802 * string, so upon return, name will only point the the name. If portnum
803 * or password are missing or empty, their respective returned value will
804 * point to null. if extra is non NULL, it is set to anything after the
805 * final : after the nickname..
806 *
807 * Note: this will set *type if it sees the IRC/ or ICB/ at the start of
808 * the "name". The server group name will be set by prepending ":group:" to
809 * the server, so any of these is valid:
810 *
811 * :group:server:portnum:...
812 * ICB/:group:server:portnum:...
813 * server:portnum:...
814 * ICB/server:portnum:...
815 *
816 * SSLIRC/ and SSLIRCNOCHECK/ prefixes also enable using an SSL connection
817 * to the server, the latter version does not perform any certificate
818 * verification.
819 *
820 * In addition, the PROXY/proxy.host:port/ and NOPROXY/ prefixes may be
821 * present (currently, only *before* any other prefix.)
822 */
823 void
parse_server_info(u_char ** name,u_char ** port,u_char ** password,u_char ** nick,u_char ** group,u_char ** extra,int * type,server_ssl_level * level,u_char ** proxy_name,int * proxy_port)824 parse_server_info(u_char **name, u_char **port, u_char **password,
825 u_char **nick, u_char **group, u_char **extra,
826 int *type, server_ssl_level *level,
827 u_char **proxy_name, int *proxy_port)
828 {
829 u_char *ptr, *ename, *savename = NULL;
830 u_char *epname, *pname;
831
832 Debug(DB_SERVER, "got %s", *name);
833 Debug(DB_PROXY, "got %s port %d", *proxy_name ? *proxy_name : UP("<>"), *proxy_port);
834 *port = *password = *nick = *extra = NULL;
835
836 if (my_strncmp(*name, "PROXY/", 6) == 0)
837 {
838 pname = (*name) + 6;
839 if ((epname = my_index(pname, '/')) == NULL)
840 {
841 yell("--- Unable to parse server info: %s", *name);
842 return;
843 }
844 *epname++ = '\0';
845
846 server_split_proxy_port(pname, proxy_name, proxy_port);
847 Debug(DB_PROXY, "set proxy_name %s port %d", *proxy_name, *proxy_port);
848 *name = epname;
849 }
850 else
851 if (my_strncmp(*name, "NO_PROXY/", 9) == 0)
852 {
853 *proxy_port = -1;
854 *name += 9;
855 }
856
857 if (my_strncmp(*name, "IRC/", 4) == 0)
858 {
859 *type = DEFAULT_SERVER_VERSION;
860 *level = SSL_OFF;
861 *name += 4;
862 }
863 else
864 if (my_strncmp(*name, "SSLIRC/", 7) == 0)
865 {
866 *type = DEFAULT_SERVER_VERSION;
867 *level = SSL_VERIFY;
868 *name += 7;
869 }
870 else
871 if (my_strncmp(*name, "SSLIRCNOCHECK/", 14) == 0)
872 {
873 *type = DEFAULT_SERVER_VERSION;
874 *level = SSL_ON;
875 *name += 14;
876 }
877 else
878 if (my_strncmp(*name, "ICB/", 4) == 0)
879 {
880 *type = ServerICB;
881 *level = SSL_OFF;
882 *name += 4;
883 }
884 else
885 if (*level == SSL_UNKNOWN)
886 *level = irc_ssl_level;
887
888 /* check for :group: processing */
889 if (**name == ':')
890 {
891 if ((ename = my_index((*name)+1, ':')))
892 {
893 *ename = '\0';
894 if (group)
895 *group = *name + 1;
896 *name = ename + 1; /* now points to empty or : we hope */
897 }
898 }
899
900 /* check for [i:p:v:6]:port style */
901 if (**name == '[')
902 {
903 if ((ename = my_index((*name)+1, ']')))
904 {
905 *ename = '\0';
906 savename = *name + 1;
907 *name = ename + 1; /* now points to empty or : we hope */
908 }
909 }
910
911 if ((ptr = my_index(*name, ':')) != NULL)
912 {
913 *(ptr++) = '\0';
914 if (my_strlen(ptr) == 0)
915 *port = NULL;
916 else
917 {
918 *port = ptr;
919 if ((ptr = my_index(ptr, ':')) != NULL)
920 {
921 *(ptr++) = '\0';
922 if (my_strlen(ptr) == 0)
923 *password = NULL;
924 else
925 {
926 *password = ptr;
927 if ((ptr = my_index(ptr, ':'))
928 != NULL)
929 {
930 *(ptr++) = '\0';
931 if (!my_strlen(ptr))
932 *nick = NULL;
933 else
934 {
935 *nick = ptr;
936 if (extra && (ptr = my_index(ptr, ':'))
937 != NULL)
938 {
939 *(ptr++) = '\0';
940 if (!my_strlen(ptr))
941 *extra = NULL;
942 else
943 *extra = ptr;
944 }
945 }
946 }
947 }
948 }
949 }
950 }
951 if (savename)
952 *name = savename;
953 Debug(DB_PROXY, "got %s port %d", *proxy_name ? *proxy_name : UP("<>"), *proxy_port);
954 }
955
956 /*
957 * build_server_list: given a whitespace separated list of server names this
958 * builds a list of those servers using add_to_server_list(). Since
959 * add_to_server_list() is used to added each server specification, this can
960 * be called many many times to add more servers to the server list. Each
961 * element in the server list case have one of the following forms:
962 *
963 * servername
964 *
965 * servername:port
966 *
967 * servername:port:password
968 *
969 * servername::password
970 *
971 * Note also that this routine mucks around with the server string passed to it,
972 * so make sure this is ok.
973 *
974 * A new format for ICB and more support is:
975 *
976 * type/<type-specifc-format>
977 *
978 * eg:
979 * IRC/server:port:pass:nick:#foo:#bar:&baz
980 * means connect to server on port port with pass and nick, and then to join
981 * channels #foo, #bar and &baz. this is not implemented beyond the nick...
982 *
983 * or
984 * ICB/[:group:]server:port:pass:nick:group:mode
985 * which is all the things needed at connection startup. this is done.
986 */
987 void
build_server_list(u_char * servers)988 build_server_list(u_char *servers)
989 {
990 u_char *host,
991 *rest,
992 *extra,
993 *mode,
994 *password = NULL,
995 *port = NULL,
996 *group = NULL,
997 *nick = NULL,
998 *proxy_name = NULL;
999 int port_num,
1000 proxy_port = 0,
1001 type = -1;
1002
1003 if (servers == NULL)
1004 return;
1005 while (servers)
1006 {
1007 if ((rest = my_index(servers, '\n')) != NULL)
1008 *rest++ = '\0';
1009 while ((host = next_arg(servers, &servers)) != NULL)
1010 {
1011 server_ssl_level level = SSL_UNKNOWN;
1012
1013 parse_server_info(&host, &port, &password, &nick,
1014 &group, &extra, &type, &level,
1015 &proxy_name, &proxy_port);
1016 if (port && *port)
1017 {
1018 port_num = my_atoi(port);
1019 if (!port_num)
1020 port_num = CHOOSE_PORT(type);
1021 }
1022 else
1023 port_num = CHOOSE_PORT(type);
1024 if (!nick)
1025 nick = my_nickname();
1026
1027 add_to_server_list(host, port_num, proxy_name, proxy_port,
1028 password, nick,
1029 find_server_group(group, 1), type,
1030 ssl_level_to_sa_flags(level));
1031 if (extra)
1032 {
1033 switch (type)
1034 {
1035 case ServerICB:
1036 if ((mode = my_index(extra, ':')) && mode[1])
1037 *mode++ = 0;
1038 else
1039 mode = NULL;
1040 server_set_icbgroup(from_server, extra);
1041 server_set_icbmode(from_server, mode);
1042 break;
1043 default:
1044 break;
1045 /* nothing yet */
1046 }
1047 }
1048 }
1049 servers = rest;
1050 }
1051 }
1052
1053 /*
1054 * connect_to_server_direct: handles the tcp connection to a server. If
1055 * successful, the user is disconnected from any previously connected server,
1056 * the new server is added to the server list, and the user is registered on
1057 * the new server. If connection to the server is not successful, the
1058 * reason for failure is displayed and the previous server connection is
1059 * resumed uniterrupted.
1060 *
1061 * This version of connect_to_server() connects directly to a server
1062 */
1063 static int
connect_to_server_direct(u_char * server_name,int port,u_char * nick,int server_index)1064 connect_to_server_direct(u_char *server_name, int port, u_char *nick, int server_index)
1065 {
1066 int new_des;
1067 struct addrinfo *r = 0, *r0 = 0;
1068 u_char *connect_name;
1069 int connect_port;
1070 u_char *proxy_name = NULL;
1071 int proxy_port = 0;
1072
1073 if (server_index >= 0)
1074 server_list[server_index].oper_command = 0;
1075 errno = 0;
1076
1077 connect_name = server_name;
1078 connect_port = port;
1079
1080 /* does this server use a proxy, or is there a non-ignored default? */
1081 if (server_index >= 0 &&
1082 server_index < number_of_servers() &&
1083 server_list[server_index].proxy_port != -1)
1084 {
1085 if (server_list[server_index].proxy_name)
1086 {
1087 connect_name = server_list[server_index].proxy_name;
1088 connect_port = server_list[server_index].proxy_port;
1089 proxy_name = connect_name;
1090 proxy_port = connect_port;
1091 }
1092 else if (default_proxy_name)
1093 {
1094 connect_name = default_proxy_name;
1095 connect_port = default_proxy_port;
1096 proxy_name = connect_name;
1097 proxy_port = connect_port;
1098 }
1099 }
1100
1101 #ifdef HAVE_SYS_UN_H
1102 if (*server_name == '/')
1103 new_des = connect_to_unix(port, server_name);
1104 else
1105 #endif /* HAVE_SYS_UN_H */
1106 {
1107 if (server_index >= 0 &&
1108 server_list[server_index].res &&
1109 server_list[server_index].res0)
1110 {
1111 new_des = connect_by_number(connect_port, connect_name,
1112 1, &server_list[server_index].res,
1113 &server_list[server_index].res0);
1114 }
1115 else
1116 {
1117 new_des = connect_by_number(connect_port, connect_name,
1118 1, &r, &r0);
1119 }
1120 }
1121 if (new_des < 0)
1122 {
1123 int error = errno;
1124
1125 char *e = NULL;
1126 switch (new_des)
1127 {
1128 default:
1129 case -2:
1130 error = 0;
1131 case -1:
1132 e = "Unknown host";
1133 break;
1134 case -3:
1135 e = "socket";
1136 break;
1137 case -4:
1138 e = "connect";
1139 break;
1140 }
1141
1142 if (proxy_name)
1143 say("Unable to connect to port %d of server %s "
1144 "(proxy %s:%d): %s%s%s",
1145 port, server_name,
1146 proxy_name, proxy_port,
1147 e, error ? ": " : "", error ? strerror(error) : "");
1148 else
1149 say("Unable to connect to port %d of server %s: %s%s%s",
1150 port, server_name,
1151 e, error ? ": " : "", error ? strerror(error) : "");
1152 if (is_server_open(from_server))
1153 say("Connection to server %s resumed...", server_list[from_server].name);
1154 return (-1);
1155 }
1156
1157 update_all_status();
1158 add_to_server_list(server_name, port, proxy_name, proxy_port, NULL,
1159 nick, -1, server_get_version(from_server),
1160 SL_ADD_OVERWRITE);
1161
1162 if (server_list[from_server].localaddr)
1163 new_free(&server_list[from_server].localaddr);
1164 server_list[from_server].localaddr = 0;
1165
1166 #ifdef HAVE_SYS_UN_H
1167 if (*server_name == '/')
1168 {
1169 server_list[from_server].localaddr = 0;
1170 server_list[from_server].localaddrlen = 0;
1171 }
1172 else
1173 #endif /* HAVE_SYS_UN_H */
1174 {
1175 SOCKADDR_STORAGE *localaddr = new_malloc(sizeof *localaddr);
1176 socklen_t address_len = sizeof *localaddr;
1177
1178 if (getsockname(new_des, (struct sockaddr *) localaddr, &address_len)
1179 >= 0)
1180 {
1181 server_list[from_server].localaddr = localaddr;
1182 server_list[from_server].localaddrlen = address_len;
1183 }
1184 else
1185 {
1186 close(new_des);
1187 say("Could not getsockname(): %s", strerror(errno));
1188 new_free(&localaddr);
1189 return -1;
1190 }
1191 }
1192 if (port)
1193 {
1194 server_list[from_server].read = new_des;
1195 server_list[from_server].write = new_des;
1196 }
1197 else
1198 server_list[from_server].read = new_des;
1199 if (!server_list[from_server].res0 && r && r0)
1200 {
1201 server_list[from_server].res = r;
1202 server_list[from_server].res0 = r0;
1203 }
1204 else if (r0)
1205 freeaddrinfo(r0);
1206
1207 server_list[from_server].operator = 0;
1208 return (0);
1209 }
1210
1211 /*
1212 * connect_to_server_process: handles the tcp connection to a server. If
1213 * successful, the user is disconnected from any previously connected server,
1214 * the new server is added to the server list, and the user is registered on
1215 * the new server. If connection to the server is not successful, the
1216 * reason for failure is displayed and the previous server connection is
1217 * resumed uniterrupted.
1218 *
1219 * This version of connect_to_server() uses the ircio process to talk to a
1220 * server
1221 */
1222 static int
connect_to_server_process(u_char * server_name,int port,u_char * nick,int server_index)1223 connect_to_server_process(u_char *server_name, int port, u_char *nick, int server_index)
1224 {
1225 int write_des[2],
1226 read_des[2],
1227 pid,
1228 c;
1229 u_char *path,
1230 *name = NULL,
1231 *s;
1232 u_char buffer[BIG_BUFFER_SIZE];
1233 int old_timeout;
1234
1235 path = UP(IRCIO_PATH);
1236 if ((s = my_rindex(path, '/')) != NULL)
1237 malloc_strcpy(&name, s + 1);
1238 if (!name)
1239 name = path;
1240 if (*path == '\0')
1241 return (connect_to_server_direct(server_name, port, nick, server_index));
1242 if (server_index >= 0)
1243 server_list[server_index].oper_command = 0;
1244 write_des[0] = -1;
1245 write_des[1] = -1;
1246 if (pipe(write_des) || pipe(read_des))
1247 {
1248 if (write_des[0] != -1)
1249 {
1250 new_close(write_des[0]);
1251 new_close(write_des[1]);
1252 }
1253 say("Couldn't start new process: %s", strerror(errno));
1254 return (connect_to_server_direct(server_name, port, nick, server_index));
1255 }
1256 switch (pid = fork())
1257 {
1258 case -1:
1259 say("Couldn't start new process: %s\n", strerror(errno));
1260 return (-1);
1261 case 0:
1262 (void) MY_SIGNAL(SIGINT, (sigfunc *)SIG_IGN, 0);
1263 dup2(read_des[1], 1);
1264 dup2(write_des[0], 0);
1265 new_close(read_des[0]);
1266 new_close(read_des[1]);
1267 new_close(write_des[0]);
1268 new_close(write_des[1]);
1269 snprintf(CP(buffer), sizeof buffer, "%u", port);
1270 (void)setuid(getuid());
1271 execl(CP(path), CP(name), server_name, buffer, NULL);
1272 printf("-5 0\n"); /* -1 - -4 returned by connect_by_number() */
1273 fflush(stdout);
1274 _exit(1);
1275 default:
1276 new_close(read_des[1]);
1277 new_close(write_des[0]);
1278 break;
1279 }
1280 old_timeout = dgets_timeout(3);
1281 c = dgets(buffer, sizeof buffer, read_des[0]);
1282 (void) dgets_timeout(old_timeout);
1283 if ((c == 0) || ((c = my_atoi(buffer)) != 0))
1284 {
1285 if (c == -5)
1286 return (connect_to_server_direct(server_name, port, nick, server_index));
1287 else
1288 {
1289 u_char *ptr;
1290
1291 if ((ptr = my_index(buffer, ' ')) != NULL)
1292 {
1293 ptr++;
1294 if (my_atoi(ptr) > 0)
1295 say("Unable to connect to port %d of server %s: %s",
1296 port, server_name, strerror(my_atoi(ptr)));
1297 else
1298 say("Unable to connect to port %d of server %s: Unknown host",
1299 port, server_name);
1300 }
1301 else
1302 say("Unable to connect to port %d of server %s: Unknown host",
1303 port, server_name);
1304 if (is_server_open(from_server))
1305 say("Connection to server %s resumed...",
1306 server_list[from_server].name);
1307 new_close(read_des[0]);
1308 new_close(write_des[1]);
1309 return (-1);
1310 }
1311 }
1312 update_all_status();
1313 add_to_server_list(server_name, port, NULL/*proxy*/, 0/*proxy port*/,
1314 NULL, nick, -1, server_get_version(from_server),
1315 SL_ADD_OVERWRITE);
1316 server_list[from_server].read = read_des[0];
1317 server_list[from_server].write = write_des[1];
1318 server_list[from_server].pid = pid;
1319 server_list[from_server].operator = 0;
1320 return (0);
1321 }
1322
1323 /*
1324 * connect_to_server: Given a name and portnumber, this will attempt to
1325 * connect to that server using either a direct connection or process
1326 * connection, depending on the value of using_ircio(). If connection
1327 * is successful, the proper NICK, USER, and PASS commands are sent to the
1328 * server. If the c_server parameter is not -1, then the server with that
1329 * index will be closed upon successful connection here. Also, if connection
1330 * is successful, the attempting_to_connect variable is incremented. This is
1331 * checked in the notice.c routines to make sure that connection was truely
1332 * successful (and not closed immediately by the server).
1333 */
1334 int
connect_to_server(u_char * server_name,int port,u_char * nick,int c_server)1335 connect_to_server(u_char *server_name, int port, u_char *nick, int c_server)
1336 {
1337 int server_index;
1338 SOCKADDR_STORAGE sa;
1339 socklen_t salen = sizeof sa;
1340 int rv;
1341
1342 save_message_from();
1343 message_from(NULL, LOG_CURRENT);
1344 server_index = find_in_server_list(server_name, port, nick);
1345 if (server_index < 0)
1346 {
1347 yell("connect_to_server: server_index returned -1 from find_in_server_list()");
1348 yell("aborting!");
1349 abort();
1350 }
1351 server_list[server_index].attempting_to_connect = 1;
1352 /*
1353 * check if the server doesn't exist, or that we're not already
1354 * connected to it. note that "connected" also means logged in.
1355 */
1356 if (!is_server_connected(server_index))
1357 {
1358 if (is_server_open(server_index))
1359 close_server(server_index, empty_string());
1360 if (port == -1)
1361 port = server_list[server_index].port;
1362 if (port == -1)
1363 port = CHOOSE_PORT(server_list[server_index].version);
1364 say("Connecting to port %d of server %s", port, server_name);
1365
1366 if (!ignore_ircrc())
1367 load_ircquick();
1368
1369 if (using_ircio())
1370 rv = connect_to_server_process(server_name, port, nick, server_index);
1371 else
1372 rv = connect_to_server_direct(server_name, port, nick, server_index);
1373 if (rv)
1374 {
1375 server_list[server_index].attempting_to_connect = 0;
1376 restore_message_from();
1377 return -1;
1378 }
1379 if ((c_server != -1) && (c_server != from_server))
1380 {
1381 #ifdef NON_BLOCKING_CONNECTS
1382 #if defined(GKM)
1383 say("--- server %s will be closed when we connect", server_list[c_server].name);
1384 if (server_list[c_server].flags & CLOSE_PENDING)
1385 say("--- why are we flagging this for closing a second time?");
1386 #endif /* GKM */
1387 server_list[from_server].close_serv = c_server;
1388 server_list[c_server].flags |= CLOSE_PENDING;
1389 server_list[c_server].connected = 0;
1390 #else
1391 close_server(c_server, empty_string());
1392 #endif /* NON_BLOCKING_CONNECTS */
1393 }
1394 else
1395 {
1396 server_list[from_server].close_serv = -1;
1397 }
1398 if (server_list[from_server].nickname == NULL)
1399 malloc_strcpy(&server_list[from_server].nickname, my_nickname());
1400 server_list[from_server].flags &= ~LOGGED_IN;
1401 /*
1402 * this used to be an ifndef NON_BLOCKING_CONNECTS .. we want to do this
1403 * whenever the connection is valid, it's possible for a connect to be
1404 * "immediate".
1405 */
1406 if (is_server_open(from_server) &&
1407 (using_ircio() ||
1408 getpeername(server_list[from_server].read, (struct sockaddr *) &sa, &salen) != -1))
1409 login_to_server(from_server);
1410 }
1411 else
1412 {
1413 if (port == -1)
1414 {
1415 if (server_index != -1)
1416 port = server_list[server_index].port;
1417 else
1418 port = CHOOSE_PORT(server_get_version(server_index));
1419 }
1420 say("Connected to port %d of server %s", port, server_name);
1421 from_server = server_index;
1422 if ((c_server != -1) && (c_server != from_server))
1423 close_server(c_server, empty_string());
1424 }
1425 update_all_status();
1426 restore_message_from();
1427 return 0;
1428 }
1429
1430 static void
login_to_server_nonblocking(int server)1431 login_to_server_nonblocking(int server)
1432 {
1433 #ifdef NON_BLOCKING_CONNECTS
1434 int old_serv = server_list[server].close_serv;
1435
1436 /* clean up after ourselves */
1437 if (server_list[server].res0)
1438 {
1439 freeaddrinfo(server_list[server].res0);
1440 server_list[server].res0 = 0;
1441 }
1442 server_list[server].res = 0;
1443 if (old_serv != -1)
1444 {
1445 #if defined(GKM)
1446 say("--- closing server %s - changing servers", server_list[server_list[server].close_serv].name);
1447 if (!(server_list[server_list[server].close_serv].flags & CLOSE_PENDING))
1448 say("--- uh oh. closing a server that wasn't CLOSE_PENDING");
1449 #endif /* GKM */
1450 if (server_list[old_serv].flags & CLEAR_PENDING)
1451 clear_channel_list(old_serv); /* Channels were
1452 transfered -Sol */
1453 server_list[old_serv].flags &= ~(CLOSE_PENDING|CLEAR_PENDING);
1454 close_server(old_serv, empty_string());
1455 server_list[server].close_serv = -1;
1456 /* should we pause here to let the net catch up with us? */
1457 }
1458 #if defined(GKM)
1459 else
1460 {
1461 say("--- no server to close in login_to_server()");
1462 }
1463 #endif /* GKM */
1464 #endif /* NON_BLOCKING_CONNECTS */
1465 }
1466
1467 /*
1468 * Check if we should attempt to initiate an SSL connection or not.
1469 * Returns SSL_INIT_OK if there was no error, either no SSL or SSL
1470 * started OK. Returns SSL_INIT_FAIL if SSL failed, either to work
1471 * at all or if certificate verification failed. Returns
1472 * SSL_INIT_PENDING if the connection establishment is still ongoing.
1473 */
1474 static ssl_init_status
server_check_ssl(int server)1475 server_check_ssl(int server)
1476 {
1477 ssl_init_status status;
1478
1479 if (server_list[server].ssl_level == SSL_OFF)
1480 return SSL_INIT_OK;
1481
1482 if (server_list[server].flags & SSL_DONE)
1483 return SSL_INIT_OK;
1484
1485 status = ssl_init_connection(server, server_list[server].read,
1486 &server_list[server].ssl_info);
1487 Debug(DB_SERVER, "server = %d; status = %d; set: %p", server, status,
1488 server_list[server].ssl_info);
1489 if (status == SSL_INIT_FAIL)
1490 {
1491 if (server_list[server].ssl_level == SSL_OFF)
1492 {
1493 yell("SSL off, why did we try to allocate one?");
1494 Debug(DB_SERVER, "SSL off");
1495 }
1496 else
1497 {
1498 Debug(DB_SERVER, "ssl_init_connection failed");
1499 yell("-- SSL init failed; closing server %s",
1500 server_list[server].name);
1501 }
1502 }
1503 else if (status == SSL_INIT_OK)
1504 {
1505 server_list[server].flags |= SSL_DONE;
1506 dgets_set_ssl_info(server_list[server].read,
1507 server_list[server].ssl_info);
1508 }
1509
1510 return status;
1511 }
1512
1513 /*
1514 * we're looking for eg:
1515 *
1516 * HTTP/1.1 200 Connection established
1517 * Proxy-Agent: Privoxy/3.0.19
1518 * <blank line>
1519 *
1520 * return values:
1521 * -1 - proxy login not completed, retry
1522 * 0 - proxy login complete
1523 * 1 - failed some how; close shop.
1524 */
1525 static int
server_check_http_response(int server,u_char * lbuf,size_t buflen)1526 server_check_http_response(int server, u_char *lbuf, size_t buflen)
1527 {
1528 Debug(DB_PROXY, "server %d: buf \"%s\"", server, lbuf);
1529 if ((server_list[server].flags & PROXY_REPLY) == 0)
1530 {
1531 u_char *arg, *args = lbuf;
1532
1533 arg = next_arg(args, &args);
1534
1535 if (arg &&
1536 ((my_stricmp(UP("HTTP/1.0"), arg) == 0) ||
1537 (my_stricmp(UP("HTTP/1.1"), arg) == 0)))
1538 {
1539 arg = next_arg(args, &args);
1540
1541 if (my_stricmp(UP("200"), arg) == 0)
1542 {
1543 server_list[server].flags |= PROXY_REPLY;
1544 Debug(DB_PROXY, "got HTTP 200 reply!");
1545 return -1;
1546 }
1547 }
1548 Debug(DB_PROXY, "did not get HTTP 200 reply.");
1549 yell("-- proxy reply when we expected 200 was: \"%s\"", lbuf);
1550 return 1;
1551 }
1552 /* be generous */
1553 if (lbuf[0] == '\0' ||
1554 (lbuf[0] == '\n' && lbuf[1] == '\0') ||
1555 (lbuf[0] == '\n' && lbuf[1] == '\r' && lbuf[2] == '\0') ||
1556 (lbuf[0] == '\r' && lbuf[1] == '\n' && lbuf[2] == '\0'))
1557 {
1558 Debug(DB_PROXY, "got empty string, end of http reply! done!");
1559 return 0;
1560 }
1561
1562 /* probably just a header, we could check? */
1563 Debug(DB_PROXY, "not empty, keep going. should be http header.");
1564 return -1;
1565 }
1566
1567 static void
login_to_server(int server)1568 login_to_server(int server)
1569 {
1570 ssl_init_status status;
1571 u_char *proxy_name;
1572
1573 Debug(DB_SERVER, "server %d", server);
1574
1575 if ((server_list[server].flags & CONNECTED) == 0)
1576 {
1577 /*
1578 * If we're CONNECTED, we've gone through the non-blocking
1579 * connect. If we're LOGGED_IN, that means that we've sent
1580 * the login sequence, and for SSL that means SSL has
1581 * successfully initialised.
1582 */
1583 server_list[server].flags |= CONNECTED;
1584
1585 #ifdef NON_BLOCKING_CONNECTS
1586 if (using_ircio() == 0)
1587 {
1588 set_blocking(server_list[server].read);
1589 if (server_list[server].read != server_list[server].write)
1590 set_blocking(server_list[server].write);
1591 }
1592 #endif /* NON_BLOCKING_CONNECTS */
1593 }
1594
1595 proxy_name = server_get_proxy_name(server, 1);
1596 if (proxy_name &&
1597 (server_list[server].flags & PROXY_CONNECT) == 0)
1598 {
1599 u_char *buf = NULL;
1600 int len, rv;
1601
1602 malloc_snprintf(&buf, "CONNECT %s:%d HTTP/1.1\nHost:\n\n",
1603 server_list[server].name,
1604 server_list[server].port);
1605 len = my_strlen(buf);
1606 rv = write(server_list[server].write, CP(buf), len);
1607 new_free(&buf);
1608 if (rv != len)
1609 {
1610 yell("--- proxy login failed.");
1611 Debug(DB_PROXY, "proxy write failed, closing.");
1612 goto failed_recover;
1613 }
1614
1615 server_list[server].flags |= PROXY_CONNECT;
1616 Debug(DB_PROXY, "proxy: send CONNECT %s:%d (from_server = %d)",
1617 server_list[server].name, server_list[server].port, from_server);
1618
1619 /* XXX need to eat HTTP reply, before doing final login */
1620 return;
1621 }
1622
1623 /*
1624 * if we've sent proxy stuff, but haven't completed it yet, we
1625 * need to eat the HTTP reply.
1626 */
1627 if ((server_list[server].flags & PROXY_CONNECT) != 0 &&
1628 (server_list[server].flags & PROXY_DONE) == 0)
1629 {
1630 u_char lbuf[BIG_BUFFER_SIZE];
1631 u_char *bufptr;
1632 u_char *s;
1633 int old_timeout;
1634 int junk;
1635 size_t len;
1636
1637 old_timeout = dgets_timeout(1);
1638 s = server_list[server].buffer;
1639 bufptr = lbuf;
1640 if (s && *s)
1641 {
1642 len = my_strlen(s);
1643 if (len >= sizeof(lbuf))
1644 goto buffer_is_full_hack;
1645 my_strncpy(lbuf, s, len);
1646 bufptr += len;
1647 }
1648 else
1649 len = 0;
1650 junk = dgets(bufptr, sizeof(lbuf) - len, server_list[server].read);
1651 (void) dgets_timeout(old_timeout);
1652
1653 switch (junk)
1654 {
1655 case -2:
1656 /* shouldn't happen! SSL retry */
1657 yell("--- proxy http reponse got -2 / SSL retry!?");
1658 Debug(DB_PROXY, "proxy http reponse got -2 / SSL retry, closing.");
1659 goto failed_recover;
1660 case -1:
1661 Debug(DB_PROXY, "added \"%s\" to the server buffer for proxy.", lbuf);
1662 add_to_server_buffer(server, lbuf);
1663 return;
1664 case 0:
1665 goto failed_recover;
1666 default:
1667 buffer_is_full_hack:
1668 switch (server_check_http_response(server, lbuf, sizeof lbuf))
1669 {
1670 case -1:
1671 Debug(DB_PROXY, "got retry on http response server %d", server);
1672 return;
1673 case 0:
1674 Debug(DB_PROXY, "proxy setup complete, server %d!", server);
1675 server_list[server].flags |= PROXY_DONE;
1676 return;
1677 case 1:
1678 yell("--- proxy http login failed, closing");
1679 Debug(DB_PROXY, "proxy http login failed, closing server %d", server);
1680 goto failed_recover;
1681 default:
1682 yell("--- help! this shouldn't happen. not -1/0/1");
1683 goto failed_recover;
1684 }
1685 }
1686 }
1687
1688 status = server_check_ssl(server);
1689 if (status == SSL_INIT_PENDING)
1690 {
1691 return;
1692 }
1693 if (status == SSL_INIT_FAIL)
1694 {
1695 int old_serv;
1696 int logged_in;
1697
1698 Debug(DB_SERVER, "SSL failed, closing.");
1699 failed_recover:
1700 old_serv = server_list[server].close_serv;
1701 logged_in = server_list[server].flags & LOGGED_IN;
1702
1703 close_server(server, UP("proxy/SSL Failed."));
1704 if (!logged_in && old_serv != -1 && old_serv != server)
1705 reestablish_close_server(server, old_serv);
1706 return;
1707 }
1708 server_list[server].flags |= LOGGED_IN;
1709 login_to_server_nonblocking(server);
1710 if (server_get_version(server) == ServerICB)
1711 icb_login_to_server(server);
1712 else
1713 irc2_login_to_server(server);
1714 window_copy_prev_server(server);
1715 }
1716
1717 static void
irc2_login_to_server(int server)1718 irc2_login_to_server(int server)
1719 {
1720 if (server_get_version(server) == ServerICB)
1721 {
1722 yell("--- ICB called irc2_login_to_server???");
1723 return;
1724 }
1725
1726 if (server_list[server].password)
1727 send_to_server("PASS %s", server_list[server].password);
1728 send_to_server("NICK %s", server_list[server].nickname);
1729 send_to_server("USER %s %s %s :%s", my_username(), irc_umode(),
1730 server_list[server].name, my_realname());
1731 }
1732
1733 /*
1734 * get_connected: This function connects the primary server for IRCII. It
1735 * attempts to connect to the given server. If this isn't possible, it
1736 * traverses the server list trying to keep the user connected at all cost.
1737 * oldconn is set if this connection is really an old connection being
1738 * resurected (eg. connection to server failed).
1739 */
1740 void
get_connected(int server)1741 get_connected(int server)
1742 {
1743 int s,
1744 ret = -1;
1745
1746 if (server_list)
1747 {
1748 int already_connected = 0;
1749
1750 if (server == number_of_servers())
1751 server = 0;
1752 else if (server < 0)
1753 server = number_of_servers() - 1;
1754 s = server;
1755 if (reconnect_to_server(server, primary_server))
1756 {
1757 while (server_list[server].read == -1)
1758 {
1759 server++;
1760 if (server == number_of_servers())
1761 server = 0;
1762 if (server == s)
1763 {
1764 clean_whois_queue();
1765 say("Use /SERVER to connect to a server");
1766 break;
1767 }
1768 from_server = server;
1769 already_connected = is_server_connected(server);
1770 ret = reconnect_to_server(server, primary_server);
1771 }
1772 if (!ret)
1773 from_server = server;
1774 else
1775 from_server = -1;
1776 }
1777 if (from_server != -1) {
1778 int flags;
1779
1780 flags = (already_connected ? 0 : WIN_TRANSFER);
1781 window_set_server(-1, from_server, flags);
1782 }
1783 }
1784 else
1785 {
1786 clean_whois_queue();
1787 say("Use /SERVER to connect to a server");
1788 }
1789 }
1790
1791 /*
1792 * read_server_file: reads hostname:portnum:password server information from
1793 * a file and adds this stuff to the server list. See build_server_list()/
1794 */
1795 int
read_server_file(void)1796 read_server_file(void)
1797 {
1798 FILE *fp;
1799 u_char format[11];
1800 u_char *file_path;
1801 u_char *free_path = NULL;
1802 u_char buffer[FS_BUFFER_SIZE];
1803
1804 if ((file_path = my_getenv("IRCSERVERSFILE")) == NULL)
1805 {
1806 malloc_strcpy(&free_path, my_irc_lib());
1807 malloc_strcat(&free_path, UP(SERVERS_FILE));
1808 file_path = free_path;
1809 }
1810 snprintf(CP(format), sizeof format, "%%%ds", (int)sizeof buffer);
1811 fp = fopen(CP(file_path), "r");
1812 new_free(&free_path);
1813 if (NULL != fp)
1814 {
1815 while (fscanf(fp, CP(format), buffer) != EOF)
1816 build_server_list(buffer);
1817 fclose(fp);
1818 return (0);
1819 }
1820 return (1);
1821 }
1822
1823 /* display_server_list: just guess what this does */
1824 void
display_server_list(void)1825 display_server_list(void)
1826 {
1827 int i;
1828
1829 if (from_server >= number_of_servers())
1830 from_server = -1;
1831
1832 if (server_list)
1833 {
1834 if (from_server != -1)
1835 say("Current server: %s %d",
1836 server_list[from_server].name,
1837 server_list[from_server].port);
1838 else
1839 say("Current server: <None>");
1840 if (primary_server != -1)
1841 say("Primary server: %s %d",
1842 server_list[primary_server].name,
1843 server_list[primary_server].port);
1844 else
1845 say("Primary server: <None>");
1846 if (client_default_is_icb())
1847 say("Using ICB connections by default");
1848 if (default_proxy_name)
1849 say("Using proxy server: %s port %d by default",
1850 default_proxy_name, default_proxy_port);
1851 say("Server list:");
1852 for (i = 0; i < number_of_servers(); i++)
1853 {
1854 u_char *proxy_msg = NULL;
1855 u_char *icb_msg;
1856 u_char *group_msg = NULL;
1857 u_char *pname = NULL;
1858 const u_char *ssl_val;
1859 int pport = 0;
1860
1861 switch (server_list[i].ssl_level) {
1862 case SSL_ON:
1863 ssl_val = UP(" (with unchecked TLS)");
1864 break;
1865 case SSL_VERIFY:
1866 ssl_val = UP(" (with TLS)");
1867 break;
1868 default:
1869 ssl_val = empty_string();
1870 break;
1871 }
1872
1873 icb_msg = server_list[i].version == ServerICB ?
1874 (u_char *) " (ICB connection)" : empty_string();
1875 if (server_list[i].server_group)
1876 malloc_snprintf(&group_msg, " [group: %s]",
1877 find_server_group_name(server_list[i].server_group));
1878 else
1879 malloc_strcat(&group_msg, empty_string());
1880
1881 pport = server_get_proxy_port(i, 0);
1882 if (pport == -1)
1883 malloc_snprintf(&proxy_msg, " (no proxy)");
1884 else if ((pname = server_get_proxy_name(i, 0)))
1885 malloc_snprintf(&proxy_msg,
1886 " (proxy on server %s port %d)",
1887 pname, pport);
1888 else
1889 malloc_strcat(&proxy_msg, empty_string());
1890
1891 if (!server_list[i].nickname)
1892 {
1893 say("\t%d) %s %d%s%s%s%s%s", i,
1894 server_list[i].name,
1895 server_list[i].port,
1896 server_list[i].read == -1 ?
1897 UP(" (not connected)") : empty_string(),
1898 group_msg,
1899 icb_msg,
1900 proxy_msg,
1901 ssl_val);
1902 }
1903 else
1904 {
1905 say("\t%d) %s %d (%s%s)%s%s%s%s", i,
1906 server_list[i].name,
1907 server_list[i].port,
1908 (server_list[i].read == -1) ?
1909 UP("was ") : empty_string(),
1910 server_list[i].nickname,
1911 group_msg,
1912 icb_msg,
1913 proxy_msg,
1914 ssl_val);
1915 }
1916 new_free(&proxy_msg);
1917 new_free(&group_msg);
1918 #ifdef GKM
1919 say("\t\tflags: %s%s%s%s%s%s%s",
1920 server_list[i].flags & SERVER_2_6_2 ? UP("SERVER_2_6_2 ") : empty_string(),
1921 server_list[i].flags & USER_MODE_I ? UP("USER_MODE_I ") : empty_string(),
1922 server_list[i].flags & USER_MODE_W ? UP("USER_MODE_W ") : empty_string(),
1923 server_list[i].flags & USER_MODE_S ? UP("USER_MODE_S ") : empty_string(),
1924 server_list[i].flags & CLOSE_PENDING ? UP("CLOSE_PENDING ") : empty_string(),
1925 server_list[i].flags & CLEAR_PENDING ? UP("CLEAR_PENDING ") : empty_string(),
1926 server_list[i].flags & LOGGED_IN ? UP("LOGGED_IN ") : empty_string() );
1927 say("\t\tclose_serv=%d, connected=%d, read=%d, eof=%d", server_list[i].close_serv, server_list[i].connected, server_list[i].read, server_list[i].eof);
1928 #endif /* GKM */
1929 }
1930 }
1931 else
1932 say("The server list is empty");
1933 }
1934
1935 void
mark_all_away(u_char * command,u_char * message)1936 mark_all_away(u_char *command, u_char *message)
1937 {
1938 int old_server;
1939
1940 old_server = from_server;
1941 for (from_server = 0; from_server < number_of_servers(); from_server++)
1942 {
1943 if (is_server_connected(from_server))
1944 send_to_server("%s :%s", command, message);
1945 }
1946 from_server = old_server;
1947 }
1948
1949
1950 /*
1951 * server_set_password: this sets the password for the server with the given
1952 * index. If password is null, the password for the given server is returned
1953 */
1954 u_char *
server_set_password(int server_index,u_char * password)1955 server_set_password(int server_index, u_char *password)
1956 {
1957
1958 if (server_list)
1959 {
1960 if (password)
1961 malloc_strcpy(&(server_list[server_index].password), password);
1962 return (server_list[server_index].password);
1963 }
1964 else
1965 return (NULL);
1966 }
1967
1968 /*
1969 * ICB support
1970 */
1971 void
server_set_icbgroup(int server_index,u_char * group)1972 server_set_icbgroup(int server_index, u_char *group)
1973 {
1974
1975 malloc_strcpy(&server_list[server_index].group, group);
1976 }
1977
1978 void
server_set_icbmode(int server_index,u_char * mode)1979 server_set_icbmode(int server_index, u_char *mode)
1980 {
1981
1982 malloc_strcpy(&server_list[server_index].icbmode, mode);
1983 }
1984
1985 /*
1986 * server: the /SERVER command. Read the SERVER help page about
1987 */
1988 void
servercmd(u_char * command,u_char * args,u_char * subargs)1989 servercmd(u_char *command, u_char *args, u_char *subargs)
1990 {
1991 u_char *server,
1992 *port,
1993 *proxy_name = NULL,
1994 *proxy_port_str = NULL,
1995 *extra,
1996 *newmode,
1997 *password = NULL,
1998 *nick = NULL,
1999 *group = NULL;
2000 int port_num,
2001 proxy_port = 0,
2002 i,
2003 new_server_flags,
2004 type = -1;
2005 server_ssl_level level = SSL_UNKNOWN;
2006
2007 if ((server = next_arg(args, &args)) != NULL)
2008 {
2009 while (*server == '-')
2010 {
2011 size_t len;
2012
2013 /*
2014 * old usage of `/server -' handled here.
2015 */
2016 if (*++server == '\0')
2017 {
2018 get_connected(primary_server - 1);
2019 return;
2020 }
2021 upper(server);
2022 len = my_strlen(server);
2023 /*
2024 * just don't return if you want to perform some action in one of
2025 * the flag handling sections.
2026 */
2027 if (!my_strncmp(server, "ICB", len))
2028 type = ServerICB;
2029 else if (!my_strncmp(server, "IRC", len))
2030 type = DEFAULT_SERVER_VERSION;
2031 else if (!my_strncmp(server, "SSL", len))
2032 level = SSL_VERIFY;
2033 else if (!my_strncmp(server, "SSLNOCHECK", len))
2034 level = SSL_ON;
2035 else if (!my_strncmp(server, "NOSSL", len))
2036 level = SSL_OFF;
2037 else if (!my_strncmp(server, "DELETE", len))
2038 {
2039 if ((server = next_arg(args, &args)) != NULL)
2040 {
2041 if ((i = parse_server_index(server)) == -1)
2042 {
2043 if (-1 == (i = find_in_server_list(server, 0, 0)))
2044 {
2045 say("No such server in list");
2046 return;
2047 }
2048 }
2049 if (server_list[i].connected)
2050 {
2051 say("Can not delete server that is already open");
2052 return;
2053 }
2054 remove_from_server_list(i);
2055 return;
2056 }
2057 say("Need server number for -DELETE");
2058 return;
2059 }
2060 else if (!my_strncmp(server, "GROUP", len))
2061 {
2062 if ((group = next_arg(args, &args)) == NULL)
2063 {
2064 say("SERVER -GROUP needs <group> and <server>");
2065 return;
2066 }
2067 }
2068 else if (!my_strncmp(server, "PROXY", len))
2069 {
2070 if ((proxy_name = next_arg(args, &args)) == NULL ||
2071 (proxy_port_str = next_arg(args, &args)) == NULL)
2072 {
2073 say("SERVER -PROXY needs <proxy> and <host>");
2074 return;
2075 }
2076 proxy_port = my_atoi(proxy_port_str);
2077 }
2078 else
2079 {
2080 say("SERVER: %s is an unknown flag", server);
2081 return;
2082 }
2083 if ((server = next_arg(args, &args)) == NULL)
2084 {
2085 say("SERVER: need a server name");
2086 return;
2087 }
2088 }
2089
2090 if (my_index(server, ':') != NULL)
2091 {
2092 parse_server_info(&server, &port, &password, &nick,
2093 group ? 0 : &group, &extra, &type, &level,
2094 &proxy_name, &proxy_port);
2095 if (!my_strlen(server))
2096 {
2097 say("Server name required");
2098 return;
2099 }
2100 if (port && *port) {
2101 port_num = my_atoi(port);
2102 if (!port_num)
2103 port_num = CHOOSE_PORT(type);
2104 } else
2105 /* consider port = next_arg() */
2106 port_num = CHOOSE_PORT(type);
2107 }
2108 else
2109 {
2110 if ((port = next_arg(args, &args)) != NULL)
2111 {
2112 port_num = my_atoi(port);
2113 if (!port_num)
2114 port_num = CHOOSE_PORT(type);
2115 if ((password = next_arg(args, &args)) != NULL)
2116 nick = next_arg(args, &args);
2117 }
2118 else
2119 port_num = CHOOSE_PORT(type);
2120
2121 if (level == SSL_UNKNOWN)
2122 level = irc_ssl_level;
2123 extra = NULL;
2124 }
2125
2126 /*
2127 * We need to not do this in the case "server" is really a
2128 * valid server number.
2129 */
2130 if (parse_server_index(server) == -1)
2131 add_to_server_list(server, port_num,
2132 proxy_name, proxy_port, password,
2133 nick, -1, type,
2134 ssl_level_to_sa_flags(level));
2135
2136 if (group && *group)
2137 server_list[from_server].server_group = find_server_group(group, 1);
2138
2139 if (extra && type == ServerICB)
2140 {
2141 if ((newmode = my_index(extra, ':')))
2142 {
2143 *newmode++ = 0;
2144 malloc_strcpy(&(server_list[from_server].icbmode), newmode);
2145 }
2146 malloc_strcpy(&(server_list[from_server].group), extra);
2147 }
2148
2149 if (*server == '+' || *server == '=' || *server == '~')
2150 {
2151 if (group)
2152 add_server_to_server_group(
2153 window_get_server(curr_scr_win), group);
2154
2155 if (*(server+1))
2156 {
2157 u_char servinfo[INPUT_BUFFER_SIZE+1];
2158
2159 if (*server == '+')
2160 server++;
2161 /* Reconstitute whole server info so
2162 window_get_connected can parse it -Sol */
2163 snprintf(CP(servinfo), sizeof servinfo, "%s:%d:%s:%s",
2164 server, port_num,
2165 password ? password : empty_string(),
2166 nick ? nick : empty_string());
2167 window_get_connected(curr_scr_win, servinfo,
2168 -1, NULL, proxy_name, proxy_port,
2169 group, type, level);
2170 }
2171 else
2172 get_connected(primary_server + 1);
2173 return;
2174 }
2175 /*
2176 * work in progress.. window_get_prev_server() needs to be set for
2177 * all windows that used to be associated with a server as it
2178 * switches [successfully] to a new server.
2179 * this'll be fun since that can happen in server.c and
2180 * window.c and non-blocking-connects will throw yet another
2181 * wrench into things since we only want it to happen on
2182 * a successful connect. - gkm
2183 */
2184 else if (*server == '.')
2185 {
2186 if (*(++server))
2187 {
2188 say("syntax error - nothing may be specified after the '.'");
2189 return;
2190 }
2191 if (get_current_screen() && curr_scr_win &&
2192 (i = window_get_prev_server(curr_scr_win)) != -1)
2193 {
2194 if (group)
2195 add_server_to_server_group(i, group);
2196
2197 window_restore_server(i);
2198 if (!proxy_name && server_list[i].proxy_name)
2199 proxy_name = server_list[i].proxy_name;
2200 if (proxy_port == 0 && server_list[i].proxy_port)
2201 proxy_port = server_list[i].proxy_port;
2202 window_get_connected(curr_scr_win, NULL,
2203 window_get_server(curr_scr_win), NULL,
2204 proxy_name, proxy_port,
2205 group, type, level);
2206 }
2207 else
2208 say("No server previously in use in this window");
2209 return;
2210 }
2211 if ((i = parse_server_index(server)) != -1)
2212 {
2213 server = server_list[i].name;
2214 if (server_list[i].port != -1)
2215 port_num = server_list[i].port;
2216 if (server_list[i].nickname && !nick)
2217 nick = server_list[i].nickname;
2218 }
2219 else
2220 i = find_in_server_list(server, port_num, nick);
2221
2222 if (group)
2223 add_server_to_server_group(i, group);
2224
2225 if (is_server_connected(i))
2226 {
2227 /*
2228 * We reset the log level only if the "new" server
2229 * already has windows associated with it : here it's
2230 * equivalent to its already being connected. -Sol
2231 */
2232 new_server_flags = 0;
2233 }
2234 else
2235 new_server_flags = WIN_TRANSFER;
2236 if (connect_to_server(server, port_num, nick, primary_server) != -1)
2237 {
2238 if (primary_server > -1 && from_server != primary_server &&
2239 !server_list[from_server].away &&
2240 server_list[primary_server].away)
2241 malloc_strcpy(&server_list[from_server].away,
2242 server_list[primary_server].away);
2243 window_set_server(-1, from_server, new_server_flags);
2244 }
2245 }
2246 else
2247 display_server_list();
2248 }
2249
2250 /*
2251 * flush_server: eats all output from server, until there is at least a
2252 * second delay between bits of servers crap... useful to abort a /links.
2253 */
2254 void
flush_server(void)2255 flush_server(void)
2256 {
2257 fd_set rd;
2258 struct timeval time_out;
2259 int flushing = 1;
2260 int des;
2261 int old_timeout;
2262 u_char buffer[BIG_BUFFER_SIZE];
2263
2264 if ((des = server_list[from_server].read) == -1)
2265 return;
2266 time_out.tv_usec = 0;
2267 time_out.tv_sec = 1;
2268 old_timeout = dgets_timeout(1);
2269 while (flushing)
2270 {
2271 FD_ZERO(&rd);
2272 FD_SET(des, &rd);
2273 switch (new_select(&rd, NULL, &time_out))
2274 {
2275 case -1:
2276 case 0:
2277 flushing = 0;
2278 break;
2279 default:
2280 if (FD_ISSET(des, &rd))
2281 {
2282 switch (dgets(buffer, sizeof buffer, des))
2283 {
2284 case -2:
2285 /* SSL retry */
2286 break;
2287 case -1:
2288 case 0:
2289 flushing = 0;
2290 break;
2291 default:
2292 break;
2293 }
2294 }
2295 break;
2296 }
2297 }
2298 /* make sure we've read a full line from server */
2299 FD_ZERO(&rd);
2300 FD_SET(des, &rd);
2301 if (new_select(&rd, NULL, &time_out) > 0)
2302 dgets(buffer, sizeof buffer, des);
2303 (void) dgets_timeout(old_timeout);
2304 }
2305
2306 /*
2307 * server_set_whois: sets the whois value for the given server index. If the
2308 * whois value is 0, it assumes the server doesn't send End of WHOIS commands
2309 * and the whois.c routines use the old fashion way of getting whois info. If
2310 * the whois value is non-zero, then the server sends End of WHOIS and things
2311 * can be done more effienciently
2312 */
2313 void
server_set_whois(int server_index,int value)2314 server_set_whois(int server_index, int value)
2315 {
2316 server_list[server_index].whois = value;
2317 }
2318
2319 /* server_get_whois: Returns the whois value for the given server index */
2320 int
server_get_whois(int server_index)2321 server_get_whois(int server_index)
2322 {
2323 if (server_index == -1)
2324 server_index = primary_server;
2325 return (server_list[server_index].whois);
2326 }
2327
2328
2329 void
server_set_2_6_2(int server_index,int value)2330 server_set_2_6_2(int server_index, int value)
2331 {
2332 server_set_flag(server_index, SERVER_2_6_2, value);
2333 }
2334
2335 int
server_get_2_6_2(int server_index)2336 server_get_2_6_2(int server_index)
2337 {
2338 if (server_index == -1)
2339 server_index = primary_server;
2340 return (server_get_flag(server_index, SERVER_2_6_2));
2341 }
2342
2343 void
server_set_flag(int server_index,int flag,int value)2344 server_set_flag(int server_index, int flag, int value)
2345 {
2346 if (server_index == -1)
2347 server_index = primary_server;
2348 if (value)
2349 server_list[server_index].flags |= flag;
2350 else
2351 server_list[server_index].flags &= ~flag;
2352 }
2353
2354 int
server_get_flag(int server_index,int value)2355 server_get_flag(int server_index, int value)
2356 {
2357 if (server_index == -1)
2358 server_index = primary_server;
2359 return server_list[server_index].flags & value;
2360 }
2361
2362 /* get ICB group */
2363 u_char *
server_get_icbgroup(int server_index)2364 server_get_icbgroup(int server_index)
2365 {
2366 u_char *group;
2367
2368 if (server_index == -1)
2369 server_index = primary_server;
2370 group = server_list[server_index].group ? server_list[server_index].group : empty_string();
2371 return (group);
2372 }
2373
2374 /* get ICB mode */
2375 u_char *
server_get_icbmode(int server_index)2376 server_get_icbmode(int server_index)
2377 {
2378 u_char *mode;
2379
2380 if (server_index == -1)
2381 server_index = primary_server;
2382 mode = server_list[server_index].icbmode ? server_list[server_index].icbmode : empty_string();
2383 return (mode);
2384 }
2385
2386 /*
2387 * server_get_password: get the passwor for this server.
2388 */
2389 u_char *
server_get_password(int server_index)2390 server_get_password(int server_index)
2391 {
2392 if (server_index == -1)
2393 server_index = primary_server;
2394 return (server_list[server_index].password);
2395 }
2396
2397 /*
2398 * server_set_version: Sets the server version for the given server type. A
2399 * zero version means pre 2.6, a one version means 2.6 aso. (look server.h
2400 * for typedef)
2401 */
2402 void
server_set_version(int server_index,int version)2403 server_set_version(int server_index, int version)
2404 {
2405 if (server_index == -1)
2406 server_index = primary_server;
2407 server_list[server_index].version = version;
2408 }
2409
2410 /*
2411 * server_get_version: returns the server version value for the given server
2412 * index
2413 */
2414 int
server_get_version(int server_index)2415 server_get_version(int server_index)
2416 {
2417 if (server_index == -1)
2418 server_index = primary_server;
2419 if (server_index == -1)
2420 return DEFAULT_SERVER_VERSION;
2421 else
2422 return (server_list[server_index].version);
2423 }
2424
2425 /* server_get_name: returns the name for the given server index */
2426 u_char *
server_get_name(int server_index)2427 server_get_name(int server_index)
2428 {
2429 if (server_index == -1)
2430 server_index = primary_server;
2431 return (server_list[server_index].name);
2432 }
2433
2434 /* server_set_itsname: returns the server's idea of its name */
2435 u_char *
server_get_itsname(int server_index)2436 server_get_itsname(int server_index)
2437 {
2438 if (server_index == -1)
2439 server_index = primary_server;
2440 if (server_list[server_index].itsname)
2441 return server_list[server_index].itsname;
2442 else if (server_list[server_index].name)
2443 return server_list[server_index].name;
2444 else
2445 return UP("<None>");
2446 }
2447
2448 void
server_set_itsname(int server_index,u_char * name)2449 server_set_itsname(int server_index, u_char *name)
2450 {
2451 if (server_index == -1)
2452 server_index = primary_server;
2453 malloc_strcpy(&server_list[server_index].itsname, name);
2454 }
2455
2456 /*
2457 * is_server_open: Returns true if the given server index represents a server
2458 * with a live connection, returns false otherwise
2459 */
2460 int
is_server_open(int server_index)2461 is_server_open(int server_index)
2462 {
2463 if (server_index < 0)
2464 return (0);
2465 return (server_list[server_index].read != -1);
2466 }
2467
2468 /*
2469 * is_server_connected: returns true if the given server is connected. This
2470 * means that both the tcp connection is open and the user is properly
2471 * registered
2472 */
2473 int
is_server_connected(int server_index)2474 is_server_connected(int server_index)
2475 {
2476 if (server_index < 0)
2477 return (0);
2478 return (server_list[server_index].connected && (server_list[server_index].flags & LOGGED_IN));
2479 }
2480
2481 /* server_get_port: Returns the connection port for the given server index */
2482 int
server_get_port(int server_index)2483 server_get_port(int server_index)
2484 {
2485 if (server_index == -1)
2486 server_index = primary_server;
2487 return (server_list[server_index].port);
2488 }
2489
2490 /*
2491 * server_get_nickname: returns the current nickname for the given server
2492 * index
2493 */
2494 u_char *
server_get_nickname(int server_index)2495 server_get_nickname(int server_index)
2496 {
2497 if ((server_index != -1) && server_list[server_index].nickname)
2498 return (server_list[server_index].nickname);
2499 else
2500 return my_nickname();
2501 }
2502
2503
2504
2505 /* server_get_qhead - get the head of the whois queue */
2506 WhoisQueue *
server_get_qhead(int server_index)2507 server_get_qhead(int server_index)
2508 {
2509 if (server_index >= 0)
2510 return server_list[server_index].WQ_head;
2511 return NULL;
2512 }
2513
2514 /* server_get_whois_stuff */
2515 WhoisStuff *
server_get_whois_stuff(int server_index)2516 server_get_whois_stuff(int server_index)
2517 {
2518 if (server_index >= 0)
2519 return &server_list[server_index].whois_stuff;
2520 return NULL;
2521 }
2522
2523 /* server_get_qtail - get the tail of the whois queue */
2524 WhoisQueue *
server_get_qtail(int server_index)2525 server_get_qtail(int server_index)
2526 {
2527 if (server_index >= 0)
2528 return server_list[server_index].WQ_tail;
2529 return NULL;
2530 }
2531
2532
2533 /* server_set_qhead - set the head of the whois queue */
2534 void
server_set_qhead(int server_index,WhoisQueue * value)2535 server_set_qhead(int server_index, WhoisQueue *value)
2536 {
2537 if (server_index >= 0)
2538 server_list[server_index].WQ_head = value;
2539 }
2540
2541 /* server_set_qtail - set the tail of the whois queue */
2542 void
server_set_qtail(int server_index,WhoisQueue * value)2543 server_set_qtail(int server_index, WhoisQueue *value)
2544 {
2545 if (server_index >= 0)
2546 server_list[server_index].WQ_tail = value;
2547 }
2548
2549
2550 /*
2551 * server_get_operator: returns true if the user has op privs on the server,
2552 * false otherwise
2553 */
2554 int
server_get_operator(int server_index)2555 server_get_operator(int server_index)
2556 {
2557 return (server_list[server_index].operator);
2558 }
2559
2560 /*
2561 * server_set_operator: If flag is non-zero, marks the user as having op
2562 * privs on the given server.
2563 */
2564 void
server_set_operator(int server_index,int flag)2565 server_set_operator(int server_index, int flag)
2566 {
2567 server_list[server_index].operator = flag;
2568 }
2569
2570 /*
2571 * server_set_nickname: sets the nickname for the given server to nickname.
2572 * This nickname is then used for all future connections to that server
2573 * (unless changed with NICK while connected to the server
2574 */
2575 void
server_set_nickname(int server_index,u_char * nick)2576 server_set_nickname(int server_index, u_char *nick)
2577 {
2578 if (server_index >= 0)
2579 {
2580 malloc_strcpy(&(server_list[server_index].nickname), nick);
2581 if (server_index == primary_server)
2582 set_nickname(nick);
2583 }
2584 update_all_status();
2585 }
2586
2587 void
server_set_motd(int server_index,int flag)2588 server_set_motd(int server_index, int flag)
2589 {
2590 if (server_index >= 0)
2591 server_list[server_index].motd = flag;
2592 }
2593
2594 int
server_get_motd(int server_index)2595 server_get_motd(int server_index)
2596 {
2597 if (server_index >= 0)
2598 return(server_list[server_index].motd);
2599 return (0);
2600 }
2601
2602 void
server_is_connected(int server_index,int value)2603 server_is_connected(int server_index, int value)
2604 {
2605 server_list[server_index].connected = value;
2606 if (value)
2607 server_list[server_index].eof = 0;
2608 }
2609
2610 /* send_to_server: sends the given info the the server */
2611 void
send_to_server(const char * format,...)2612 send_to_server(const char *format, ...)
2613 {
2614 static int in_send_to_server = 0;
2615 u_char lbuf[BIG_BUFFER_SIZE]; /* make this buffer *much*
2616 * bigger than needed */
2617 u_char *buf = lbuf;
2618 int des;
2619 size_t len;
2620 int server = from_server;
2621 va_list vlist;
2622
2623 va_start(vlist, format);
2624
2625 if (in_send_to_server)
2626 return;
2627 //memset(lbuf, 0, sizeof(lbuf));
2628 in_send_to_server = 1;
2629 if (server == -1)
2630 server = primary_server;
2631 if (server != -1 && ((des = server_list[server].write) != -1) &&
2632 (server_list[server].flags & LOGGED_IN) )
2633 {
2634 /* save space for the packet length */
2635 if (server_get_version(server) == ServerICB)
2636 buf++;
2637 server_list[server].sent = 1;
2638 vsnprintf(CP(buf), sizeof lbuf, format, vlist);
2639 va_end(vlist);
2640 len = my_strlen(buf);
2641 if (len > (IRCD_BUFFER_SIZE - 2))
2642 lbuf[IRCD_BUFFER_SIZE - 2] = '\0';
2643 /*
2644 * for ICB, we send a final nul, and for IRC, we have
2645 * a final newline.
2646 */
2647 len++;
2648 if (do_hook(RAW_SEND_LIST, "%s", lbuf))
2649 {
2650 if (server_get_version(server) == ServerICB)
2651 {
2652 /*
2653 * we depend on our caller to split things
2654 * up for the ICB server
2655 */
2656 if (len > 254)
2657 len = 254;
2658 lbuf[len] = 0;
2659 lbuf[0] = (u_char)len;
2660 lbuf[++len] = 0;
2661 }
2662 else
2663 my_strmcat(buf, "\n", IRCD_BUFFER_SIZE);
2664
2665 /* XXX retval */
2666 ssl_write(server_list[server].ssl_info,
2667 server_list[server].write, CP(lbuf), len);
2668 }
2669 }
2670 else if (!in_redirect() && !connected_to_server())
2671 say("You are not connected to a server, use /SERVER to connect.");
2672 in_send_to_server = 0;
2673 }
2674
2675 #ifdef HAVE_SYS_UN_H
2676 /*
2677 * Connect to a UNIX domain socket. Only works for servers.
2678 * submitted by Avalon for use with server 2.7.2 and beyond.
2679 */
2680 int
connect_to_unix(int port,u_char * path)2681 connect_to_unix(int port, u_char *path)
2682 {
2683 struct sockaddr_un un;
2684 int sock;
2685
2686 sock = socket(AF_UNIX, SOCK_STREAM, 0);
2687
2688 un.sun_family = AF_UNIX;
2689 if (snprintf(un.sun_path, sizeof un.sun_path, "%-.100s/%-.6d", path, port) != sizeof un.sun_path)
2690 {
2691 yell("--- sun_path truncated: wanted '%-.100s/%-.6d'", path, port);
2692 }
2693
2694 if (connect(sock, (struct sockaddr *)&un, (int)my_strlen(path)+2) == -1)
2695 {
2696 new_close(sock);
2697 return -1;
2698 }
2699 return sock;
2700 }
2701 #endif /* HAVE_SYS_UN_H */
2702
2703 /*
2704 * close_all_server: Used whn creating new screens to close all the open
2705 * server connections in the child process...
2706 */
2707 void
close_all_server(void)2708 close_all_server(void)
2709 {
2710 int i;
2711
2712 for (i = 0; i < number_of_servers(); i++)
2713 {
2714 if (server_list[i].read != -1)
2715 new_close(server_list[i].read);
2716 if (server_list[i].write != -1)
2717 new_close(server_list[i].write);
2718 }
2719 }
2720
2721 u_char *
create_server_list(void)2722 create_server_list(void)
2723 {
2724 int i;
2725 u_char *value = NULL;
2726 StringList *sl;
2727
2728 sl = sl_init();
2729 for (i = 0; i < number_of_servers(); i++)
2730 if (server_list[i].read != -1)
2731 sl_add(sl, CP(server_get_itsname(i)));
2732 value = sl_concat(sl, UP(" "));
2733 sl_free(sl, 0);
2734
2735 return value;
2736 }
2737
2738 static void
add_to_server_buffer(int server,u_char * buf)2739 add_to_server_buffer(int server, u_char *buf)
2740 {
2741 if (buf && *buf)
2742 {
2743 if (server_list[server].buffer)
2744 malloc_strcat(&server_list[server].buffer, buf);
2745 else
2746 malloc_strcpy(&server_list[server].buffer, buf);
2747 }
2748 }
2749
2750 void
disconnectcmd(u_char * command,u_char * args,u_char * subargs)2751 disconnectcmd(u_char *command, u_char *args, u_char *subargs)
2752 {
2753 u_char *server;
2754 u_char *message;
2755 int i;
2756 int old_serv;
2757
2758 if ((server = next_arg(args, &args)) != NULL && server[0] != '*' && server[1] != '\0')
2759 {
2760 i = parse_server_index(server);
2761 if (-1 == i)
2762 {
2763 say("No such server!");
2764 return;
2765 }
2766 }
2767 else
2768 i = get_window_server(0);
2769 /*
2770 * XXX - this is a major kludge. i should never equal -1 at
2771 * this point. we only do this because something has gotten
2772 * *really* confused at this point. .mrg.
2773 */
2774 if (i == -1)
2775 {
2776 for (i = 0; i < number_of_servers(); i++)
2777 {
2778 server_list[i].eof = -1;
2779 server_list[i].connected = 0;
2780 new_close(server_list[i].read);
2781 new_close(server_list[i].write);
2782 }
2783 goto done;
2784 }
2785 if (!args || !*args)
2786 message = UP("Disconnecting");
2787 else
2788 message = args;
2789 if (-1 == server_list[i].write)
2790 {
2791 say("That server isn't connected!");
2792 return;
2793 }
2794 server = server_list[i].itsname ? server_list[i].itsname :
2795 server_list[i].name ? server_list[i].name : (u_char *) "unknown?";
2796 say("Disconnecting from server %s", server);
2797 old_serv = server_list[i].close_serv;
2798 close_server(i, message);
2799 server_list[i].eof = 1;
2800 if (old_serv != -1 && old_serv != i)
2801 {
2802 Window *tmp;
2803 Win_Trav wt;
2804
2805 say("Connection to server %s resumed...", server_list[old_serv].name);
2806 server_list[i].close_serv = -1;
2807 server_list[old_serv].flags &= ~(CLOSE_PENDING|CLEAR_PENDING);
2808 server_list[old_serv].flags |= LOGGED_IN;
2809 server_list[old_serv].connected = 1;
2810 wt.init = 1;
2811 while ((tmp = window_traverse(&wt)))
2812 if (window_get_server(tmp) == i)
2813 {
2814 window_set_server(window_get_refnum(tmp), old_serv, WIN_ALL);
2815 break;
2816 }
2817 }
2818 done:
2819 clean_whois_queue();
2820 window_check_servers();
2821 if (!connected_to_server())
2822 say("You are not connected to a server. Use /SERVER to connect.");
2823 }
2824
2825 /*
2826 * parse_server: feed this line into the right server parser
2827 */
2828 static void
parse_server(u_char * line)2829 parse_server(u_char *line)
2830 {
2831 server_list[parsing_server_index].parse_server(line);
2832 }
2833
2834 int
server_get_server_group(int server_index)2835 server_get_server_group(int server_index)
2836 {
2837 if (server_index < 0 && server_index >= number_of_servers())
2838 server_index = from_server;
2839
2840 return server_list[server_index].server_group;
2841 }
2842
2843 void
server_set_server_group(int server_index,int group)2844 server_set_server_group(int server_index, int group)
2845 {
2846 if (server_index < 0 && server_index >= number_of_servers())
2847 server_index = from_server;
2848
2849 server_list[server_index].server_group = group;
2850 }
2851
2852 static void
server_group_get_connected_next(int si)2853 server_group_get_connected_next(int si)
2854 {
2855 int i, group;
2856
2857 group = server_list[si].server_group;
2858
2859 for (i = si + 1; i != si; i = (i + 1) % number_of_servers())
2860 if (server_list[i].server_group == group)
2861 {
2862 say("Ok, trying server %s...", server_get_itsname(si));
2863 get_connected(i);
2864 return;
2865 }
2866 say("No servers available.");
2867 }
2868
2869 void
add_server_to_server_group(int server,u_char * group)2870 add_server_to_server_group(int server, u_char *group)
2871 {
2872 int i = find_server_group(group, 1);
2873
2874 server_list[server].server_group = i;
2875 say("Server %s's server group is now %s", server_get_itsname(server), group);
2876 }
2877
2878 int
find_server_group(u_char * group,int add)2879 find_server_group(u_char *group, int add)
2880 {
2881 static int next = 1;
2882 SGroup *g;
2883
2884 if (!group || !*group)
2885 return 0;
2886
2887 g = (SGroup *) find_in_list((List **)(void *)&server_group_list, group, 0);
2888 if (g)
2889 goto end;
2890
2891 if (!add)
2892 return 0;
2893
2894 g = new_malloc(sizeof *g);
2895 g->name = NULL;
2896 malloc_strcpy(&g->name, group);
2897 g->number = next++;
2898 add_to_list((List **)(void *)&server_group_list, (List *) g);
2899 end:
2900 return g->number;
2901 }
2902
2903 u_char *
find_server_group_name(int number)2904 find_server_group_name(int number)
2905 {
2906 SGroup *g = server_group_list;
2907
2908 for (; g; g = g->next)
2909 if (g->number == number)
2910 return g->name;
2911 return empty_string();
2912 }
2913
2914 int
active_server_group(int sgroup)2915 active_server_group(int sgroup)
2916 {
2917 int i;
2918
2919 /* kinda blah - returns first active server in that group */
2920 for (i = 0; i < number_of_servers(); i++)
2921 if (server_list[i].connected)
2922 return i;
2923
2924 return -1;
2925 }
2926
2927 void
server_set_version_string(int server,u_char * ver)2928 server_set_version_string(int server, u_char *ver)
2929 {
2930 if (ver)
2931 malloc_strcpy(&server_list[server].version_string, ver);
2932 else
2933 new_free(&server_list[server].version_string);
2934 }
2935
2936 u_char *
server_get_version_string(int server)2937 server_get_version_string(int server)
2938 {
2939 return server_list[server].version_string;
2940 }
2941
2942 void
server_set_away(int server,u_char * away)2943 server_set_away(int server, u_char *away)
2944 {
2945 if (away)
2946 malloc_strcpy(&server_list[server].away, away);
2947 else
2948 new_free(&server_list[server].away);
2949 }
2950
2951 u_char *
server_get_away(int server)2952 server_get_away(int server)
2953 {
2954 return server_list[server].away;
2955 }
2956
2957 void
server_get_local_ip_info(int server,SOCKADDR_STORAGE ** sa,socklen_t * salen)2958 server_get_local_ip_info(int server, SOCKADDR_STORAGE **sa, socklen_t *salen)
2959 {
2960 if (sa)
2961 *sa = server_list[from_server].localaddr;
2962 if (salen)
2963 *salen = server_list[from_server].localaddrlen;
2964 }
2965
2966 void
server_set_chan_list(int server,ChannelList * chan)2967 server_set_chan_list(int server, ChannelList *chan)
2968 {
2969 server_list[server].chan_list = chan;
2970 }
2971
2972 ChannelList *
server_get_chan_list(int server)2973 server_get_chan_list(int server)
2974 {
2975 return server_list[server].chan_list;
2976 }
2977
2978 void
server_set_attempting_to_connect(int server,int attempt)2979 server_set_attempting_to_connect(int server, int attempt)
2980 {
2981 server_list[server].attempting_to_connect = attempt;
2982 }
2983
2984 int
server_get_attempting_to_connect(int server)2985 server_get_attempting_to_connect(int server)
2986 {
2987 return server_list[server].attempting_to_connect;
2988 }
2989
2990 void
server_set_sent(int server,int sent)2991 server_set_sent(int server, int sent)
2992 {
2993 server_list[server].sent = sent;
2994 }
2995
2996 int
server_get_sent(int server)2997 server_get_sent(int server)
2998 {
2999 return server_list[server].sent;
3000 }
3001
3002 CtcpFlood *
server_get_ctcp_flood(int server_index)3003 server_get_ctcp_flood(int server_index)
3004 {
3005 if (server_index < 0 && server_index >= number_of_servers())
3006 server_index = from_server;
3007
3008 return server_list[server_index].ctcp_flood;
3009 }
3010
3011 int
number_of_servers(void)3012 number_of_servers(void)
3013 {
3014 return number_of_servers_count;
3015 }
3016
3017 void
unset_never_connected(void)3018 unset_never_connected(void)
3019 {
3020 never_connected_local = 0;
3021 }
3022
3023 int
never_connected(void)3024 never_connected(void)
3025 {
3026 return never_connected_local;
3027 }
3028
3029 void
set_connected_to_server(int val)3030 set_connected_to_server(int val)
3031 {
3032 connected_to_server_local = val;
3033 }
3034
3035 int
connected_to_server(void)3036 connected_to_server(void)
3037 {
3038 return connected_to_server_local;
3039 }
3040
3041 WhoInfo *
server_get_who_info(void)3042 server_get_who_info(void)
3043 {
3044 return server_list[from_server].who_info;
3045 }
3046
3047 int
server_get_oper_command(void)3048 server_get_oper_command(void)
3049 {
3050 return server_list[from_server].oper_command;
3051 }
3052
3053 void
server_set_oper_command(int val)3054 server_set_oper_command(int val)
3055 {
3056 server_list[from_server].oper_command = val;
3057 }
3058
3059 int
parsing_server(void)3060 parsing_server(void)
3061 {
3062 return parsing_server_index;
3063 }
3064
3065 int
get_primary_server(void)3066 get_primary_server(void)
3067 {
3068 return primary_server;
3069 }
3070
3071 void
set_primary_server(int server)3072 set_primary_server(int server)
3073 {
3074 primary_server = server;
3075 }
3076
3077 int
get_from_server(void)3078 get_from_server(void)
3079 {
3080 return from_server;
3081 }
3082
3083 int
set_from_server(int server)3084 set_from_server(int server)
3085 {
3086 int old_from_server = from_server;
3087
3088 from_server = server;
3089 return old_from_server;
3090 }
3091
3092 server_ssl_level
server_do_ssl(int server)3093 server_do_ssl(int server)
3094 {
3095 return server_list[server].ssl_level;
3096 }
3097
3098 void
server_default_encryption(u_char * proto,u_char * type)3099 server_default_encryption(u_char *proto, u_char *type)
3100 {
3101 if (my_stricmp(proto, UP("ICB")) == 0)
3102 {
3103 yell("No ICB SSL support yet.");
3104 return;
3105 }
3106 if (my_stricmp(proto, UP("IRC")) != 0)
3107 {
3108 yell("Only support IRC and ICB.");
3109 return;
3110 }
3111
3112 /* OK, irc SSL here. */
3113 if (my_stricmp(type, UP("check")) == 0)
3114 {
3115 irc_ssl_level = SSL_VERIFY;
3116 return;
3117 }
3118
3119 if (my_stricmp(type, UP("nocheck")) == 0)
3120 {
3121 irc_ssl_level = SSL_ON;
3122 return;
3123 }
3124
3125 if (my_stricmp(type, UP("off")) == 0)
3126 {
3127 irc_ssl_level = SSL_OFF;
3128 return;
3129 }
3130 }
3131
3132 void *
server_get_server_private(int server)3133 server_get_server_private(int server)
3134 {
3135 return server_list[server].server_private;
3136 }
3137
3138 void
server_set_server_private(int server,void * data,server_private_cb_type cb)3139 server_set_server_private(int server, void *data, server_private_cb_type cb)
3140 {
3141 if (server < 0 && server >= number_of_servers())
3142 server = from_server;
3143
3144 server_list[server].server_private = data;
3145 server_list[server].server_private_cb = cb;
3146 }
3147
3148 u_char *
server_get_proxy_name(int server,int use_default)3149 server_get_proxy_name(int server, int use_default)
3150 {
3151 u_char *name;
3152
3153 if (server < 0 && server >= number_of_servers())
3154 return NULL;
3155 name = server_list[server].proxy_name;
3156 if (server_list[server].proxy_port == -1)
3157 name = NULL;
3158 else if (name == NULL && use_default)
3159 name = default_proxy_name;
3160
3161 Debug(DB_PROXY, "returning name '%s'", name ? name : UP("<>"));
3162 return name;
3163 }
3164
3165 int
server_get_proxy_port(int server,int use_default)3166 server_get_proxy_port(int server, int use_default)
3167 {
3168 int port;
3169
3170 if (server < 0 && server >= number_of_servers())
3171 return 0;
3172 port = server_list[server].proxy_port;
3173 if (port == 0 && use_default)
3174 port = default_proxy_port;
3175
3176 Debug(DB_PROXY, "returning port %d", port);
3177 return port;
3178 }
3179
3180 void
server_set_default_proxy(u_char * proxy_and_port)3181 server_set_default_proxy(u_char *proxy_and_port)
3182 {
3183 server_split_proxy_port(proxy_and_port,
3184 &default_proxy_name, &default_proxy_port);
3185 Debug(DB_PROXY, "set server '%s' port '%d'", default_proxy_name, default_proxy_port);
3186 }
3187