guix-env: some update.
[oweals/gnunet.git] / src / testbed / gnunet-daemon-testbed-blacklist.c
1 /*
2       This file is part of GNUnet
3       Copyright (C) 2008--2013 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18       Boston, MA 02110-1301, USA.
19 */
20
21
22 /**
23  * @file testbed/gnunet-daemon-testbed-blacklist.c
24  * @brief daemon to restrict incoming connections from other peers at the
25  *          transport layer of a peer
26  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
27  */
28
29 #include "platform.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_transport_service.h"
32
33
34 /**
35  * Logging shorthand
36  */
37 #define LOG(type,...)                           \
38   GNUNET_log (type, __VA_ARGS__)
39
40 /**
41  * Debug logging shorthand
42  */
43 #define DEBUG(...)                              \
44   LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
45
46 /**
47  * Allow access from the peers read from the whitelist
48  */
49 #define ACCESS_ALLOW 1
50
51 /**
52  * Deny access from the peers read from the blacklist
53  */
54 #define ACCESS_DENY 0
55
56 /**
57  * The map to store the peer identities to allow/deny
58  */
59 static struct GNUNET_CONTAINER_MultiPeerMap *map;
60
61 /**
62  * The array of peer identities we read from whitelist/blacklist
63  */
64 static struct GNUNET_PeerIdentity *ilist;
65
66 /**
67  * The blacklist handle we obtain from transport when we register ourselves for
68  * access control
69  */
70 static struct GNUNET_TRANSPORT_Blacklist *bh;
71
72 /**
73  * Are we allowing or denying access from peers
74  */
75 static int mode;
76
77
78 /**
79  * Cleaup and destroy the map
80  */
81 static void
82 cleanup_map ()
83 {
84   if (NULL != map)
85   {
86     GNUNET_CONTAINER_multipeermap_destroy (map);
87     map = NULL;
88   }
89 }
90
91
92 /**
93  * Shutdown task to cleanup our resources and exit.
94  *
95  * @param cls NULL
96  */
97 static void
98 do_shutdown (void *cls)
99 {
100   cleanup_map ();
101   if (NULL != bh)
102     GNUNET_TRANSPORT_blacklist_cancel (bh);
103 }
104
105
106 /**
107  * Function that decides if a connection is acceptable or not.
108  *
109  * @param cls closure
110  * @param pid peer to approve or disapproave
111  * @return GNUNET_OK if the connection is allowed, GNUNET_SYSERR if not
112  */
113 static int
114 check_access (void *cls, const struct GNUNET_PeerIdentity * pid)
115 {
116   int contains;
117
118   if (NULL != map)
119     contains = GNUNET_CONTAINER_multipeermap_contains (map, pid);
120   else
121     contains = GNUNET_NO;
122   if (ACCESS_DENY == mode)
123     return (contains) ? GNUNET_SYSERR : GNUNET_OK;
124   return (contains) ? GNUNET_OK : GNUNET_SYSERR;
125 }
126
127
128 /**
129  * Setup the access control by reading the given file containing peer identities
130  * and then establishing blacklist handler with the peer's transport service
131  *
132  * @param fname the filename to read the list of peer identities
133  * @param cfg the configuration for connecting to the peer's transport service
134  */
135 static void
136 setup_ac (const char *fname,
137           const struct GNUNET_CONFIGURATION_Handle *cfg)
138 {
139   uint64_t fsize;
140   unsigned int npeers;
141   unsigned int cnt;
142
143   GNUNET_assert (GNUNET_OK !=
144                  GNUNET_DISK_file_size (fname, &fsize, GNUNET_NO,
145                                         GNUNET_YES));
146   if (0 != (fsize % sizeof (struct GNUNET_PeerIdentity)))
147   {
148     GNUNET_break (0);
149     return;
150   }
151   npeers = fsize / sizeof (struct GNUNET_PeerIdentity);
152   if (0 != npeers)
153   {
154     map = GNUNET_CONTAINER_multipeermap_create (npeers, GNUNET_YES);
155     ilist = GNUNET_malloc_large (fsize);
156     GNUNET_assert (fsize == GNUNET_DISK_fn_read (fname, ilist, fsize));
157   }
158   for (cnt = 0; cnt < npeers; cnt++)
159   {
160     if (GNUNET_SYSERR ==
161         GNUNET_CONTAINER_multipeermap_put (map, &ilist[cnt],
162                                            &ilist[cnt],
163                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
164     {
165       cleanup_map ();
166       GNUNET_free (ilist);
167       return;
168     }
169   }
170   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
171   bh = GNUNET_TRANSPORT_blacklist (cfg, &check_access, NULL);
172 }
173
174
175 /**
176  * Main function that will be run.
177  *
178  * @param cls closure
179  * @param args remaining command-line arguments
180  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
181  * @param c configuration
182  */
183 static void
184 run (void *cls,
185      char *const *args,
186      const char *cfgfile,
187      const struct GNUNET_CONFIGURATION_Handle *c)
188 {
189   char *shome;
190   char *fname;
191
192   if (GNUNET_OK !=
193       GNUNET_CONFIGURATION_get_value_filename (c, "PATHS",
194                                                "GNUNET_HOME",
195                                                &shome))
196   {
197     GNUNET_break (0);
198     return;
199   }
200   GNUNET_asprintf (&fname,
201                    "%s/whitelist",
202                    shome);
203   if (GNUNET_YES == GNUNET_DISK_file_test (fname))
204   {
205     mode = ACCESS_ALLOW;
206     setup_ac (fname, c);
207     GNUNET_free (shome);
208     GNUNET_free (fname);
209     return;
210   }
211   GNUNET_asprintf (&fname,
212                    "%s/blacklist",
213                    shome);
214   if (GNUNET_YES == GNUNET_DISK_file_test (fname))
215   {
216     mode = ACCESS_DENY;
217     setup_ac (shome, c);
218   }
219   GNUNET_free (shome);
220   GNUNET_free (fname);
221 }
222
223
224 /**
225  * The main function.
226  *
227  * @param argc number of arguments from the command line
228  * @param argv command line arguments
229  * @return 0 ok, 1 on error
230  */
231 int
232 main (int argc, char *const *argv)
233 {
234   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
235     GNUNET_GETOPT_OPTION_END
236   };
237   int ret;
238
239   if (GNUNET_OK !=
240       GNUNET_STRINGS_get_utf8_args (argc, argv,
241                                     &argc, &argv))
242     return 2;
243   ret =
244       (GNUNET_OK ==
245        GNUNET_PROGRAM_run (argc, argv,
246                            "gnunet-daemon-testbed-blacklist",
247                            _("Daemon to restrict incoming transport layer connections during testbed deployments"),
248                            options, &run, NULL)) ? 0 : 1;
249   GNUNET_free ((void*) argv);
250   return ret;
251 }