aboutsummaryrefslogtreecommitdiff
path: root/src/setup/gnunet-setup-exit-services.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/setup/gnunet-setup-exit-services.c')
-rw-r--r--src/setup/gnunet-setup-exit-services.c762
1 files changed, 762 insertions, 0 deletions
diff --git a/src/setup/gnunet-setup-exit-services.c b/src/setup/gnunet-setup-exit-services.c
new file mode 100644
index 00000000..91b58b05
--- /dev/null
+++ b/src/setup/gnunet-setup-exit-services.c
@@ -0,0 +1,762 @@
1/*
2 This file is part of GNUnet.
3 (C) 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file src/setup/gnunet-setup-exit-services.c
23 * @brief code for the dialog to configure EXIT records
24 * @author Christian Grothoff
25 */
26#include "gnunet-setup.h"
27#include <gnunet/gnunet_util_lib.h>
28#include <gdk/gdkkeysyms.h>
29
30
31/**
32 * Columns in the hosted service model.
33 */
34enum ServiceModelColumns
35{
36 /**
37 * A gchararray
38 */
39 SERVICE_MC_HOSTNAME = 0,
40
41 /**
42 * A gboolean
43 */
44 SERVICE_MC_ISUDP = 1
45
46 /**
47 * A guint
48 */
49 SERVICE_MC_VISIBLE_PORT = 2,
50
51 /**
52 * Destination adddress, a gchararray
53 */
54 SERVICE_MC_DESTINATION_ADDRESS = 3
55
56};
57
58
59/**
60 * Check if the section represents a hosted service and then update
61 * the GtkListStore accordingly.
62 *
63 * @param cls the list store to modify
64 * @param section name of the section
65 */
66static void
67add_dns_entry_to_list_store (void *cls,
68 const char *section)
69{
70 GtkListStore *ls = cls;
71 GtkTreeIter iter;
72 char *sld;
73 char *destination;
74 char *redirect;
75 char *cpy;
76 gboolean udp;
77
78 if (NULL == section)
79 {
80 gtk_list_store_insert_with_values (ls, &iter, G_MAXINT,
81 SERVICE_MC_HOSTNAME, "",
82 SERVICE_MC_ISUDP, FALSE,
83 SERVICE_MC_VISIBLE_PORT, (guint) 80,
84 SERVICE_MC_DESTINATION_ADDRESS, "127.0.0.1:8080",
85 -1);
86 return;
87 }
88
89 if ((8 > strlen (section)) ||
90 (0 != strcmp (".gnunet.", section + ((strlen (section) - 8)))))
91 return;
92 sld = GNUNET_strdup (section);
93 sld[strlen (section) - 8] = '\0';
94 udp = FALSE;
95 do
96 {
97 if (GNUNET_OK ==
98 GNUNET_CONFIGURATION_get_value_string (cfg, section,
99 (udp)
100 ? "UDP_REDIRECTS"
101 : "TCP_REDIRECTS",
102 &cpy))
103 {
104 for (redirect = strtok (cpy, " "); NULL != redirect;
105 redirect = strtok (NULL, " "))
106 {
107 if (NULL == (hostname = strstr (redirect, ":")))
108 {
109 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
110 _("Option `%s' is not formatted correctly!\n"), redirect);
111 continue;
112 }
113 hostname[0] = '\0';
114 hostname++;
115
116 guint local_port = atoi (redirect);
117 if (!((local_port > 0) && (local_port < 65536)))
118 {
119 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
120 _("`%s' is not a valid port number!\n"), redirect);
121 continue;
122 }
123 gtk_list_store_insert_with_values (ls, &iter, 0,
124 SERVICE_MC_HOSTNAME, sld,
125 SERVICE_MC_ISUDP, udp,
126 SERVICE_MC_VISIBLE_PORT, local_port,
127 SERVICE_MC_DESTINATION_ADDRESS, hostname,
128 -1);
129 }
130 GNUNET_free (cpy);
131 }
132 udp = !udp;
133 }
134 while (udp);
135 GNUNET_free (sld);
136}
137
138
139/**
140 * Initialize the GtkListModel with the hosted service specification.
141 *
142 * @param cls NULL
143 * @param section section with the value (NULL)
144 * @param option option name (NULL)
145 * @param value value as a string (NULL)
146 * @param widget widget to initialize (the GtkTreeView)
147 * @param cfg configuration handle
148 * @return #GNUNET_OK on success, #GNUNET_SYSERR if there was a problem
149 */
150static int
151load_hosted_service_configuration (const void *cls,
152 const char *section,
153 const char *option,
154 const char *value,
155 GObject * widget,
156 const struct GNUNET_CONFIGURATION_Handle *cfg)
157{
158 GtkTreeView *tv;
159 GtkListStore *ls;
160
161 tv = GTK_TREE_VIEW (widget);
162 if (NULL == tv)
163 {
164 GNUNET_break (0);
165 return GNUNET_SYSERR;
166 }
167 ls = GTK_LIST_STORE (gtk_tree_view_get_model (tv));
168 GNUNET_CONFIGURATION_iterate_sections (cfg,
169 &add_dns_entry_to_list_store,
170 ls);
171 /* finally, add empty entry */
172 add_dns_entry_to_list_store (ls, NULL);
173 return GNUNET_OK;
174}
175
176
177/**
178 * Records we use to build DNS information lists.
179 */
180struct DnsInfo
181{
182 /**
183 * We keep these in a singly-linked list.
184 */
185 struct DnsInfo *next;
186
187 /**
188 * Name of the section in the configuration (must end in ".gnunet.").
189 */
190 char *section;
191
192 /**
193 * String describing all TCP redirects.
194 */
195 char *tcpred;
196
197 /**
198 * String describing all UDP redirects.
199 */
200 char *udpred;
201
202};
203
204
205/**
206 * Function called for each section in the configuration.
207 * Gather existing ttl, section names and altnames.
208 *
209 * @param cls 'struct DnsInfo**' to create
210 * @param section name of a section in the configuration
211 */
212static void
213collect_dns_sections (void *cls,
214 const char *section)
215{
216 struct DnsInfo **base = cls;
217 struct DnsInfo *pos;
218
219 if ((8 > strlen (section)) ||
220 (0 != strcmp (".gnunet.",
221 section + ((strlen (section) - 8)))))
222 return;
223 pos = GNUNET_new (struct DnsInfo);
224 pos->section = GNUNET_strdup (section);
225 pos->tcpred = GNUNET_strdup ("");
226 pos->udpred = GNUNET_strdup ("");
227 pos->next = *base;
228 *base = pos;
229}
230
231
232/**
233 * Function called for each section in the configuration.
234 * Removes those ending in '.gnunet.'.
235 *
236 * @param cls unused
237 * @param section name of a section in the configuration
238 */
239static void
240remove_dns_sections (void *cls,
241 const char *section)
242{
243 if ((8 > strlen (section)) ||
244 (0 != strcmp (".gnunet.", section + ((strlen (section) - 8)))))
245 return;
246 GNUNET_CONFIGURATION_remove_section (cfg, section);
247}
248
249
250/**
251 * Given the list store and the data in it, update the
252 * configuration file accordingly.
253 *
254 * @param tm model to use
255 */
256static void
257update_vpn_dns_configuration (GtkTreeModel * tm)
258{
259 GtkTreeIter iter;
260 gchar *name;
261 guint srcport;
262 gchar *targetaddress;
263 gboolea is_udp;
264 char *tmp;
265 struct DnsInfo *head;
266 struct DnsInfo *pos;
267
268 head = NULL;
269 GNUNET_CONFIGURATION_iterate_sections (cfg,
270 &collect_dns_sections,
271 &head);
272 if (gtk_tree_model_get_iter_first (tm, &iter))
273 do
274 {
275 gtk_tree_model_get (tm, &iter,
276 SERVICE_MC_HOSTNAME, &name,
277 SERVICE_MC_ISUDP, &is_udp,
278 SERVICE_MC_VISIBLE_PORT, &srcport,
279 SERVICE_MC_DESTINATION_ADDRESS, &targetaddress,
280 -1);
281 if (0 != strlen (name))
282 {
283 pos = head;
284 GNUNET_asprintf (&tmp, "%s.gnunet.", name);
285 while ((NULL != pos) && (0 != strcasecmp (tmp, pos->section)))
286 pos = pos->next;
287 if (NULL == pos)
288 {
289 pos = GNUNET_new (struct DnsInfo);
290 pos->section = tmp;
291 pos->tcpred = GNUNET_strdup ("");
292 pos->udpred = GNUNET_strdup ("");
293 pos->next = head;
294 head = pos;
295 }
296 else
297 {
298 GNUNET_free (tmp);
299 }
300 GNUNET_asprintf (&tmp,
301 "%u:%s %s",
302 srcport,
303 targetaddress,
304 (is_udp)
305 ? pos->udpred
306 : pos->tcpred);
307 if (is_udp)
308 {
309 GNUNET_free (pos->udpred);
310 pos->udpred = tmp;
311 }
312 else
313 {
314 GNUNET_free (pos->tcpred);
315 pos->tcpred = tmp;
316 }
317 }
318 g_free (name);
319 g_free (targetaddress);
320 }
321 while (TRUE == gtk_tree_model_iter_next (tm, &iter));
322 GNUNET_CONFIGURATION_iterate_sections (cfg,
323 &remove_dns_sections,
324 NULL);
325 while (NULL != head)
326 {
327 pos = head;
328 head = pos->next;
329 if (strlen (pos->udpred) > 0)
330 GNUNET_CONFIGURATION_set_value_string (cfg, pos->section,
331 "UDP_REDIRECTS",
332 pos->udpred);
333 if (strlen (pos->tcpred) > 0)
334 GNUNET_CONFIGURATION_set_value_string (cfg, pos->section,
335 "TCP_REDIRECTS",
336 pos->tcpred);
337 GNUNET_free (pos->tcpred);
338 GNUNET_free (pos->udpred);
339 GNUNET_free (pos->section);
340 GNUNET_free (pos);
341 }
342}
343
344
345/**
346 * The user has edited the DNS name of a service we're offering.
347 * Update the GtkTreeModel (at the given path) and update the
348 * respective service entry in the configuration file. Finally,
349 * if the edited path is for a "fresh" entry, create another empty
350 * one at the bottom. If the hostname was set to empty, remove
351 * the entire entry from the configuration and the model.
352 *
353 * @param renderer GtkCellRendererText that changed
354 * @param path GtkTreePath identifying where in the Model the change is
355 * @param new_text the new text that was stored in the line
356 * @param user_data NULL
357 */
358static void
359save_vpn_dns_service_dnsname (GtkCellRendererText * renderer,
360 gchar * path,
361 gchar * new_text,
362 gpointer user_data)
363{
364 GtkTreeModel *tm;
365 GtkListStore *ls;
366 GtkTreeIter iter;
367 gchar *old;
368
369 tm = GTK_TREE_MODEL (GNUNET_SETUP_get_object ("GNUNET_setup_gns_liststore"));
370 if (NULL == tm)
371 {
372 GNUNET_break (0);
373 return;
374 }
375 ls = GTK_LIST_STORE (tm);
376 if (NULL == ls)
377 {
378 GNUNET_break (0);
379 return;
380 }
381 if (TRUE != gtk_tree_model_get_iter_from_string (tm, &iter, path))
382 {
383 GNUNET_break (0);
384 return;
385 }
386 gtk_tree_model_get (tm, &iter, SERVICE_MC_HOSTNAME, &old, -1);
387 if ((0 != strlen (old)) && (0 == strlen (new_text)))
388 {
389 /* deletion */
390 gtk_list_store_remove (ls, &iter);
391 g_free (old);
392 /* update configuration */
393 update_vpn_dns_configuration (tm);
394 return;
395 }
396 /* update model */
397 gtk_list_store_set (ls, &iter,
398 SERVICE_MC_HOSTNAME, new_text, -1);
399 /* update configuration */
400 update_vpn_dns_configuration (tm);
401 if ((0 == strlen (old)) && (0 != strlen (new_text)))
402 {
403 /* need another empty entry at the end for future expansion */
404 add_dns_entry_to_list_store (GTK_LIST_STORE (tm), NULL);
405 }
406 g_free (old);
407}
408
409
410/**
411 * Initialize the GtkListModel with the VPN's DNS service specification.
412 *
413 * @param cls NULL
414 * @param section section with the value (NULL)
415 * @param option option name (NULL)
416 * @param widget widget to initialize (the GtkTreeView)
417 * @param cfg configuration handle
418 * @return #GNUNET_OK on success, #GNUNET_SYSERR if there was a problem
419 */
420static int
421gns_name_install_edited_handler (const void *cls,
422 const char *section,
423 const char *option,
424 GObject * widget,
425 struct GNUNET_CONFIGURATION_Handle *cfg)
426{
427 static int once;
428 GtkCellRendererText *rt;
429
430 rt = GTK_CELL_RENDERER_TEXT (widget);
431 if (NULL == rt)
432 return GNUNET_SYSERR;
433 if (0 != once++)
434 return GNUNET_OK;
435 g_signal_connect (rt, "edited",
436 G_CALLBACK (&save_vpn_dns_service_dnsname),
437 NULL);
438 return GNUNET_OK;
439}
440
441
442/**
443 * The user has edited the DNS name of a service we're offering.
444 * Update the GtkTreeModel (at the given path) and update the
445 * respective service entry in the configuration file. Finally,
446 * if the edited path is for a "fresh" entry, create another empty
447 * one at the bottom. If the hostname was set to empty, remove
448 * the entire entry from the configuration and the model.
449 *
450 * @param renderer GtkCellRendererText that changed
451 * @param path GtkTreePath identifying where in the Model the change is
452 * @param new_text the new text that was stored in the line
453 * @param user_data NULL
454 */
455static void
456save_vpn_dns_service_tcpudp (GtkCellRendererText * renderer,
457 gchar * path,
458 gchar * new_text,
459 gpointer user_data)
460{
461 GtkTreeModel *tm;
462 GtkListStore *ls;
463 GtkTreeIter iter;
464
465 if ((0 != strcasecmp ("tcp", new_text)) &&
466 (0 != strcasecmp ("udp", new_text)))
467 {
468 /* FIXME: warn... */
469 return;
470 }
471 tm = GTK_TREE_MODEL (GNUNET_SETUP_get_object ("GNUNET_setup_gns_liststore"));
472 if (NULL == tm)
473 {
474 GNUNET_break (0);
475 return;
476 }
477 ls = GTK_LIST_STORE (tm);
478 if (NULL == ls)
479 {
480 GNUNET_break (0);
481 return;
482 }
483 if (TRUE != gtk_tree_model_get_iter_from_string (tm, &iter, path))
484 {
485 GNUNET_break (0);
486 return;
487 }
488 /* update model */
489 gtk_list_store_set (ls, &iter, SERVICE_MC_ISUDP, new_text, -1);
490 /* update configuration */
491 update_vpn_dns_configuration (tm);
492}
493
494
495/**
496 * Initialize the GtkListModel with the VPN's DNS service specification.
497 *
498 * @param cls NULL
499 * @param section section with the value (NULL)
500 * @param option option name (NULL)
501 * @param widget widget to initialize (the GtkTreeView)
502 * @param cfg configuration handle
503 * @return #GNUNET_OK on success, #GNUNET_SYSERR if there was a problem
504 */
505static int
506gns_type_install_edited_handler (const void *cls,
507 const char *section,
508 const char *option,
509 GObject * widget,
510 struct GNUNET_CONFIGURATION_Handle *cfg)
511{
512 static int once;
513 GtkCellRendererText *rt;
514
515 rt = GTK_CELL_RENDERER_TEXT (widget);
516 if (NULL == rt)
517 return GNUNET_SYSERR;
518 if (0 != once++)
519 return GNUNET_OK;
520 g_signal_connect (rt, "edited", G_CALLBACK (&save_vpn_dns_service_tcpudp),
521 NULL);
522 return GNUNET_OK;
523}
524
525
526/**
527 * The user has edited the DNS name of a service we're offering.
528 * Update the GtkTreeModel (at the given path) and update the
529 * respective service entry in the configuration file. Finally,
530 * if the edited path is for a "fresh" entry, create another empty
531 * one at the bottom. If the hostname was set to empty, remove
532 * the entire entry from the configuration and the model.
533 *
534 * @param renderer GtkCellRendererText that changed
535 * @param path GtkTreePath identifying where in the Model the change is
536 * @param new_text the new text that was stored in the line
537 * @param user_data NULL
538 */
539static void
540save_vpn_dns_service_sourceport (GtkCellRendererText * renderer,
541 gchar * path,
542 gchar * new_text,
543 gpointer user_data)
544{
545 GtkTreeModel *tm;
546 GtkListStore *ls;
547 GtkTreeIter iter;
548 int port;
549
550 port = atoi (new_text);
551 if ((port < 1) || (port > UINT16_MAX))
552 {
553 /* invalid port, FIXME: warn */
554 return;
555 }
556 tm = GTK_TREE_MODEL (GNUNET_SETUP_get_object ("GNUNET_setup_gns_liststore"));
557 if (NULL == tm)
558 {
559 GNUNET_break (0);
560 return;
561 }
562 ls = GTK_LIST_STORE (tm);
563 if (NULL == ls)
564 {
565 GNUNET_break (0);
566 return;
567 }
568 if (TRUE != gtk_tree_model_get_iter_from_string (tm, &iter, path))
569 {
570 GNUNET_break (0);
571 return;
572 }
573 /* update model */
574 gtk_list_store_set (ls, &iter,
575 SERVICE_MC_SOURCEPORT, (guint) port, -1);
576 /* update configuration */
577 update_vpn_dns_configuration (tm);
578}
579
580
581/**
582 * Initialize the GtkListModel with the VPN's DNS service specification.
583 *
584 * @param cls NULL
585 * @param section section with the value (NULL)
586 * @param option option name (NULL)
587 * @param widget widget to initialize (the GtkTreeView)
588 * @param cfg configuration handle
589 * @return #GNUNET_OK on success, #GNUNET_SYSERR if there was a problem
590 */
591static int
592gns_ttl_install_edited_handler (const void *cls,
593 const char *section,
594 const char *option,
595 GObject * widget,
596 struct GNUNET_CONFIGURATION_Handle *cfg)
597{
598 static int once;
599 GtkCellRendererText *rt;
600
601 rt = GTK_CELL_RENDERER_TEXT (widget);
602 if (NULL == rt)
603 return GNUNET_SYSERR;
604 if (0 != once++)
605 return GNUNET_OK;
606 g_signal_connect (rt, "edited", G_CALLBACK (&save_vpn_dns_service_sourceport),
607 NULL);
608 return GNUNET_OK;
609}
610
611
612/**
613 * The user has edited the DNS name of a service we're offering.
614 * Update the GtkTreeModel (at the given path) and update the
615 * respective service entry in the configuration file. Finally,
616 * if the edited path is for a "fresh" entry, create another empty
617 * one at the bottom. If the hostname was set to empty, remove
618 * the entire entry from the configuration and the model.
619 *
620 * @param renderer GtkCellRendererText that changed
621 * @param path GtkTreePath identifying where in the Model the change is
622 * @param new_text the new text that was stored in the line
623 * @param user_data NULL
624 */
625static void
626save_vpn_dns_service_targethostname (GtkCellRendererText * renderer,
627 gchar * path, gchar * new_text,
628 gpointer user_data)
629{
630 GtkTreeModel *tm;
631 GtkListStore *ls;
632 GtkTreeIter iter;
633
634 tm = GTK_TREE_MODEL (GNUNET_SETUP_get_object ("GNUNET_setup_gns_liststore"));
635 if (NULL == tm)
636 {
637 GNUNET_break (0);
638 return;
639 }
640 ls = GTK_LIST_STORE (tm);
641 if (NULL == ls)
642 {
643 GNUNET_break (0);
644 return;
645 }
646 if (TRUE != gtk_tree_model_get_iter_from_string (tm, &iter, path))
647 {
648 GNUNET_break (0);
649 return;
650 }
651 /* update model */
652 gtk_list_store_set (ls, &iter,
653 SERVICE_MC_TARGETHOSTNAME, new_text, -1);
654 /* update configuration */
655 update_vpn_dns_configuration (tm);
656}
657
658
659/**
660 * Initialize the GtkListModel with the VPN's DNS service specification.
661 *
662 * @param cls NULL
663 * @param section section with the value (NULL)
664 * @param option option name (NULL)
665 * @param widget widget to initialize (the GtkTreeView)
666 * @param cfg configuration handle
667 * @return #GNUNET_OK on success, #GNUNET_SYSERR if there was a problem
668 */
669static int
670gns_value_install_edited_handler (const void *cls,
671 const char *section,
672 const char *option,
673 GObject * widget,
674 struct GNUNET_CONFIGURATION_Handle *cfg)
675{
676 static int once;
677 GtkCellRendererText *rt;
678
679 rt = GTK_CELL_RENDERER_TEXT (widget);
680 if (NULL == rt)
681 return GNUNET_SYSERR;
682 if (0 != once++)
683 return GNUNET_OK;
684 g_signal_connect (rt, "edited",
685 G_CALLBACK (&save_vpn_dns_service_targethostname), NULL);
686 return GNUNET_OK;
687}
688
689
690#if 0
691 {
692 "GNUNET_setup_gns_treeview",
693 NULL,
694 NULL,
695 NULL,
696 gettext_noop
697 ("Specification of .gnunet TLD"),
698 "https://gnunet.org/configuration-dns",
699 &load_vpn_dns_configuration,
700 NULL, NULL,
701 NULL, NULL,
702 NULL},
703
704 {
705 "GNUNET_setup_gns_name_cellrenderertext",
706 "editing-started",
707 NULL,
708 NULL,
709 NULL,
710 "https://gnunet.org/configuration-dns",
711 NULL,
712 &gns_name_install_edited_handler,
713 NULL,
714 NULL,
715 NULL,
716 NULL},
717
718 {
719 "GNUNET_setup_gns_type_cellrenderertext",
720 "editing-started",
721 NULL,
722 NULL,
723 NULL,
724 "https://gnunet.org/configuration-dns",
725 NULL,
726 &gns_type_install_edited_handler,
727 NULL,
728 NULL,
729 NULL,
730 NULL},
731
732 {
733 "GNUNET_setup_gns_ttl_cellrenderertext",
734 "editing-started",
735 NULL,
736 NULL,
737 NULL,
738 "https://gnunet.org/configuration-dns",
739 NULL,
740 &gns_ttl_install_edited_handler,
741 NULL,
742 NULL,
743 NULL,
744 NULL},
745
746 {
747 "GNUNET_setup_gns_value_cellrenderertext",
748 "editing-started",
749 NULL,
750 NULL,
751 NULL,
752 "https://gnunet.org/configuration-dns",
753 NULL,
754 &gns_value_install_edited_handler,
755 NULL,
756 NULL,
757 NULL,
758 NULL},
759
760#endif
761
762/* end of gnunet-setup-dns-exit.c */