plugin_gnsrecord_conversation.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. This file is part of GNUnet
  3. Copyright (C) 2013 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file conversation/plugin_gnsrecord_conversation.c
  18. * @brief gnsrecord plugin to provide the API for fundamental GNS records
  19. * This includes the VPN record because GNS resolution
  20. * is expected to understand VPN records and (if needed)
  21. * map the result to A/AAAA.
  22. * @author Christian Grothoff
  23. */
  24. #include "platform.h"
  25. #include "gnunet_util_lib.h"
  26. #include "gnunet_gnsrecord_lib.h"
  27. #include "gnunet_conversation_service.h"
  28. #include "gnunet_gnsrecord_plugin.h"
  29. /**
  30. * Convert the 'value' of a record to a string.
  31. *
  32. * @param cls closure, unused
  33. * @param type type of the record
  34. * @param data value in binary encoding
  35. * @param data_size number of bytes in @a data
  36. * @return NULL on error, otherwise human-readable representation of the value
  37. */
  38. static char *
  39. conversation_value_to_string (void *cls,
  40. uint32_t type,
  41. const void *data,
  42. size_t data_size)
  43. {
  44. char *s;
  45. (void) cls;
  46. switch (type)
  47. {
  48. case GNUNET_GNSRECORD_TYPE_PHONE:
  49. {
  50. const struct GNUNET_CONVERSATION_PhoneRecord *pr;
  51. char *ret;
  52. char *pkey;
  53. if (data_size != sizeof(struct GNUNET_CONVERSATION_PhoneRecord))
  54. {
  55. GNUNET_break_op (0);
  56. return NULL;
  57. }
  58. pr = data;
  59. if (1 != ntohl (pr->version))
  60. {
  61. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  62. _ ("PHONE version %u not supported\n"),
  63. ntohl (pr->version));
  64. return NULL;
  65. }
  66. pkey = GNUNET_CRYPTO_eddsa_public_key_to_string (&pr->peer.public_key);
  67. s = GNUNET_STRINGS_data_to_string_alloc (&pr->line_port,
  68. sizeof(struct GNUNET_HashCode));
  69. GNUNET_asprintf (&ret,
  70. "%s-%s",
  71. s,
  72. pkey);
  73. GNUNET_free (s);
  74. GNUNET_free (pkey);
  75. return ret;
  76. }
  77. default:
  78. return NULL;
  79. }
  80. }
  81. /**
  82. * Convert human-readable version of a 'value' of a record to the binary
  83. * representation.
  84. *
  85. * @param cls closure, unused
  86. * @param type type of the record
  87. * @param s human-readable string
  88. * @param data set to value in binary encoding (will be allocated)
  89. * @param data_size set to number of bytes in @a data
  90. * @return #GNUNET_OK on success
  91. */
  92. static int
  93. conversation_string_to_value (void *cls,
  94. uint32_t type,
  95. const char *s,
  96. void **data,
  97. size_t *data_size)
  98. {
  99. (void) cls;
  100. if (NULL == s)
  101. {
  102. GNUNET_break (0);
  103. return GNUNET_SYSERR;
  104. }
  105. switch (type)
  106. {
  107. case GNUNET_GNSRECORD_TYPE_PHONE:
  108. {
  109. struct GNUNET_CONVERSATION_PhoneRecord *pr;
  110. char line_port[103];
  111. const char *dash;
  112. struct GNUNET_PeerIdentity peer;
  113. if ((NULL == (dash = strchr (s, '-'))) ||
  114. (1 != sscanf (s, "%103s-", line_port)) ||
  115. (GNUNET_OK !=
  116. GNUNET_CRYPTO_eddsa_public_key_from_string (dash + 1,
  117. strlen (dash + 1),
  118. &peer.public_key)))
  119. {
  120. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  121. _ ("Unable to parse PHONE record `%s'\n"),
  122. s);
  123. return GNUNET_SYSERR;
  124. }
  125. pr = GNUNET_new (struct GNUNET_CONVERSATION_PhoneRecord);
  126. pr->version = htonl (1);
  127. pr->reserved = htonl (0);
  128. if (GNUNET_OK !=
  129. GNUNET_STRINGS_string_to_data (line_port,
  130. strlen (line_port),
  131. &pr->line_port,
  132. sizeof(struct GNUNET_HashCode)))
  133. {
  134. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  135. _ ("Unable to parse PHONE record `%s'\n"),
  136. s);
  137. GNUNET_free (pr);
  138. return GNUNET_SYSERR;
  139. }
  140. pr->peer = peer;
  141. *data = pr;
  142. *data_size = sizeof(struct GNUNET_CONVERSATION_PhoneRecord);
  143. return GNUNET_OK;
  144. }
  145. default:
  146. return GNUNET_SYSERR;
  147. }
  148. }
  149. /**
  150. * Mapping of record type numbers to human-readable
  151. * record type names.
  152. */
  153. static struct
  154. {
  155. const char *name;
  156. uint32_t number;
  157. } name_map[] = {
  158. { "PHONE", GNUNET_GNSRECORD_TYPE_PHONE },
  159. { NULL, UINT32_MAX }
  160. };
  161. /**
  162. * Convert a type name (e.g. "AAAA") to the corresponding number.
  163. *
  164. * @param cls closure, unused
  165. * @param gns_typename name to convert
  166. * @return corresponding number, UINT32_MAX on error
  167. */
  168. static uint32_t
  169. conversation_typename_to_number (void *cls,
  170. const char *gns_typename)
  171. {
  172. unsigned int i;
  173. (void) cls;
  174. i = 0;
  175. while ((name_map[i].name != NULL) &&
  176. (0 != strcasecmp (gns_typename, name_map[i].name)))
  177. i++;
  178. return name_map[i].number;
  179. }
  180. /**
  181. * Convert a type number to the corresponding type string (e.g. 1 to "A")
  182. *
  183. * @param cls closure, unused
  184. * @param type number of a type to convert
  185. * @return corresponding typestring, NULL on error
  186. */
  187. static const char *
  188. conversation_number_to_typename (void *cls,
  189. uint32_t type)
  190. {
  191. unsigned int i;
  192. (void) cls;
  193. i = 0;
  194. while ((name_map[i].name != NULL) &&
  195. (type != name_map[i].number))
  196. i++;
  197. return name_map[i].name;
  198. }
  199. /**
  200. * Entry point for the plugin.
  201. *
  202. * @param cls NULL
  203. * @return the exported block API
  204. */
  205. void *
  206. libgnunet_plugin_gnsrecord_conversation_init (void *cls)
  207. {
  208. struct GNUNET_GNSRECORD_PluginFunctions *api;
  209. (void) cls;
  210. api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
  211. api->value_to_string = &conversation_value_to_string;
  212. api->string_to_value = &conversation_string_to_value;
  213. api->typename_to_number = &conversation_typename_to_number;
  214. api->number_to_typename = &conversation_number_to_typename;
  215. return api;
  216. }
  217. /**
  218. * Exit point from the plugin.
  219. *
  220. * @param cls the return value from #libgnunet_plugin_block_test_init
  221. * @return NULL
  222. */
  223. void *
  224. libgnunet_plugin_gnsrecord_conversation_done (void *cls)
  225. {
  226. struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
  227. GNUNET_free (api);
  228. return NULL;
  229. }
  230. /* end of plugin_gnsrecord_conversation.c */