1 /*
2  servers-setup.c : irssi
3 
4     Copyright (C) 1999-2001 Timo Sirainen
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 
21 #include "module.h"
22 #include "signals.h"
23 #include "network.h"
24 #include "lib-config/iconfig.h"
25 #include "settings.h"
26 
27 #include "chat-protocols.h"
28 #include "chatnets.h"
29 #include "servers.h"
30 #include "servers-setup.h"
31 
32 GSList *setupservers;
33 
34 static char *old_source_host;
35 int source_host_ok; /* Use source_host_ip .. */
36 IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */
37 
save_ips(IPADDR * ip4,IPADDR * ip6,IPADDR ** save_ip4,IPADDR ** save_ip6)38 static void save_ips(IPADDR *ip4, IPADDR *ip6,
39 		     IPADDR **save_ip4, IPADDR **save_ip6)
40 {
41 	if (ip4->family == 0)
42 		g_free_and_null(*save_ip4);
43 	else {
44                 if (*save_ip4 == NULL)
45 			*save_ip4 = g_new(IPADDR, 1);
46 		memcpy(*save_ip4, ip4, sizeof(IPADDR));
47 	}
48 
49 	if (ip6->family == 0)
50 		g_free_and_null(*save_ip6);
51 	else {
52                 if (*save_ip6 == NULL)
53 			*save_ip6 = g_new(IPADDR, 1);
54 		memcpy(*save_ip6, ip6, sizeof(IPADDR));
55 	}
56 }
57 
get_source_host_ip(void)58 static void get_source_host_ip(void)
59 {
60         const char *hostname;
61 	IPADDR ip4, ip6;
62 
63 	if (source_host_ok)
64 		return;
65 
66 	/* FIXME: This will block! */
67         hostname = settings_get_str("hostname");
68 	source_host_ok = *hostname != '\0' &&
69 		net_gethostbyname(hostname, &ip4, &ip6) == 0;
70 
71 	if (source_host_ok)
72 		save_ips(&ip4, &ip6, &source_host_ip4, &source_host_ip6);
73 	else {
74                 g_free_and_null(source_host_ip4);
75                 g_free_and_null(source_host_ip6);
76 	}
77 }
78 
conn_set_ip(SERVER_CONNECT_REC * conn,const char * own_host,IPADDR ** own_ip4,IPADDR ** own_ip6)79 static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host,
80 			IPADDR **own_ip4, IPADDR **own_ip6)
81 {
82 	IPADDR ip4, ip6;
83 
84 	if (*own_ip4 == NULL && *own_ip6 == NULL) {
85 		/* resolve the IP */
86 		if (net_gethostbyname(own_host, &ip4, &ip6) == 0)
87                         save_ips(&ip4, &ip6, own_ip4, own_ip6);
88 	}
89 
90 	server_connect_own_ip_save(conn, *own_ip4, *own_ip6);
91 }
92 
93 /* Fill information to connection from server setup record */
server_setup_fill_reconn(SERVER_CONNECT_REC * conn,SERVER_SETUP_REC * sserver)94 void server_setup_fill_reconn(SERVER_CONNECT_REC *conn,
95 			      SERVER_SETUP_REC *sserver)
96 {
97 	g_return_if_fail(IS_SERVER_CONNECT(conn));
98 	g_return_if_fail(IS_SERVER_SETUP(sserver));
99 
100 	if (sserver->own_host != NULL) {
101 		conn_set_ip(conn, sserver->own_host,
102 			    &sserver->own_ip4, &sserver->own_ip6);
103 	}
104 
105 	if (sserver->chatnet != NULL && conn->chatnet == NULL)
106 		conn->chatnet = g_strdup(sserver->chatnet);
107 
108 	if (sserver->password != NULL && conn->password == NULL)
109 		conn->password = g_strdup(sserver->password);
110 
111 	if (sserver->no_proxy)
112 		g_free_and_null(conn->proxy);
113 
114 	if (sserver->family != 0 && conn->family == 0)
115 		conn->family = sserver->family;
116 	if (sserver->address && !conn->address)
117 		conn->address = g_strdup(sserver->address);
118 	if (sserver->port > 0 && conn->port <= 0)
119 		conn->port = sserver->port;
120 
121 	conn->use_tls = sserver->use_tls;
122 	if (conn->tls_cert == NULL && sserver->tls_cert != NULL && sserver->tls_cert[0] != '\0')
123 		conn->tls_cert = g_strdup(sserver->tls_cert);
124 	if (conn->tls_pkey == NULL && sserver->tls_pkey != NULL && sserver->tls_pkey[0] != '\0')
125 		conn->tls_pkey = g_strdup(sserver->tls_pkey);
126 	if (conn->tls_pass == NULL && sserver->tls_pass != NULL && sserver->tls_pass[0] != '\0')
127 		conn->tls_pass = g_strdup(sserver->tls_pass);
128 	conn->tls_verify = sserver->tls_verify;
129 	if (conn->tls_cafile == NULL && sserver->tls_cafile != NULL && sserver->tls_cafile[0] != '\0')
130 		conn->tls_cafile = g_strdup(sserver->tls_cafile);
131 	if (conn->tls_capath == NULL && sserver->tls_capath != NULL && sserver->tls_capath[0] != '\0')
132 		conn->tls_capath = g_strdup(sserver->tls_capath);
133 	if (conn->tls_ciphers == NULL && sserver->tls_ciphers != NULL && sserver->tls_ciphers[0] != '\0')
134 		conn->tls_ciphers = g_strdup(sserver->tls_ciphers);
135 	if (conn->tls_pinned_cert == NULL && sserver->tls_pinned_cert != NULL && sserver->tls_pinned_cert[0] != '\0')
136 		conn->tls_pinned_cert = g_strdup(sserver->tls_pinned_cert);
137 	if (conn->tls_pinned_pubkey == NULL && sserver->tls_pinned_pubkey != NULL && sserver->tls_pinned_pubkey[0] != '\0')
138 		conn->tls_pinned_pubkey = g_strdup(sserver->tls_pinned_pubkey);
139 
140 	signal_emit("server setup fill reconn", 2, conn, sserver);
141 }
142 
server_setup_fill(SERVER_CONNECT_REC * conn,const char * address,int port)143 static void server_setup_fill(SERVER_CONNECT_REC *conn,
144 			      const char *address, int port)
145 {
146 	g_return_if_fail(conn != NULL);
147 	g_return_if_fail(address != NULL);
148 
149 	conn->type = module_get_uniq_id("SERVER CONNECT", 0);
150 
151 	conn->address = g_strdup(address);
152 	if (port > 0) conn->port = port;
153 
154 	if (strchr(address, '/') != NULL)
155 		conn->unix_socket = TRUE;
156 
157 	if (!conn->nick) conn->nick = g_strdup(settings_get_str("nick"));
158 	conn->username = g_strdup(settings_get_str("user_name"));
159 	conn->realname = g_strdup(settings_get_str("real_name"));
160 
161 	/* proxy settings */
162 	if (settings_get_bool("use_proxy")) {
163 		conn->proxy = g_strdup(settings_get_str("proxy_address"));
164 		conn->proxy_port = settings_get_int("proxy_port");
165 		conn->proxy_string = g_strdup(settings_get_str("proxy_string"));
166 		conn->proxy_string_after = g_strdup(settings_get_str("proxy_string_after"));
167 		conn->proxy_password = g_strdup(settings_get_str("proxy_password"));
168 	}
169 
170 	/* source IP */
171 	if (source_host_ip4 != NULL) {
172 		conn->own_ip4 = g_new(IPADDR, 1);
173 		memcpy(conn->own_ip4, source_host_ip4, sizeof(IPADDR));
174 	}
175 	if (source_host_ip6 != NULL) {
176 		conn->own_ip6 = g_new(IPADDR, 1);
177 		memcpy(conn->own_ip6, source_host_ip6, sizeof(IPADDR));
178 	}
179 
180 	signal_emit("server setup fill connect", 1, conn);
181 }
182 
server_setup_fill_server(SERVER_CONNECT_REC * conn,SERVER_SETUP_REC * sserver)183 static void server_setup_fill_server(SERVER_CONNECT_REC *conn,
184 				     SERVER_SETUP_REC *sserver)
185 {
186 	g_return_if_fail(IS_SERVER_CONNECT(conn));
187 	g_return_if_fail(IS_SERVER_SETUP(sserver));
188 
189 	sserver->last_connect = time(NULL);
190 
191 	server_setup_fill_reconn(conn, sserver);
192 
193 	signal_emit("server setup fill server", 2, conn, sserver);
194 }
195 
server_setup_fill_chatnet(SERVER_CONNECT_REC * conn,CHATNET_REC * chatnet)196 static void server_setup_fill_chatnet(SERVER_CONNECT_REC *conn,
197 				      CHATNET_REC *chatnet)
198 {
199 	g_return_if_fail(IS_SERVER_CONNECT(conn));
200 	g_return_if_fail(IS_CHATNET(chatnet));
201 
202 	if (chatnet->nick != NULL) {
203 		g_free(conn->nick);
204 		conn->nick = g_strdup(chatnet->nick);;
205 	}
206 	if (chatnet->username != NULL) {
207                 g_free(conn->username);
208 		conn->username = g_strdup(chatnet->username);;
209 	}
210 	if (chatnet->realname != NULL) {
211                 g_free(conn->realname);
212 		conn->realname = g_strdup(chatnet->realname);;
213 	}
214 	if (chatnet->own_host != NULL) {
215 		conn_set_ip(conn, chatnet->own_host,
216 			    &chatnet->own_ip4, &chatnet->own_ip6);
217 	}
218 
219 	signal_emit("server setup fill chatnet", 2, conn, chatnet);
220 }
221 
222 static SERVER_CONNECT_REC *
create_addr_conn(int chat_type,const char * address,int port,const char * chatnet,const char * password,const char * nick)223 create_addr_conn(int chat_type, const char *address, int port,
224 		 const char *chatnet, const char *password,
225 		 const char *nick)
226 {
227         CHAT_PROTOCOL_REC *proto;
228 	SERVER_CONNECT_REC *conn;
229 	SERVER_SETUP_REC *sserver;
230 	CHATNET_REC *chatnetrec;
231 
232 	g_return_val_if_fail(address != NULL, NULL);
233 
234 	sserver = server_setup_find(address, port, chatnet);
235 	if (sserver != NULL) {
236 		if (chat_type < 0)
237 			chat_type = sserver->chat_type;
238 		else if (chat_type != sserver->chat_type)
239                         sserver = NULL;
240 	}
241 
242 	proto = chat_type >= 0 ? chat_protocol_find_id(chat_type) :
243                 chat_protocol_get_default();
244 
245 	conn = proto->create_server_connect();
246 	server_connect_ref(conn);
247 
248 	conn->chat_type = proto->id;
249         if (chatnet != NULL && *chatnet != '\0')
250 		conn->chatnet = g_strdup(chatnet);
251 
252 	/* fill in the defaults */
253 	server_setup_fill(conn, address, port);
254 
255 	/* fill the rest from chat network settings */
256 	chatnetrec = chatnet != NULL ? chatnet_find(chatnet) :
257 		(sserver == NULL || sserver->chatnet == NULL ? NULL :
258 		 chatnet_find(sserver->chatnet));
259 	if (chatnetrec != NULL)
260 		server_setup_fill_chatnet(conn, chatnetrec);
261 
262 	/* fill the information from setup */
263 	if (sserver != NULL)
264 		server_setup_fill_server(conn, sserver);
265 
266 	/* nick / password given in command line overrides all settings */
267 	if (password && *password) {
268 		g_free_not_null(conn->password);
269 		conn->password = g_strdup(password);
270 	}
271 	if (nick && *nick) {
272 		g_free_not_null(conn->nick);
273 		conn->nick = g_strdup(nick);
274 	}
275 
276 	return conn;
277 }
278 
279 /* Connect to server where last connect succeeded (or we haven't tried to
280    connect yet). If there's no such server, connect to server where we
281    haven't connected for the longest time */
282 static SERVER_CONNECT_REC *
create_chatnet_conn(const char * dest,int port,const char * password,const char * nick)283 create_chatnet_conn(const char *dest, int port,
284 		    const char *password, const char *nick)
285 {
286 	SERVER_SETUP_REC *bestrec;
287 	GSList *tmp;
288 	time_t now, besttime;
289 
290 	now = time(NULL);
291 	bestrec = NULL; besttime = now;
292 	for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
293 		SERVER_SETUP_REC *rec = tmp->data;
294 
295 		if (rec->chatnet == NULL ||
296 		    g_ascii_strcasecmp(rec->chatnet, dest) != 0)
297 			continue;
298 
299 		if (!rec->last_failed) {
300 			bestrec = rec;
301 			break;
302 		}
303 
304 		if (bestrec == NULL || besttime > rec->last_connect) {
305 			bestrec = rec;
306 			besttime = rec->last_connect;
307 		}
308 	}
309 
310 	return bestrec == NULL ? NULL :
311 		create_addr_conn(bestrec->chat_type, bestrec->address, 0,
312 				 dest, NULL, nick);
313 }
314 
315 /* Create server connection record. `dest' is required, rest can be NULL.
316    `dest' is either a server address or chat network */
317 SERVER_CONNECT_REC *
server_create_conn(int chat_type,const char * dest,int port,const char * chatnet,const char * password,const char * nick)318 server_create_conn(int chat_type, const char *dest, int port,
319 		   const char *chatnet, const char *password,
320 		   const char *nick)
321 {
322 	SERVER_CONNECT_REC *rec;
323         CHATNET_REC *chatrec;
324 
325 	g_return_val_if_fail(dest != NULL, NULL);
326 
327         chatrec = chatnet_find(dest);
328 	if (chatrec != NULL) {
329 		rec = create_chatnet_conn(chatrec->name, port, password, nick);
330 		/* If rec is NULL the chatnet has no url to connect to */
331 		return rec;
332 	}
333 
334 	chatrec = chatnet == NULL ? NULL : chatnet_find(chatnet);
335 	if (chatrec != NULL)
336 		chatnet = chatrec->name;
337 
338 	return create_addr_conn(chat_type, dest, port,
339 				chatnet, password, nick);
340 }
341 
342 /* Find matching server from setup. Try to find record with a same port,
343    but fallback to any server with the same address. */
server_setup_find(const char * address,int port,const char * chatnet)344 SERVER_SETUP_REC *server_setup_find(const char *address, int port,
345 				    const char *chatnet)
346 {
347 	SERVER_SETUP_REC *server;
348 	GSList *tmp;
349 
350 	g_return_val_if_fail(address != NULL, NULL);
351 
352 	server = NULL;
353 	for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
354 		SERVER_SETUP_REC *rec = tmp->data;
355 
356 		if (g_ascii_strcasecmp(rec->address, address) == 0 &&
357 		    (chatnet == NULL || rec->chatnet == NULL ||
358 		     g_ascii_strcasecmp(rec->chatnet, chatnet) == 0)) {
359 			server = rec;
360 			if (rec->port == port)
361 				break;
362 		}
363 	}
364 
365 	return server;
366 }
367 
server_setup_read(CONFIG_NODE * node)368 static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node)
369 {
370 	SERVER_SETUP_REC *rec;
371 	CHATNET_REC *chatnetrec;
372 	char *server, *chatnet, *family;
373 	int port;
374 	char *value = NULL;
375 
376 	g_return_val_if_fail(node != NULL, NULL);
377 
378 	server = config_node_get_str(node, "address", NULL);
379 	if (server == NULL)
380 		return NULL;
381 
382 	port = config_node_get_int(node, "port", 0);
383 	chatnet = config_node_get_str(node, "chatnet", NULL);
384 
385 	if (server_setup_find(server, port, chatnet) != NULL) {
386 		return NULL;
387 	}
388 
389 	rec = NULL;
390 
391 	chatnetrec = chatnet == NULL ? NULL : chatnet_find(chatnet);
392 	if (chatnetrec == NULL && chatnet != NULL) {
393                 /* chat network not found, create it. */
394 		chatnetrec = chat_protocol_get_default()->create_chatnet();
395 		chatnetrec->chat_type = chat_protocol_get_default()->id;
396 		chatnetrec->name = g_strdup(chatnet);
397 		chatnet_create(chatnetrec);
398 	}
399 
400 	family = config_node_get_str(node, "family", "");
401 
402 	rec = CHAT_PROTOCOL(chatnetrec)->create_server_setup();
403 	rec->type = module_get_uniq_id("SERVER SETUP", 0);
404         rec->chat_type = CHAT_PROTOCOL(chatnetrec)->id;
405 	rec->chatnet = chatnetrec == NULL ? NULL : g_strdup(chatnetrec->name);
406 	rec->family = g_ascii_strcasecmp(family, "inet6") == 0 ? AF_INET6 :
407 		(g_ascii_strcasecmp(family, "inet") == 0 ? AF_INET : 0);
408 	rec->address = g_strdup(server);
409 	rec->password = g_strdup(config_node_get_str(node, "password", NULL));
410 
411 	rec->use_tls = config_node_get_bool(node, "use_tls", FALSE) || config_node_get_bool(node, "use_ssl", FALSE);
412 	rec->tls_verify = config_node_get_bool(node, "tls_verify", FALSE) || config_node_get_bool(node, "ssl_verify", FALSE);
413 
414 	value = config_node_get_str(node, "tls_cert", NULL);
415 	if (value == NULL)
416 		value = config_node_get_str(node, "ssl_cert", NULL);
417 	rec->tls_cert = g_strdup(value);
418 
419 	value = config_node_get_str(node, "tls_pkey", NULL);
420 	if (value == NULL)
421 		value = config_node_get_str(node, "ssl_pkey", NULL);
422 	rec->tls_pkey = g_strdup(value);
423 
424 	value = config_node_get_str(node, "tls_pass", NULL);
425 	if (value == NULL)
426 		value = config_node_get_str(node, "ssl_pass", NULL);
427 	rec->tls_pass = g_strdup(value);
428 
429 	value = config_node_get_str(node, "tls_cafile", NULL);
430 	if (value == NULL)
431 		value = config_node_get_str(node, "ssl_cafile", NULL);
432 	rec->tls_cafile = g_strdup(value);
433 
434 	value = config_node_get_str(node, "tls_capath", NULL);
435 	if (value == NULL)
436 		value = config_node_get_str(node, "ssl_capath", NULL);
437 	rec->tls_capath = g_strdup(value);
438 
439 	value = config_node_get_str(node, "tls_ciphers", NULL);
440 	if (value == NULL)
441 		value = config_node_get_str(node, "ssl_ciphers", NULL);
442 	rec->tls_ciphers = g_strdup(value);
443 
444 	value = config_node_get_str(node, "tls_pinned_cert", NULL);
445 	if (value == NULL)
446 		value = config_node_get_str(node, "ssl_pinned_cert", NULL);
447 	rec->tls_pinned_cert = g_strdup(value);
448 
449 	value = config_node_get_str(node, "tls_pinned_pubkey", NULL);
450 	if (value == NULL)
451 		value = config_node_get_str(node, "ssl_pinned_pubkey", NULL);
452 	rec->tls_pinned_pubkey = g_strdup(value);
453 
454 	if (rec->tls_cafile || rec->tls_capath)
455 		rec->tls_verify = TRUE;
456 	if (rec->tls_cert != NULL || rec->tls_verify)
457 		rec->use_tls = TRUE;
458 
459 	rec->port = port;
460 	rec->autoconnect = config_node_get_bool(node, "autoconnect", FALSE);
461 	rec->no_proxy = config_node_get_bool(node, "no_proxy", FALSE);
462 	rec->own_host = g_strdup(config_node_get_str(node, "own_host", NULL));
463 
464 	signal_emit("server setup read", 2, rec, node);
465 
466 	setupservers = g_slist_append(setupservers, rec);
467 	return rec;
468 }
469 
compare_server_setup(CONFIG_NODE * node,SERVER_SETUP_REC * server)470 static int compare_server_setup (CONFIG_NODE *node, SERVER_SETUP_REC *server)
471 {
472 	char *address, *chatnet;
473 	int port;
474 
475 	address = config_node_get_str(node, "address", NULL);
476 	chatnet = config_node_get_str(node, "chatnet", NULL);
477 	port = config_node_get_int(node, "port", 0);
478 
479 	if (address == NULL || chatnet == NULL) {
480 		return 0;
481 	}
482 
483 	if (g_ascii_strcasecmp(address, server->address) != 0 ||
484 	    g_ascii_strcasecmp(chatnet, server->chatnet) != 0 ||
485 	    port != server->port) {
486 		return 1;
487 	}
488 
489 	return 0;
490 }
491 
server_setup_save(SERVER_SETUP_REC * rec)492 static void server_setup_save(SERVER_SETUP_REC *rec)
493 {
494 	CONFIG_NODE *parent_node, *node;
495 	GSList *config_node;
496 
497 	parent_node = iconfig_node_traverse("(servers", TRUE);
498 
499 	/* Try to find this channel in the configuration */
500 	config_node = g_slist_find_custom(parent_node->value, rec,
501 					  (GCompareFunc)compare_server_setup);
502 	if (config_node != NULL)
503 		/* Let's update this server record */
504 		node = config_node->data;
505 	else
506 		/* Create a brand-new server record */
507 		node = iconfig_node_section(parent_node, NULL, NODE_TYPE_BLOCK);
508 
509         iconfig_node_clear(node);
510 	iconfig_node_set_str(node, "address", rec->address);
511 	iconfig_node_set_str(node, "chatnet", rec->chatnet);
512 
513 	iconfig_node_set_int(node, "port", rec->port);
514 	iconfig_node_set_str(node, "password", rec->password);
515 
516 	iconfig_node_set_bool(node, "use_tls", rec->use_tls);
517 	iconfig_node_set_str(node, "tls_cert", rec->tls_cert);
518 	iconfig_node_set_str(node, "tls_pkey", rec->tls_pkey);
519 	iconfig_node_set_str(node, "tls_pass", rec->tls_pass);
520 	iconfig_node_set_bool(node, "tls_verify", rec->tls_verify);
521 	iconfig_node_set_str(node, "tls_cafile", rec->tls_cafile);
522 	iconfig_node_set_str(node, "tls_capath", rec->tls_capath);
523 	iconfig_node_set_str(node, "tls_ciphers", rec->tls_ciphers);
524 	iconfig_node_set_str(node, "tls_pinned_cert", rec->tls_pinned_cert);
525 	iconfig_node_set_str(node, "tls_pinned_pubkey", rec->tls_pinned_pubkey);
526 
527 	iconfig_node_set_str(node, "own_host", rec->own_host);
528 
529 	iconfig_node_set_str(node, "family",
530 			     rec->family == AF_INET6 ? "inet6" :
531 			     rec->family == AF_INET ? "inet" : NULL);
532 
533 	if (rec->autoconnect)
534 		iconfig_node_set_bool(node, "autoconnect", TRUE);
535 	if (rec->no_proxy)
536 		iconfig_node_set_bool(node, "no_proxy", TRUE);
537 
538 	signal_emit("server setup saved", 2, rec, node);
539 }
540 
server_setup_remove_config(SERVER_SETUP_REC * rec)541 static void server_setup_remove_config(SERVER_SETUP_REC *rec)
542 {
543 	CONFIG_NODE *parent_node;
544 	GSList *config_node;
545 
546 	parent_node = iconfig_node_traverse("servers", FALSE);
547 
548 	if (parent_node == NULL)
549 		return;
550 
551 	/* Try to find this server in the configuration */
552 	config_node = g_slist_find_custom(parent_node->value, rec,
553 					  (GCompareFunc)compare_server_setup);
554 
555 	if (config_node != NULL)
556 		/* Delete the server from the configuration */
557 		iconfig_node_remove(parent_node, config_node->data);
558 }
559 
server_setup_destroy(SERVER_SETUP_REC * rec)560 static void server_setup_destroy(SERVER_SETUP_REC *rec)
561 {
562 	setupservers = g_slist_remove(setupservers, rec);
563 	signal_emit("server setup destroyed", 1, rec);
564 
565 	g_free_not_null(rec->own_host);
566 	g_free_not_null(rec->own_ip4);
567 	g_free_not_null(rec->own_ip6);
568 	g_free_not_null(rec->chatnet);
569 	g_free_not_null(rec->password);
570 	g_free_not_null(rec->tls_cert);
571 	g_free_not_null(rec->tls_pkey);
572 	g_free_not_null(rec->tls_pass);
573 	g_free_not_null(rec->tls_cafile);
574 	g_free_not_null(rec->tls_capath);
575 	g_free_not_null(rec->tls_ciphers);
576 	g_free_not_null(rec->tls_pinned_cert);
577 	g_free_not_null(rec->tls_pinned_pubkey);
578 	g_free(rec->address);
579 	g_free(rec);
580 }
581 
server_setup_add(SERVER_SETUP_REC * rec)582 void server_setup_add(SERVER_SETUP_REC *rec)
583 {
584 	rec->type = module_get_uniq_id("SERVER SETUP", 0);
585 	if (g_slist_find(setupservers, rec) == NULL)
586 		setupservers = g_slist_append(setupservers, rec);
587 	server_setup_save(rec);
588 
589 	signal_emit("server setup updated", 1, rec);
590 }
591 
server_setup_remove_chatnet(const char * chatnet)592 void server_setup_remove_chatnet(const char *chatnet)
593 {
594 	GSList *tmp, *next;
595 
596 	g_return_if_fail(chatnet != NULL);
597 
598 	for (tmp = setupservers; tmp != NULL; tmp = next) {
599 		SERVER_SETUP_REC *rec = tmp->data;
600 
601 		next = tmp->next;
602 		if (g_ascii_strcasecmp(rec->chatnet, chatnet) == 0)
603 			server_setup_remove(rec);
604 	}
605 }
606 
server_setup_remove(SERVER_SETUP_REC * rec)607 void server_setup_remove(SERVER_SETUP_REC *rec)
608 {
609 	server_setup_remove_config(rec);
610 	server_setup_destroy(rec);
611 }
612 
read_servers(void)613 static void read_servers(void)
614 {
615 	CONFIG_NODE *node;
616 	GSList *tmp;
617 
618 	while (setupservers != NULL)
619 		server_setup_destroy(setupservers->data);
620 
621 	/* Read servers */
622 	node = iconfig_node_traverse("servers", FALSE);
623 	if (node != NULL) {
624 		tmp = config_node_first(node->value);
625 		for (; tmp != NULL; tmp = config_node_next(tmp))
626 			server_setup_read(tmp->data);
627 	}
628 }
629 
read_settings(void)630 static void read_settings(void)
631 {
632 	if (old_source_host == NULL ||
633 	    g_strcmp0(old_source_host, settings_get_str("hostname")) != 0) {
634                 g_free_not_null(old_source_host);
635 		old_source_host = g_strdup(settings_get_str("hostname"));
636 
637 		source_host_ok = FALSE;
638 		get_source_host_ip();
639 	}
640 }
641 
servers_setup_init(void)642 void servers_setup_init(void)
643 {
644 	settings_add_str("server", "hostname", "");
645 
646 	settings_add_str("server", "nick", NULL);
647 	settings_add_str("server", "user_name", NULL);
648 	settings_add_str("server", "real_name", NULL);
649 
650 	settings_add_bool("proxy", "use_proxy", FALSE);
651 	settings_add_str("proxy", "proxy_address", "");
652 	settings_add_int("proxy", "proxy_port", 6667);
653 	settings_add_str("proxy", "proxy_string", "CONNECT %s %d");
654 	settings_add_str("proxy", "proxy_string_after", "");
655 	settings_add_str("proxy", "proxy_password", "");
656 
657         setupservers = NULL;
658 	source_host_ip4 = source_host_ip6 = NULL;
659         old_source_host = NULL;
660 	read_settings();
661 
662 	signal_add("setup changed", (SIGNAL_FUNC) read_settings);
663 	signal_add("setup reread", (SIGNAL_FUNC) read_servers);
664         signal_add("irssi init read settings", (SIGNAL_FUNC) read_servers);
665 }
666 
servers_setup_deinit(void)667 void servers_setup_deinit(void)
668 {
669 	g_free_not_null(source_host_ip4);
670 	g_free_not_null(source_host_ip6);
671 	g_free_not_null(old_source_host);
672 
673 	while (setupservers != NULL)
674 		server_setup_destroy(setupservers->data);
675 
676 	signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
677 	signal_remove("setup reread", (SIGNAL_FUNC) read_servers);
678         signal_remove("irssi init read settings", (SIGNAL_FUNC) read_servers);
679 
680 	module_uniq_destroy("SERVER SETUP");
681 }
682