7e5709d67ee957ba31d96a35c97e6406a88e0ca5
[jelmer/ctrlproxy.git] / src / network.c
1 /*
2         ctrlproxy: A modular IRC proxy
3         (c) 2002-2007 Jelmer Vernooij <jelmer@nl.linux.org>
4
5         This program is free software; you can redistribute it and/or modify
6         it under the terms of the GNU General Public License as published by
7         the Free Software Foundation; either version 2 of the License, or
8         (at your option) any later version.
9
10         This program is distributed in the hope that it will be useful,
11         but WITHOUT ANY WARRANTY; without even the implied warranty of
12         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13         GNU General Public License for more details.
14
15         You should have received a copy of the GNU General Public License
16         along with this program; if not, write to the Free Software
17         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "internals.h"
21 #include "irc.h"
22 #include "ssl.h"
23
24 static GHashTable *virtual_network_ops = NULL;
25
26 static gboolean delayed_connect_server(struct network *s);
27 static gboolean connect_server(struct network *s);
28 static gboolean close_server(struct network *s);
29 static void reconnect(struct network *server, gboolean rm_source);
30 static void clients_send_state(GList *clients, struct network_state *s);
31
32 struct new_network_notify_data {
33         new_network_notify_fn fn;
34         void *data;
35 };
36
37 void register_new_network_notify(struct global *global, new_network_notify_fn fn, void *userdata)
38 {
39         struct new_network_notify_data *p = g_new0(struct new_network_notify_data, 1);
40         p->fn = fn;
41         p->data = userdata;
42         global->new_network_notifiers = g_list_append(global->new_network_notifiers, p);
43 }
44
45 static void state_log_helper(enum log_level l, void *userdata, const char *msg)
46 {
47         log_network(l, (const struct network *)userdata, "%s", msg);
48 }
49
50 static void server_send_login (struct network *s) 
51 {
52         g_assert(s);
53
54         s->connection.state = NETWORK_CONNECTION_STATE_LOGIN_SENT;
55
56         log_network(LOG_TRACE, s, "Sending login details");
57
58         s->state = network_state_init(s->config->nick, s->config->username, 
59                                                                   get_my_hostname());
60         s->state->userdata = s;
61         s->state->log = state_log_helper;
62         s->linestack = new_linestack(s);
63         g_assert(s->linestack != NULL);
64
65         if (s->config->type == NETWORK_TCP && 
66            s->connection.data.tcp.current_server->password) { 
67                 network_send_args(s, "PASS", 
68                                         s->connection.data.tcp.current_server->password, NULL);
69         } else if (s->config->password) {
70                 network_send_args(s, "PASS", s->config->password, NULL);
71         }
72         network_send_args(s, "NICK", s->config->nick, NULL);
73         network_send_args(s, "USER", s->config->username, s->config->username, 
74                                           s->config->name, s->config->fullname, NULL);
75 }
76
77 /**
78  * Change the character set used to communicate with the server.
79  *
80  * @param n network to change the character set for
81  * @param name name of the character set to use
82  * @return true if setting the charset worked
83  */
84 gboolean network_set_charset(struct network *n, const char *name)
85 {
86         GIConv tmp;
87
88         if (name != NULL) {
89                 tmp = g_iconv_open(name, "UTF-8");
90
91                 if (tmp == (GIConv)-1) {
92                         log_network(LOG_WARNING, n, "Unable to find charset `%s'", name);
93                         return FALSE;
94                 }
95         } else {
96                 tmp = (GIConv)-1;
97         }
98         
99         if (n->connection.outgoing_iconv != (GIConv)-1)
100                 g_iconv_close(n->connection.outgoing_iconv);
101
102         n->connection.outgoing_iconv = tmp;
103
104         if (name != NULL) {
105                 tmp = g_iconv_open("UTF-8", name);
106                 if (tmp == (GIConv)-1) {
107                         log_network(LOG_WARNING, n, "Unable to find charset `%s'", name);
108                         return FALSE;
109                 }
110         } else {
111                 tmp = (GIConv)-1;
112         }
113
114         if (n->connection.incoming_iconv != (GIConv)-1)
115                 g_iconv_close(n->connection.incoming_iconv);
116
117         n->connection.incoming_iconv = tmp;
118
119         if (n->config->type == NETWORK_VIRTUAL)
120                 return TRUE;
121
122         return TRUE;
123 }
124
125 /**
126  * Update the isupport settings for a local network based on the 
127  * ISUPPORT info sent by a server.
128  *
129  * @param net_info Current information
130  * @param remote_info Remote information
131  * @return Whether updating went ok.
132  */
133 static gboolean network_update_isupport(struct network_info *net_info,
134                                                                                 struct network_info *remote_info)
135 {
136         if (remote_info->name != NULL) {
137                 g_free(net_info->name);
138                 net_info->name = g_strdup(remote_info->name);
139         }
140
141         if (remote_info->prefix != NULL) {
142                 g_free(net_info->prefix);
143                 net_info->prefix = g_strdup(remote_info->prefix);
144         }
145
146         if (remote_info->chantypes != NULL) {
147                 g_free(net_info->chantypes);
148                 net_info->chantypes = g_strdup(remote_info->chantypes);
149         }
150
151         if (remote_info->casemapping != CASEMAP_UNKNOWN) {
152                 net_info->casemapping = remote_info->casemapping;
153         }
154
155         if (remote_info->supported_user_modes != NULL) {
156                 g_free(net_info->supported_user_modes);
157                 net_info->supported_user_modes = g_strdup(remote_info->supported_user_modes);
158         } 
159
160         if (remote_info->supported_channel_modes != NULL) {
161                 g_free(net_info->supported_channel_modes);
162                 net_info->supported_channel_modes = g_strdup(remote_info->supported_channel_modes);
163         }
164
165         return TRUE;
166 }
167
168 /**
169  * Process a line received from the server
170  *
171  * @param n Network the line is received at
172  * @param l Line received
173  * @return Whether the message was received ok
174  */
175 static gboolean process_from_server(struct network *n, struct line *l)
176 {
177         struct line *lc;
178         GError *error = NULL;
179
180         g_assert(n);
181         g_assert(l);
182
183         log_network_line(n, l, TRUE);
184
185         /* Silently drop empty messages, as allowed by RFC */
186         if (l->argc == 0) {
187                 return TRUE;
188         }
189
190         n->connection.last_line_recvd = time(NULL);
191
192         if (n->state == NULL) {
193                 log_network(LOG_WARNING, n, 
194                                         "Dropping message '%s' because network is disconnected.", 
195                                         l->args[0]);
196                 return FALSE;
197         }
198
199         run_log_filter(n, lc = linedup(l), FROM_SERVER); free_line(lc);
200         run_replication_filter(n, lc = linedup(l), FROM_SERVER); free_line(lc);
201
202         g_assert(n->state);
203
204         state_handle_data(n->state, l);
205
206         g_assert(l->args[0]);
207
208         if (!g_strcasecmp(l->args[0], "PING")){
209                 network_send_args(n, "PONG", l->args[1], NULL);
210                 return TRUE;
211         } else if (!g_strcasecmp(l->args[0], "PONG")){
212                 return TRUE;
213         } else if (!g_strcasecmp(l->args[0], "ERROR")) {
214                 log_network(LOG_ERROR, n, "error: %s", l->args[1]);
215         } else if (!g_strcasecmp(l->args[0], "433") && 
216                           n->connection.state == NETWORK_CONNECTION_STATE_LOGIN_SENT){
217                 char *tmp = g_strdup_printf("%s_", l->args[2]);
218                 network_send_args(n, "NICK", tmp, NULL);
219                 log_network(LOG_WARNING, n, "%s was already in use, trying %s", 
220                                         l->args[2], tmp);
221                 g_free(tmp);
222         } else if (atoi(l->args[0]) == RPL_ENDOFMOTD ||
223                           atoi(l->args[0]) == ERR_NOMOTD) {
224                 GList *gl;
225                 n->connection.state = NETWORK_CONNECTION_STATE_MOTD_RECVD;
226
227                 network_set_charset(n, get_charset(&n->info));
228
229                 if (error != NULL)
230                         log_network(LOG_WARNING, n, "Error setting charset %s: %s", 
231                                 get_charset(&n->info), error->message);
232
233                 log_network(LOG_INFO, n, "Successfully logged in");
234
235                 network_update_isupport(&n->info, &n->state->info);
236
237                 nickserv_identify_me(n, n->state->me.nick);
238
239                 clients_send_state(n->clients, n->state);
240
241                 server_connected_hook_execute(n);
242
243                 network_send_args(n, "USERHOST", n->state->me.nick, NULL);
244
245                 /* Rejoin channels */
246                 for (gl = n->config->channels; gl; gl = gl->next) {
247                         struct channel_config *c = gl->data;
248
249                         if (c->autojoin) {
250                                 network_send_args(n, "JOIN", c->name, c->key, NULL);
251                         } 
252                 }
253         } 
254
255         if ( n->connection.state == NETWORK_CONNECTION_STATE_MOTD_RECVD) {
256                 gboolean linestack_store = TRUE;
257                 if (atoi(l->args[0])) {
258                         linestack_store &= (!redirect_response(n, l));
259                 } else if (!g_strcasecmp(l->args[0], "PRIVMSG") && l->argc > 2 && 
260                         l->args[2][0] == '\001' && 
261                         g_strncasecmp(l->args[2], "\001ACTION", 7) != 0) {
262                         ctcp_process_network_request(n, l);
263                 } else if (!g_strcasecmp(l->args[0], "NOTICE") && l->argc > 2 && 
264                         l->args[2][0] == '\001') {
265                         ctcp_process_network_reply(n, l);
266                 } else if (run_server_filter(n, l, FROM_SERVER)) {
267                         clients_send(n->clients, l, NULL);
268                 } 
269
270                 if (linestack_store)
271                         linestack_insert_line(n->linestack, l, FROM_SERVER, n->state);
272         } 
273
274         return TRUE;
275 }
276
277 static void network_report_disconnect(struct network *n, const char *fmt, ...)
278 {
279         va_list ap;
280         char *tmp;
281         va_start(ap, fmt);
282         tmp = g_strdup_vprintf(fmt, ap);
283         va_end(ap);
284
285         g_free(n->connection.data.tcp.last_disconnect_reason);
286         n->connection.data.tcp.last_disconnect_reason = tmp;
287
288         log_network(LOG_WARNING, n, "%s", tmp);
289 }
290
291 static gboolean handle_server_receive (GIOChannel *c, GIOCondition cond, void *_server)
292 {
293         struct network *server = (struct network *)_server;
294         struct line *l;
295         gboolean ret;
296
297         g_assert(c != NULL);
298         g_assert(server != NULL);
299
300         if (cond & G_IO_HUP) {
301                 network_report_disconnect(server, "Hangup from server, scheduling reconnect");
302                 reconnect(server, FALSE);
303                 return FALSE;
304         }
305
306         if (cond & G_IO_ERR) {
307                 network_report_disconnect(server, "Error from server, scheduling reconnect");
308                 reconnect(server, FALSE);
309                 return FALSE;
310         }
311
312         if (cond & G_IO_IN) {
313                 GError *err = NULL;
314                 GIOStatus status;
315                 
316                 while ((status = irc_recv_line(c, server->connection.incoming_iconv, 
317                                                                            &err, &l)) == G_IO_STATUS_NORMAL) 
318                 {
319                         g_assert(l != NULL);
320
321                         ret = process_from_server(server, l);
322
323                         free_line(l);
324
325                         if (!ret)
326                                 return FALSE;
327                 }
328
329                 switch (status) {
330                 case G_IO_STATUS_AGAIN:
331                         return TRUE;
332                 case G_IO_STATUS_EOF:
333                         if (server->connection.state != NETWORK_CONNECTION_STATE_NOT_CONNECTED) 
334                                 reconnect(server, FALSE);
335                         return FALSE;
336                 case G_IO_STATUS_ERROR:
337                         g_assert(err != NULL);
338                         log_network(LOG_WARNING, server, 
339                                                 "Error \"%s\" reading from server", err->message);
340                         if (l != NULL) {
341                                 ret = process_from_server(server, l);
342
343                                 free_line(l);
344
345                                 return ret;
346                         }
347
348                         return TRUE;
349                 default: abort();
350                 }
351
352                 return TRUE;
353         }
354
355         return TRUE;
356 }
357
358 static struct tcp_server_config *network_get_next_tcp_server(struct network *n)
359 {
360         GList *cur;
361         
362         g_assert(n);
363         g_assert(n->config);
364         cur = g_list_find(n->config->type_settings.tcp_servers, n->connection.data.tcp.current_server);
365
366         /* Get next available server */
367         if (cur != NULL && cur->next != NULL) 
368                 cur = cur->next; 
369         else 
370                 cur = n->config->type_settings.tcp_servers;
371
372         if (cur != NULL) 
373                 return cur->data; 
374
375         return NULL;
376 }
377
378 static gboolean antiflood_allow_line(struct network *s)
379 {
380         /* FIXME: Implement antiflood, use s->config->queue_speed */
381         return TRUE;
382 }
383
384 static gboolean server_send_queue(GIOChannel *ch, GIOCondition cond, 
385                                                                   gpointer user_data)
386 {
387         struct network *s = user_data;
388         GError *error = NULL;
389         GIOStatus status;
390
391         while (!g_queue_is_empty(s->connection.pending_lines)) {
392                 struct line *l = g_queue_peek_head(s->connection.pending_lines);
393
394                 /* Check if antiflood allows us to send a line */
395                 if (!antiflood_allow_line(s)) 
396                         return TRUE;
397
398                 status = irc_send_line(s->connection.outgoing, s->connection.outgoing_iconv, l, &error);
399
400                 if (status == G_IO_STATUS_AGAIN)
401                         return TRUE;
402
403                 g_queue_pop_head(s->connection.pending_lines);
404
405                 if (status != G_IO_STATUS_NORMAL) {
406                         log_network(LOG_WARNING, s, "Error sending line '%s': %s",
407                    l->args[0], error != NULL?error->message:"ERROR");
408                         free_line(l);
409
410                         return FALSE;
411                 }
412                 s->connection.last_line_sent = time(NULL);
413
414                 free_line(l);
415         }
416
417         s->connection.outgoing_id = 0;
418         return FALSE;
419 }
420
421 static gboolean network_send_line_direct(struct network *s, struct client *c, 
422                                                                                  const struct line *ol)
423 {
424         struct line nl, *l;
425
426         g_assert(s->config != NULL);
427
428         g_assert(s->config->type == NETWORK_TCP ||
429                  s->config->type == NETWORK_PROGRAM ||
430                  s->config->type == NETWORK_IOCHANNEL ||
431                  s->config->type == NETWORK_VIRTUAL);
432
433         l = &nl;
434         memcpy(l, ol, sizeof(struct line));
435         nl.origin = NULL;
436
437         g_assert(l->origin == NULL); /* origin lines should never be sent to the server */
438
439         if (s->config->type == NETWORK_VIRTUAL) {
440                 if (s->connection.data.virtual.ops == NULL) 
441                         return FALSE;
442                 return s->connection.data.virtual.ops->to_server(s, c, l);
443         } else if (s->connection.outgoing_id == 0) {
444                 GError *error = NULL;
445
446                 GIOStatus status = irc_send_line(s->connection.outgoing, s->connection.outgoing_iconv, l, &error);
447
448                 if (status == G_IO_STATUS_AGAIN) {
449                         g_queue_push_tail(s->connection.pending_lines, linedup(l));
450                         s->connection.outgoing_id = g_io_add_watch(s->connection.outgoing, G_IO_OUT, server_send_queue, s);
451                 } else if (status != G_IO_STATUS_NORMAL) {
452                         log_network(LOG_WARNING, s, "Error sending line '%s': %s",
453                    l->args[0], error != NULL?error->message:"ERROR");
454                         return FALSE;
455                 }
456
457                 s->connection.last_line_sent = time(NULL);
458                 return TRUE;
459         } else {
460                 g_queue_push_tail(s->connection.pending_lines, linedup(l));
461         }
462
463         return TRUE;
464 }
465
466 /**
467  * Send a line to the network.
468  * @param s Network to send to.
469  * @param c Client the line was sent by originally.
470  * @param ol Line to send to the network
471  * @param is_private Whether the line should not be broadcast to other clients
472  */
473 gboolean network_send_line(struct network *s, struct client *c, 
474                                                    const struct line *ol, gboolean is_private)
475 {
476         struct line l;
477         char *tmp = NULL;
478         struct line *lc;
479
480         g_assert(ol);
481         g_assert(s);
482         l = *ol;
483
484         if (l.origin == NULL && s->state != NULL) {
485                 tmp = l.origin = g_strdup(s->state->me.hostmask);
486         }
487
488         if (l.origin != NULL) {
489                 if (!run_server_filter(s, &l, TO_SERVER)) {
490                         g_free(tmp);
491                         return TRUE;
492                 }
493
494                 run_log_filter(s, lc = linedup(&l), TO_SERVER); free_line(lc);
495                 run_replication_filter(s, lc = linedup(&l), TO_SERVER); free_line(lc);
496                 linestack_insert_line(s->linestack, ol, TO_SERVER, s->state);
497         }
498
499         g_assert(l.args[0] != NULL);
500
501         /* Also write this message to all other clients currently connected */
502         if (!is_private && 
503            (!g_strcasecmp(l.args[0], "PRIVMSG") || 
504                 !g_strcasecmp(l.args[0], "NOTICE"))) {
505                 g_assert(l.origin);
506                 clients_send(s->clients, &l, c);
507         }
508
509         g_free(tmp);
510
511         log_network_line(s, ol, FALSE);
512
513         redirect_record(s, c, ol);
514
515         return network_send_line_direct(s, c, ol);
516 }
517
518 /**
519  * Indicate that a response is received by a virtual network.
520  *
521  * @param n Network to receive data
522  * @param num Number of the response to receive
523  */
524 gboolean virtual_network_recv_response(struct network *n, int num, ...) 
525 {
526         va_list ap;
527         struct line *l;
528         gboolean ret;
529
530         g_assert(n);
531         g_assert(n->config->type == NETWORK_VIRTUAL);
532
533         va_start(ap, num);
534         l = virc_parse_line(n->info.name, ap);
535         va_end(ap);
536
537         l->args = g_realloc(l->args, sizeof(char *) * (l->argc+4));
538         memmove(&l->args[2], &l->args[0], l->argc * sizeof(char *));
539
540         l->args[0] = g_strdup_printf("%03d", num);
541
542         if (n->state != NULL && n->state->me.nick != NULL) 
543                 l->args[1] = g_strdup(n->state->me.nick);
544         else 
545                 l->args[1] = g_strdup("*");
546
547         l->argc+=2;
548         l->args[l->argc] = NULL;
549
550         ret = virtual_network_recv_line(n, l);
551
552         free_line(l);
553
554         return ret;
555 }
556
557 /**
558  * Indicate that a line is received by a virtual network.
559  *
560  * @param s Network to send to.
561  * @param l Line to receive.
562  */
563 gboolean virtual_network_recv_line(struct network *s, struct line *l)
564 {
565         g_assert(s != NULL);
566         g_assert(l != NULL);
567
568         if (l->origin == NULL) 
569                 l->origin = g_strdup(get_my_hostname());
570
571         return process_from_server(s, l);
572 }
573
574 /**
575  * Indicate that a line has been received.
576  *
577  * @param s Network to use.
578  * @param origin Origin to make the data originate from
579  */
580 gboolean virtual_network_recv_args(struct network *s, const char *origin, ...)
581 {
582         va_list ap;
583         struct line *l;
584         gboolean ret;
585
586         g_assert(s);
587
588         va_start(ap, origin);
589         l = virc_parse_line(origin, ap);
590         va_end(ap);
591
592         ret = virtual_network_recv_line(s, l);
593
594         free_line(l);
595
596         return ret;
597 }
598
599 /**
600  * Send a new line to the network.
601  *
602  * @param s Network
603  * @param ... Arguments terminated by NULL
604  */
605 gboolean network_send_args(struct network *s, ...)
606 {
607         va_list ap;
608         struct line *l;
609         gboolean ret;
610
611         g_assert(s);
612
613         va_start(ap, s);
614         l = virc_parse_line(NULL, ap);
615         va_end(ap);
616
617         ret = network_send_line(s, NULL, l, TRUE);
618
619         free_line(l);
620
621         return ret;
622 }
623
624 static gboolean bindsock(struct network *s,
625                                                  int sock, struct addrinfo *res, 
626                                                  const char *address,
627                                                  const char *service)
628 {
629         struct addrinfo hints_bind;
630         int error;
631         struct addrinfo *res_bind, *addrinfo_bind;
632
633         memset(&hints_bind, 0, sizeof(hints_bind));
634         hints_bind.ai_family = res->ai_family;
635         hints_bind.ai_flags = AI_ADDRCONFIG;
636         hints_bind.ai_socktype = res->ai_socktype;
637         hints_bind.ai_protocol = res->ai_protocol;
638
639         error = getaddrinfo(address, service, &hints_bind, &addrinfo_bind);
640         if (error) {
641                 log_network(LOG_ERROR, s, 
642                                         "Unable to lookup %s:%s %s", address, service, 
643                                         gai_strerror(error));
644                 return FALSE;
645         } 
646
647         for (res_bind = addrinfo_bind; 
648                  res_bind; res_bind = res_bind->ai_next) {
649                 if (bind(sock, res_bind->ai_addr, res_bind->ai_addrlen) < 0) {
650                         log_network(LOG_ERROR, s, "Unable to bind to %s:%s %s", 
651                                                 address, service, strerror(errno));
652                 } else 
653                         break;
654         }
655         freeaddrinfo(addrinfo_bind);
656
657         return (res_bind != NULL);
658 }
659
660 /**
661  * Ping the network.
662  *
663  * @param server network to ping
664  * @param ping_source GSource id of the ping event
665  */
666 static void ping_server(struct network *server, gboolean ping_source)
667 {
668         gint silent_time = time(NULL) - server->connection.last_line_recvd;
669         if (silent_time > MAX_SILENT_TIME) {
670                 disconnect_network(server);
671         } else if (silent_time > MIN_SILENT_TIME) {
672                 network_send_args(server, "PING", "ctrlproxy", NULL);
673         }
674 }
675
676 static gboolean connect_current_tcp_server(struct network *s) 
677 {
678         struct addrinfo *res;
679         int sock = -1;
680         socklen_t size;
681         struct tcp_server_config *cs;
682         GIOChannel *ioc = NULL;
683         struct addrinfo hints;
684         struct addrinfo *addrinfo = NULL;
685         int error;
686
687         g_assert(s != NULL);
688
689         if (!s->connection.data.tcp.current_server) {
690                 s->connection.data.tcp.current_server = network_get_next_tcp_server(s);
691         }
692
693         log_network(LOG_TRACE, s, "connect_current_tcp_server");
694         
695         cs = s->connection.data.tcp.current_server;
696         if (cs == NULL) {
697                 s->config->autoconnect = FALSE;
698                 log_network(LOG_WARNING, s, "No servers listed, not connecting");
699                 return FALSE;
700         }
701
702         log_network(LOG_INFO, s, "Connecting with %s:%s", 
703                           cs->host, 
704                           cs->port);
705
706         memset(&hints, 0, sizeof(hints));
707         hints.ai_family = PF_UNSPEC;
708         hints.ai_socktype = SOCK_STREAM;
709         hints.ai_flags = AI_ADDRCONFIG;
710
711         /* Lookup */
712         error = getaddrinfo(cs->host, cs->port, &hints, &addrinfo);
713         if (error) {
714                 log_network(LOG_ERROR, s, "Unable to lookup %s:%s %s", cs->host, cs->port, gai_strerror(error));
715                 freeaddrinfo(addrinfo);
716                 return FALSE;
717         }
718
719         /* Connect */
720
721         for (res = addrinfo; res; res = res->ai_next) {
722
723                 sock = socket(res->ai_family, res->ai_socktype,
724                                           res->ai_protocol);
725                 if (sock < 0) {
726                         continue;
727                 }
728
729                 if (cs->bind_address || cs->bind_port)
730                         bindsock(s, sock, res, cs->bind_address, cs->bind_port);
731
732                 ioc = g_io_channel_unix_new(sock);
733                 if (connect(sock, res->ai_addr, res->ai_addrlen) < 0 && errno != EINPROGRESS) {
734                         g_io_channel_unref(ioc);
735                         ioc = NULL;
736                         continue;
737                 }
738
739                 break; 
740         }
741
742         freeaddrinfo(addrinfo);
743
744         if (!ioc) {
745                 log_network(LOG_ERROR, s, "Unable to connect: %s", strerror(errno));
746                 return FALSE;
747         }
748
749 #ifdef HAVE_IPV6
750         size = sizeof(struct sockaddr_in6);
751 #else
752         size = sizeof(struct sockaddr_in);
753 #endif
754         g_free(s->connection.data.tcp.local_name);
755         g_free(s->connection.data.tcp.remote_name);
756         s->connection.data.tcp.remote_name = g_malloc(size);
757         s->connection.data.tcp.local_name = g_malloc(size);
758         s->connection.data.tcp.namelen = getsockname(sock, s->connection.data.tcp.local_name, &size);
759         getpeername(sock, s->connection.data.tcp.remote_name, &size);
760
761         if (cs->ssl) {
762 #ifdef HAVE_GNUTLS
763                 g_io_channel_set_close_on_unref(ioc, TRUE);
764                 g_io_channel_set_flags(ioc, G_IO_FLAG_NONBLOCK, NULL);
765
766                 ioc = ssl_wrap_iochannel (ioc, SSL_TYPE_CLIENT, 
767                                                                  s->connection.data.tcp.current_server->host,
768                                                                  s->ssl_credentials
769                                                                  );
770                 g_assert(ioc != NULL);
771 #else
772                 log_network(LOG_WARNING, s, "SSL enabled for %s:%s, but no SSL support loaded", cs->host, cs->port);
773 #endif
774         }
775
776         if (!ioc) {
777                 log_network(LOG_ERROR, s, "Couldn't connect via server %s:%s", cs->host, cs->port);
778                 return FALSE;
779         }
780
781         network_set_iochannel(s, ioc);
782
783         g_io_channel_unref(s->connection.outgoing);
784
785         s->connection.data.tcp.ping_id = g_timeout_add(5000, 
786                                                                    (GSourceFunc) ping_server, s);
787
788
789         return TRUE;
790 }
791
792
793 static void reconnect(struct network *server, gboolean rm_source)
794 {
795         g_assert(server);
796
797         g_assert(server->connection.state != NETWORK_CONNECTION_STATE_RECONNECT_PENDING);
798
799         if (server->connection.state == NETWORK_CONNECTION_STATE_MOTD_RECVD) {
800                 server_disconnected_hook_execute(server);
801         }
802
803         close_server(server);
804
805         g_assert(server->config);
806
807         if (server->config->type == NETWORK_TCP)
808                 server->connection.data.tcp.current_server = network_get_next_tcp_server(server);
809
810         if (server->config->type == NETWORK_TCP ||
811                 server->config->type == NETWORK_IOCHANNEL ||
812                 server->config->type == NETWORK_PROGRAM) {
813                 server->connection.state = NETWORK_CONNECTION_STATE_RECONNECT_PENDING;
814                 server->reconnect_id = g_timeout_add(1000 * 
815                                                                 server->config->reconnect_interval, 
816                                                                 (GSourceFunc) delayed_connect_server, server);
817         } else {
818                 connect_server(server); 
819         }
820 }
821
822 static void clients_send_state(GList *clients, struct network_state *s)
823 {
824         GList *gl;
825
826         for (gl = clients; gl; gl = gl->next) {
827                 struct client *c = gl->data;
828                 client_send_state(c, s);
829         }
830 }
831
832 static void clients_invalidate_state(GList *clients, struct network_state *s)
833 {
834         GList *gl;
835
836         /* Leave channels */
837         for (gl = s->channels; gl; gl = gl->next) {
838                 struct channel_state *ch = gl->data;
839
840                 clients_send_args_ex(clients, s->me.hostmask, "PART", ch->name, 
841                                                          "Network disconnected", NULL);
842         }
843
844         /* private queries quit */
845         for (gl = s->nicks; gl; gl = gl->next) {
846                 struct network_nick *gn = gl->data;
847
848                 if (!gn->query || gn == &s->me) continue;
849
850                 clients_send_args_ex(clients, gn->hostmask, "QUIT", "Network disconnected", NULL);
851         }
852 }
853
854 static gboolean close_server(struct network *n) 
855 {
856         g_assert(n);
857
858         if (n->connection.state == NETWORK_CONNECTION_STATE_RECONNECT_PENDING) {
859                 g_source_remove(n->reconnect_id);
860                 n->reconnect_id = 0;
861                 n->connection.state = NETWORK_CONNECTION_STATE_NOT_CONNECTED;
862         }
863
864         if (n->connection.state == NETWORK_CONNECTION_STATE_NOT_CONNECTED) {
865                 return FALSE;
866         } 
867
868         network_send_args(n, "QUIT", NULL);
869
870         if (n->connection.state == NETWORK_CONNECTION_STATE_MOTD_RECVD) {
871                 server_disconnected_hook_execute(n);
872                 clients_invalidate_state(n->clients, n->state);
873                 network_update_config(n->state, n->config);
874         }
875
876         if (n->state) {
877                 free_linestack_context(n->linestack);
878                 n->linestack = NULL;
879                 free_network_state(n->state); 
880                 n->state = NULL;
881         }
882
883         g_assert(n->config);
884
885         switch (n->config->type) {
886         case NETWORK_TCP: 
887         case NETWORK_PROGRAM: 
888         case NETWORK_IOCHANNEL:
889                 g_assert(n->connection.incoming_id > 0);
890                 g_source_remove(n->connection.incoming_id); 
891                 n->connection.incoming_id = 0;
892                 if (n->connection.outgoing_id > 0)
893                         g_source_remove(n->connection.outgoing_id); 
894                 if (n->connection.data.tcp.ping_id > 0) {
895                         g_source_remove(n->connection.data.tcp.ping_id);
896                         n->connection.data.tcp.ping_id = 0;
897                 }
898                 n->connection.outgoing_id = 0;
899                 break;
900         case NETWORK_VIRTUAL:
901                 if (n->connection.data.virtual.ops && 
902                         n->connection.data.virtual.ops->fini) {
903                         n->connection.data.virtual.ops->fini(n);
904                 }
905                 break;
906                 default: g_assert(0);
907         }
908
909         n->connection.state = NETWORK_CONNECTION_STATE_NOT_CONNECTED;
910         redirect_clear(n);
911
912         return TRUE;
913 }
914
915 void clients_send_args_ex(GList *clients, const char *hostmask, ...)
916 {
917         struct line *l;
918         va_list ap;
919
920         va_start(ap, hostmask);
921         l = virc_parse_line(hostmask, ap);
922         va_end(ap);
923
924         clients_send(clients, l, NULL);
925
926         free_line(l); l = NULL;
927 }
928
929 /**
930  * Send a line to a list of clients.
931  *
932  * @param clients List of clients to send to
933  * @param l Line to send
934  * @param exception Client to which nothing should be sent. Can be NULL.
935  */
936 void clients_send(GList *clients, struct line *l, 
937                                   const struct client *exception) 
938 {
939         GList *g;
940
941         for (g = clients; g; g = g->next) {
942                 struct client *c = (struct client *)g->data;
943                 if (c != exception) {
944                         if (run_client_filter(c, l, FROM_SERVER)) { 
945                                 client_send_line(c, l);
946                         }
947                 }
948         }
949 }
950
951 static pid_t piped_child(char* const command[], int *f_in)
952 {
953         pid_t pid;
954         int sock[2];
955
956         if (socketpair(PF_UNIX, SOCK_STREAM, AF_LOCAL, sock) == -1) {
957                 log_global(LOG_ERROR, "socketpair: %s", strerror(errno));
958                 return -1;
959         }
960
961         *f_in = sock[0];
962
963         fcntl(sock[0], F_SETFL, O_NONBLOCK);
964
965         pid = fork();
966
967         if (pid == -1) {
968                 log_global(LOG_ERROR, "fork: %s", strerror(errno));
969                 return -1;
970         }
971
972         if (pid == 0) {
973                 close(0);
974                 close(1);
975                 close(2);
976                 close(sock[0]);
977
978                 dup2(sock[1], 0);
979                 dup2(sock[1], 1);
980                 execvp(command[0], command);
981                 exit(-1);
982         }
983
984         close(sock[1]);
985
986         return pid;
987 }
988
989 /**
990  * Change the IO channel used to communicate with a network.
991  * @param s Network to set the IO channel for.
992  * @param ioc IO channel to use
993  */
994 void network_set_iochannel(struct network *s, GIOChannel *ioc)
995 {
996         g_assert(s->config->type != NETWORK_VIRTUAL);
997         g_io_channel_set_encoding(ioc, NULL, NULL);
998         g_io_channel_set_close_on_unref(ioc, TRUE);
999         g_io_channel_set_flags(ioc, G_IO_FLAG_NONBLOCK, NULL);
1000
1001         s->connection.outgoing = ioc;
1002         g_io_channel_set_close_on_unref(s->connection.outgoing, TRUE);
1003
1004         s->connection.incoming_id = g_io_add_watch(s->connection.outgoing, 
1005                                                                 G_IO_IN | G_IO_HUP | G_IO_ERR, 
1006                                                                 handle_server_receive, s);
1007         handle_server_receive(s->connection.outgoing, 
1008                                   g_io_channel_get_buffer_condition(s->connection.outgoing), 
1009                                   s);
1010
1011         server_send_login(s);
1012 }
1013
1014 static gboolean connect_program(struct network *s)
1015 {
1016         int sock;
1017         char *cmd[2];
1018         pid_t pid;
1019         
1020         g_assert(s);
1021         g_assert(s->config);
1022         g_assert(s->config->type == NETWORK_PROGRAM);
1023         
1024         cmd[0] = s->config->type_settings.program_location;
1025         cmd[1] = NULL;
1026         pid = piped_child(cmd, &sock);
1027
1028         if (pid == -1) return FALSE;
1029
1030         network_set_iochannel(s, g_io_channel_unix_new(sock));
1031
1032         g_io_channel_unref(s->connection.outgoing);
1033
1034
1035         if (s->info.name == NULL) {
1036                 if (strchr(s->config->type_settings.program_location, '/')) {
1037                         s->info.name = g_strdup(strrchr(s->config->type_settings.program_location, '/')+1);
1038                 } else {
1039                         s->info.name = g_strdup(s->config->type_settings.program_location);
1040                 }
1041         }
1042
1043         return TRUE;
1044 }
1045
1046 static gboolean connect_server(struct network *s)
1047 {
1048         g_assert(s);
1049         g_assert(s->config);
1050
1051         switch (s->config->type) {
1052         case NETWORK_TCP:
1053                 return connect_current_tcp_server(s);
1054
1055         case NETWORK_PROGRAM:
1056                 return connect_program(s);
1057
1058         case NETWORK_VIRTUAL:
1059                 s->connection.data.virtual.ops = g_hash_table_lookup(
1060                                                                 virtual_network_ops, 
1061                                                                 s->config->type_settings.virtual_type);
1062                 if (!s->connection.data.virtual.ops) 
1063                         return FALSE;
1064
1065                 s->state = network_state_init(s->config->nick, s->config->username, 
1066                                                                           get_my_hostname());
1067                 s->state->userdata = s;
1068                 s->state->log = state_log_helper;
1069                 s->linestack = new_linestack(s);
1070                 s->connection.state = NETWORK_CONNECTION_STATE_MOTD_RECVD;
1071
1072                 if (s->connection.data.virtual.ops->init)
1073                         return s->connection.data.virtual.ops->init(s);
1074
1075                 return TRUE;
1076         default: g_assert(0);
1077         }
1078
1079         return TRUE;
1080 }
1081
1082 static gboolean delayed_connect_server(struct network *s)
1083 {
1084         g_assert(s);
1085         connect_server(s);
1086         return (s->connection.state == NETWORK_CONNECTION_STATE_RECONNECT_PENDING);
1087 }
1088
1089 /**
1090  * Load a network from a configuration file specification.
1091  *
1092  * @param global Global context to use.
1093  * @param sc Network configuration to load form
1094  * @return A new network instance, already added to the global context.
1095  */
1096 struct network *load_network(struct global *global, struct network_config *sc)
1097 {
1098         struct network *s;
1099         GList *gl;
1100
1101         g_assert(sc);
1102
1103         if (global != NULL) {
1104                 /* Don't connect to the same network twice */
1105                 s = find_network(global, sc->name);
1106                 if (s) 
1107                         return s;
1108         }
1109
1110         s = g_new0(struct network, 1);
1111         s->config = sc;
1112         network_info_init(&s->info);
1113         s->info.name = g_strdup(s->config->name);
1114         s->connection.pending_lines = g_queue_new();
1115         s->global = global;
1116         s->info.forced_nick_changes = TRUE; /* Forced nick changes are done by ctrlproxy */
1117         s->connection.outgoing_iconv = s->connection.incoming_iconv = (GIConv)-1;
1118
1119         if (global != NULL) {
1120                 g_free(s->info.charset);
1121                 if (s->global->config->client_charset != NULL) {
1122                         s->info.charset = g_strdup(s->global->config->client_charset);
1123                 }
1124
1125                 global->networks = g_list_append(global->networks, s);
1126
1127                 for (gl = global->new_network_notifiers; gl; gl = gl->next) {
1128                         struct new_network_notify_data *p = gl->data;
1129
1130                         p->fn(s, p->data);
1131                 }
1132         }
1133
1134 #ifdef HAVE_GNUTLS
1135         s->ssl_credentials = ssl_get_client_credentials(NULL);
1136 #endif
1137
1138         return s;
1139 }
1140
1141 /**
1142  * Connect to a network, returns TRUE if connection was successful 
1143  * (or startup of connection was successful) 
1144  *
1145  * @param s Network to connect to
1146  */
1147 gboolean connect_network(struct network *s) 
1148 {
1149         g_assert(s);
1150         g_assert(s->connection.state == NETWORK_CONNECTION_STATE_NOT_CONNECTED ||
1151                          s->connection.state == NETWORK_CONNECTION_STATE_RECONNECT_PENDING);
1152
1153         return connect_server(s);
1154 }
1155
1156 static void free_pending_line(void *_line, void *userdata)
1157 {
1158         free_line((struct line *)_line);
1159 }
1160
1161 /** 
1162  * Unload a network from a global context.
1163  *
1164  * @param s Network to unload.
1165  */
1166 void unload_network(struct network *s)
1167 {
1168         GList *l;
1169         
1170         g_assert(s);
1171         if (s->connection.state == NETWORK_CONNECTION_STATE_MOTD_RECVD) {
1172                 log_network(LOG_INFO, s, "Closing connection");
1173         }
1174
1175         l = s->clients;
1176
1177         while(l) {
1178                 struct client *c = l->data;
1179                 l = l->next;
1180                 disconnect_client(c, "Server exiting");
1181         }
1182
1183         if (s->global != NULL) {
1184                 s->global->networks = g_list_remove(s->global->networks, s);
1185         }
1186
1187         if (s->config->type == NETWORK_TCP) {
1188                 g_free(s->connection.data.tcp.local_name);
1189                 g_free(s->connection.data.tcp.remote_name);
1190         }
1191         g_queue_foreach(s->connection.pending_lines, free_pending_line, NULL);
1192         g_queue_free(s->connection.pending_lines);
1193
1194         free_network_info(&s->info);
1195
1196 #ifdef HAVE_GNUTLS
1197         ssl_free_client_credentials(s->ssl_credentials);
1198 #endif
1199
1200         g_iconv_close(s->connection.incoming_iconv);
1201         g_iconv_close(s->connection.outgoing_iconv);
1202
1203         g_free(s);
1204 }
1205
1206 /** 
1207  * Disconnect from a network. The network will still be kept in memory, 
1208  * but all socket connections associated with it will be dropped.
1209  *
1210  * @param s Network to disconnect from
1211  * @return Whether disconnecting succeeded.
1212  */
1213 gboolean disconnect_network(struct network *s)
1214 {
1215         g_assert(s);
1216         if (s->connection.state == NETWORK_CONNECTION_STATE_NOT_CONNECTED) {
1217                 return FALSE;
1218         }
1219         log_network(LOG_INFO, s, "Disconnecting");
1220         return close_server(s);
1221 }
1222
1223 /**
1224  * Check whether a client is still associated with a network.
1225  *
1226  * The client pointer does not have to point to a valid piece of memory.
1227  *
1228  * @param s Network the client should be associated with.
1229  * @param c The client.
1230  * @return Whether the client is still associated with the network.
1231  */
1232 gboolean verify_client(const struct network *s, const struct client *c)
1233 {
1234         GList *gl;
1235
1236         g_assert(s);
1237         g_assert(c);
1238         
1239         for (gl = s->clients; gl; gl = gl->next) {
1240                 struct client *nc = (struct client *)gl->data;
1241                 if (c == nc) return 1;
1242         }
1243
1244         return 0;
1245 }
1246
1247 /**
1248  * Register a new virtual network type.
1249  *
1250  * @param ops Callback functions for the virtual network type.
1251  */
1252 void register_virtual_network(struct virtual_network_ops *ops)
1253 {
1254         if (virtual_network_ops == NULL)
1255                 virtual_network_ops = g_hash_table_new(g_str_hash, g_str_equal);
1256         g_assert(ops);
1257         g_hash_table_insert(virtual_network_ops, ops->name, ops);
1258 }
1259
1260 /**
1261  * Autoconnect to all the networks in a global context.
1262  *
1263  * @param Global global context
1264  * @return TRUE
1265  */
1266 gboolean autoconnect_networks(struct global *global)
1267 {
1268         GList *gl;
1269         for (gl = global->networks; gl; gl = gl->next)
1270         {
1271                 struct network *n = gl->data;
1272                 g_assert(n);
1273                 g_assert(n->config);
1274                 if (n->config->autoconnect)
1275                         connect_network(n);
1276         }
1277
1278         return TRUE;
1279 }
1280
1281 /**
1282  * Load all the networks in a configuration file.
1283  *
1284  * @param global Global context to load networks into.
1285  * @param cfg Configuration to read from
1286  * @return TRUE
1287  */
1288 gboolean load_networks(struct global *global, struct ctrlproxy_config *cfg)
1289 {
1290         GList *gl;
1291         g_assert(cfg);
1292         for (gl = cfg->networks; gl; gl = gl->next)
1293         {
1294                 struct network_config *nc = gl->data;
1295                 load_network(global, nc);
1296         }
1297
1298         return TRUE;
1299 }
1300
1301 /**
1302  * Find a network by name.
1303  *
1304  * @param global Global context to search in.
1305  * @param name Name of the network to search for.
1306  * @return first network found or NULL
1307  */
1308 struct network *find_network(struct global *global, const char *name)
1309 {
1310         GList *gl;
1311         for (gl = global->networks; gl; gl = gl->next) {
1312                 struct network *n = gl->data;
1313                 if (n->info.name && !g_strcasecmp(n->info.name, name)) 
1314                         return n;
1315         }
1316
1317         return NULL;
1318 }
1319
1320 /**
1321  * Find a network by host name and port or name.
1322  * 
1323  * @param global Context to search in
1324  * @param hostname Hostname to search for
1325  * @param port Port to search from.
1326  * @param create Whether to create the network if it wasn't found.
1327  * @return the network found or created or NULL
1328  */
1329 struct network *find_network_by_hostname(struct global *global, 
1330                                                                                  const char *hostname, guint16 port, 
1331                                                                                  gboolean create)
1332 {
1333         GList *gl;
1334         char *portname = g_strdup_printf("%d", port);
1335         g_assert(portname != NULL);
1336         g_assert(hostname != NULL);
1337         
1338         for (gl = global->networks; gl; gl = gl->next) {
1339                 GList *sv;
1340                 struct network *n = gl->data;
1341                 g_assert(n);
1342
1343                 if (n->info.name && !g_strcasecmp(n->info.name, hostname)) {
1344                         g_free(portname);
1345                         return n;
1346                 }
1347
1348                 g_assert(n->config);
1349                 if (n->config->type == NETWORK_TCP) 
1350                 {
1351                         for (sv = n->config->type_settings.tcp_servers; sv; sv = sv->next)
1352                         {
1353                                 struct tcp_server_config *server = sv->data;
1354
1355                                 if (!g_strcasecmp(server->host, hostname) && 
1356                                         !g_strcasecmp(server->port, portname)) {
1357                                         g_free(portname);
1358                                         return n;
1359                                 }
1360                         } 
1361                 }
1362
1363                 if (n->info.name && !g_strcasecmp(n->info.name, hostname)) {
1364                         g_free(portname);
1365                         return n;
1366                 }
1367         }
1368
1369         /* Create a new server */
1370         if (create)
1371         {
1372                 struct tcp_server_config *s = g_new0(struct tcp_server_config, 1);
1373                 struct network_config *nc;
1374                 nc = network_config_init(global->config);
1375
1376                 nc->name = g_strdup(hostname);
1377                 nc->type = NETWORK_TCP;
1378                 s->host = g_strdup(hostname);
1379                 s->port = portname;
1380
1381                 nc->type_settings.tcp_servers = g_list_append(nc->type_settings.tcp_servers, s);
1382
1383                 return load_network(global, nc);
1384         }
1385
1386         g_free(portname);
1387
1388         return NULL;
1389 }
1390
1391 /**
1392  * Disconnect from and unload all networks.
1393  *
1394  * @param global Global context
1395  */
1396 void fini_networks(struct global *global)
1397 {
1398         GList *gl;
1399         while((gl = global->networks)) {
1400                 struct network *n = (struct network *)gl->data;
1401                 disconnect_network(n);
1402                 unload_network(n);
1403         }
1404
1405         if (virtual_network_ops != NULL)
1406                 g_hash_table_destroy(virtual_network_ops);
1407         virtual_network_ops = NULL;
1408 }
1409
1410 /**
1411  * Switch to the next server listed for a network.
1412  *
1413  * @param n Network
1414  */
1415 void network_select_next_server(struct network *n)
1416 {
1417         g_assert(n);
1418         g_assert(n->config);
1419
1420         if (n->config->type != NETWORK_TCP) 
1421                 return;
1422
1423         log_network(LOG_INFO, n, "Trying next server");
1424         n->connection.data.tcp.current_server = network_get_next_tcp_server(n);
1425 }
1426
1427 /**
1428  * Generate 005-response string to send to client connected to a network.
1429  *
1430  * @param n Network to generate for
1431  * @return An 005 string, newly allocated
1432  */
1433 char *network_generate_feature_string(struct network *n)
1434 {
1435         g_assert(n);
1436
1437         return network_info_string(&n->info);
1438 }
1439
1440