diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-10-16 12:07:46 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-10-16 12:07:46 +0000 |
commit | 10e14fa5739998d29fb8f47f54e45df52eff0d9d (patch) | |
tree | 6dd65c1fc587eda6f0d5d8f6255b14d6fb0e6720 /src/gns/plugin_gnsrecord_gns.c | |
parent | 7848f548f552b3576dc029e276bbe4aeb4e5392c (diff) | |
download | gnunet-10e14fa5739998d29fb8f47f54e45df52eff0d9d.tar.gz gnunet-10e14fa5739998d29fb8f47f54e45df52eff0d9d.zip |
-adding plugin for fundamental gns records
Diffstat (limited to 'src/gns/plugin_gnsrecord_gns.c')
-rw-r--r-- | src/gns/plugin_gnsrecord_gns.c | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/src/gns/plugin_gnsrecord_gns.c b/src/gns/plugin_gnsrecord_gns.c new file mode 100644 index 000000000..56e35f05b --- /dev/null +++ b/src/gns/plugin_gnsrecord_gns.c | |||
@@ -0,0 +1,303 @@ | |||
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 gnsrecord/plugin_gnsrecord_gns.c | ||
23 | * @brief gnsrecord plugin to provide the API for fundamental GNS records | ||
24 | * This includes the VPN record because GNS resolution | ||
25 | * is expected to understand VPN records and (if needed) | ||
26 | * map the result to A/AAAA. | ||
27 | * @author Christian Grothoff | ||
28 | */ | ||
29 | |||
30 | #include "platform.h" | ||
31 | #include "gnunet_util_lib.h" | ||
32 | #include "gnunet_gnsrecord_lib.h" | ||
33 | #include "gnunet_dnsparser_lib.h" | ||
34 | #include "gnunet_gnsrecord_plugin.h" | ||
35 | |||
36 | |||
37 | /** | ||
38 | * Convert the 'value' of a record to a string. | ||
39 | * | ||
40 | * @param cls closure, unused | ||
41 | * @param type type of the record | ||
42 | * @param data value in binary encoding | ||
43 | * @param data_size number of bytes in @a data | ||
44 | * @return NULL on error, otherwise human-readable representation of the value | ||
45 | */ | ||
46 | static char * | ||
47 | gns_value_to_string (void *cls, | ||
48 | uint32_t type, | ||
49 | const void *data, | ||
50 | size_t data_size) | ||
51 | { | ||
52 | const char *cdata; | ||
53 | |||
54 | switch (type) | ||
55 | { | ||
56 | case GNUNET_GNSRECORD_TYPE_PKEY: | ||
57 | if (data_size != sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) | ||
58 | return NULL; | ||
59 | return GNUNET_CRYPTO_ecdsa_public_key_to_string (data); | ||
60 | case GNUNET_GNSRECORD_TYPE_PSEU: | ||
61 | return GNUNET_strndup (data, data_size); | ||
62 | case GNUNET_GNSRECORD_TYPE_LEHO: | ||
63 | return GNUNET_strndup (data, data_size); | ||
64 | case GNUNET_GNSRECORD_TYPE_GNS2DNS: | ||
65 | { | ||
66 | char *ns; | ||
67 | size_t off; | ||
68 | |||
69 | off = 0; | ||
70 | ns = GNUNET_DNSPARSER_parse_name (data, | ||
71 | data_size, | ||
72 | &off); | ||
73 | if ( (NULL == ns) || | ||
74 | (off != data_size) ) | ||
75 | { | ||
76 | GNUNET_break_op (0); | ||
77 | GNUNET_free_non_null (ns); | ||
78 | return NULL; | ||
79 | } | ||
80 | return ns; | ||
81 | } | ||
82 | case GNUNET_GNSRECORD_TYPE_VPN: | ||
83 | { | ||
84 | const struct GNUNET_TUN_GnsVpnRecord *vpn; | ||
85 | char* vpn_str; | ||
86 | |||
87 | cdata = data; | ||
88 | if ( (data_size <= sizeof (struct GNUNET_TUN_GnsVpnRecord)) || | ||
89 | ('\0' != cdata[data_size - 1]) ) | ||
90 | return NULL; /* malformed */ | ||
91 | vpn = data; | ||
92 | if (0 == GNUNET_asprintf (&vpn_str, "%u %s %s", | ||
93 | (unsigned int) ntohs (vpn->proto), | ||
94 | (const char*) GNUNET_i2s_full (&vpn->peer), | ||
95 | (const char*) &vpn[1])) | ||
96 | { | ||
97 | GNUNET_free (vpn_str); | ||
98 | return NULL; | ||
99 | } | ||
100 | return vpn_str; | ||
101 | } | ||
102 | default: | ||
103 | return NULL; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | |||
108 | /** | ||
109 | * Convert human-readable version of a 'value' of a record to the binary | ||
110 | * representation. | ||
111 | * | ||
112 | * @param cls closure, unused | ||
113 | * @param type type of the record | ||
114 | * @param s human-readable string | ||
115 | * @param data set to value in binary encoding (will be allocated) | ||
116 | * @param data_size set to number of bytes in @a data | ||
117 | * @return #GNUNET_OK on success | ||
118 | */ | ||
119 | static int | ||
120 | gns_string_to_value (void *cls, | ||
121 | uint32_t type, | ||
122 | const char *s, | ||
123 | void **data, | ||
124 | size_t *data_size) | ||
125 | { | ||
126 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; | ||
127 | struct GNUNET_TUN_GnsVpnRecord *vpn; | ||
128 | char s_peer[103 + 1]; | ||
129 | char s_serv[253 + 1]; | ||
130 | unsigned int proto; | ||
131 | |||
132 | if (NULL == s) | ||
133 | return GNUNET_SYSERR; | ||
134 | switch (type) | ||
135 | { | ||
136 | |||
137 | case GNUNET_GNSRECORD_TYPE_PKEY: | ||
138 | if (GNUNET_OK != | ||
139 | GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey)) | ||
140 | { | ||
141 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
142 | _("Unable to parse PKEY record `%s'\n"), | ||
143 | s); | ||
144 | return GNUNET_SYSERR; | ||
145 | } | ||
146 | *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey); | ||
147 | memcpy (*data, &pkey, sizeof (pkey)); | ||
148 | *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey); | ||
149 | return GNUNET_OK; | ||
150 | |||
151 | case GNUNET_GNSRECORD_TYPE_PSEU: | ||
152 | *data = GNUNET_strdup (s); | ||
153 | *data_size = strlen (s); | ||
154 | return GNUNET_OK; | ||
155 | case GNUNET_GNSRECORD_TYPE_LEHO: | ||
156 | *data = GNUNET_strdup (s); | ||
157 | *data_size = strlen (s); | ||
158 | return GNUNET_OK; | ||
159 | case GNUNET_GNSRECORD_TYPE_GNS2DNS: | ||
160 | { | ||
161 | char nsbuf[256]; | ||
162 | size_t off; | ||
163 | |||
164 | off = 0; | ||
165 | if (GNUNET_OK != | ||
166 | GNUNET_DNSPARSER_builder_add_name (nsbuf, | ||
167 | sizeof (nsbuf), | ||
168 | &off, | ||
169 | s)) | ||
170 | { | ||
171 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
172 | _("Failed to serialize GNS2DNS record with value `%s'\n"), | ||
173 | s); | ||
174 | return GNUNET_SYSERR; | ||
175 | } | ||
176 | *data_size = off; | ||
177 | *data = GNUNET_malloc (off); | ||
178 | memcpy (*data, nsbuf, off); | ||
179 | return GNUNET_OK; | ||
180 | } | ||
181 | case GNUNET_GNSRECORD_TYPE_VPN: | ||
182 | if (3 != SSCANF (s,"%u %103s %253s", | ||
183 | &proto, s_peer, s_serv)) | ||
184 | { | ||
185 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
186 | _("Unable to parse VPN record string `%s'\n"), | ||
187 | s); | ||
188 | return GNUNET_SYSERR; | ||
189 | } | ||
190 | *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1; | ||
191 | *data = vpn = GNUNET_malloc (*data_size); | ||
192 | if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer, | ||
193 | strlen (s_peer), | ||
194 | &vpn->peer.public_key)) | ||
195 | { | ||
196 | GNUNET_free (vpn); | ||
197 | *data_size = 0; | ||
198 | return GNUNET_SYSERR; | ||
199 | } | ||
200 | vpn->proto = htons ((uint16_t) proto); | ||
201 | strcpy ((char*)&vpn[1], s_serv); | ||
202 | return GNUNET_OK; | ||
203 | default: | ||
204 | return GNUNET_SYSERR; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | |||
209 | /** | ||
210 | * Mapping of record type numbers to human-readable | ||
211 | * record type names. | ||
212 | */ | ||
213 | static struct { | ||
214 | const char *name; | ||
215 | uint32_t number; | ||
216 | } name_map[] = { | ||
217 | { "PKEY", GNUNET_GNSRECORD_TYPE_PKEY }, | ||
218 | { "PSEU", GNUNET_GNSRECORD_TYPE_PSEU }, | ||
219 | { "LEHO", GNUNET_GNSRECORD_TYPE_LEHO }, | ||
220 | { "VPN", GNUNET_GNSRECORD_TYPE_VPN }, | ||
221 | { "GNS2DNS", GNUNET_GNSRECORD_TYPE_GNS2DNS }, | ||
222 | { NULL, UINT32_MAX } | ||
223 | }; | ||
224 | |||
225 | |||
226 | /** | ||
227 | * Convert a type name (i.e. "AAAA") to the corresponding number. | ||
228 | * | ||
229 | * @param cls closure, unused | ||
230 | * @param gns_typename name to convert | ||
231 | * @return corresponding number, UINT32_MAX on error | ||
232 | */ | ||
233 | static uint32_t | ||
234 | gns_typename_to_number (void *cls, | ||
235 | const char *gns_typename) | ||
236 | { | ||
237 | unsigned int i; | ||
238 | |||
239 | i=0; | ||
240 | while ( (name_map[i].name != NULL) && | ||
241 | (0 != strcasecmp (gns_typename, name_map[i].name)) ) | ||
242 | i++; | ||
243 | return name_map[i].number; | ||
244 | } | ||
245 | |||
246 | |||
247 | /** | ||
248 | * Convert a type number (i.e. 1) to the corresponding type string (i.e. "A") | ||
249 | * | ||
250 | * @param cls closure, unused | ||
251 | * @param type number of a type to convert | ||
252 | * @return corresponding typestring, NULL on error | ||
253 | */ | ||
254 | static const char * | ||
255 | gns_number_to_typename (void *cls, | ||
256 | uint32_t type) | ||
257 | { | ||
258 | unsigned int i; | ||
259 | |||
260 | i=0; | ||
261 | while ( (name_map[i].name != NULL) && | ||
262 | (type != name_map[i].number) ) | ||
263 | i++; | ||
264 | return name_map[i].name; | ||
265 | } | ||
266 | |||
267 | |||
268 | /** | ||
269 | * Entry point for the plugin. | ||
270 | * | ||
271 | * @param cls NULL | ||
272 | * @return the exported block API | ||
273 | */ | ||
274 | void * | ||
275 | libgnunet_plugin_gnsrecord_gns_init (void *cls) | ||
276 | { | ||
277 | struct GNUNET_GNSRECORD_PluginFunctions *api; | ||
278 | |||
279 | api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions); | ||
280 | api->value_to_string = &gns_value_to_string; | ||
281 | api->string_to_value = &gns_string_to_value; | ||
282 | api->typename_to_number = &gns_typename_to_number; | ||
283 | api->number_to_typename = &gns_number_to_typename; | ||
284 | return api; | ||
285 | } | ||
286 | |||
287 | |||
288 | /** | ||
289 | * Exit point from the plugin. | ||
290 | * | ||
291 | * @param cls the return value from #libgnunet_plugin_block_test_init | ||
292 | * @return NULL | ||
293 | */ | ||
294 | void * | ||
295 | libgnunet_plugin_gnsrecord_gns_done (void *cls) | ||
296 | { | ||
297 | struct GNUNET_GNSRECORD_PluginFunctions *api = cls; | ||
298 | |||
299 | GNUNET_free (api); | ||
300 | return NULL; | ||
301 | } | ||
302 | |||
303 | /* end of plugin_gnsrecord_gns.c */ | ||