Example #1
0
/**
 * Add an SOA record to the UDP packet at the given location.
 *
 * @param dst where to write the SOA record
 * @param dst_len number of bytes in @a dst
 * @param off pointer to offset where to write the SOA information (increment by bytes used)
 *            can also change if there was an error
 * @param soa SOA information to write
 * @return #GNUNET_SYSERR if @a soa is invalid
 *         #GNUNET_NO if @a soa did not fit
 *         #GNUNET_OK if @a soa was added to @a dst
 */
int
GNUNET_DNSPARSER_builder_add_soa (char *dst,
				  size_t dst_len,
				  size_t *off,
				  const struct GNUNET_DNSPARSER_SoaRecord *soa)
{
  struct GNUNET_TUN_DnsSoaRecord sd;
  int ret;

  if ( (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst,
                                                               dst_len,
                                                               off,
                                                               soa->mname))) ||
       (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst,
                                                               dst_len,
                                                               off,
                                                               soa->rname)) ) )
    return ret;
  if (*off + sizeof (struct GNUNET_TUN_DnsSoaRecord) > dst_len)
    return GNUNET_NO;
  sd.serial = htonl (soa->serial);
  sd.refresh = htonl (soa->refresh);
  sd.retry = htonl (soa->retry);
  sd.expire = htonl (soa->expire);
  sd.minimum = htonl (soa->minimum_ttl);
  GNUNET_memcpy (&dst[*off], &sd, sizeof (sd));
  (*off) += sizeof (sd);
  return GNUNET_OK;
}
Example #2
0
/**
 * Add an MX record to the UDP packet at the given location.
 *
 * @param dst where to write the mx record
 * @param dst_len number of bytes in @a dst
 * @param off pointer to offset where to write the mx information (increment by bytes used);
 *            can also change if there was an error
 * @param mx mx information to write
 * @return #GNUNET_SYSERR if @a mx is invalid
 *         #GNUNET_NO if @a mx did not fit
 *         #GNUNET_OK if @a mx was added to @a dst
 */
int
GNUNET_DNSPARSER_builder_add_mx (char *dst,
				 size_t dst_len,
				 size_t *off,
				 const struct GNUNET_DNSPARSER_MxRecord *mx)
{
  uint16_t mxpref;

  if (*off + sizeof (uint16_t) > dst_len)
    return GNUNET_NO;
  mxpref = htons (mx->preference);
  GNUNET_memcpy (&dst[*off], &mxpref, sizeof (mxpref));
  (*off) += sizeof (mxpref);
  return GNUNET_DNSPARSER_builder_add_name (dst, dst_len, off, mx->mxhost);
}
Example #3
0
/**
 * Add a DNS query to the UDP packet at the given location.
 *
 * @param dst where to write the query
 * @param dst_len number of bytes in @a dst
 * @param off pointer to offset where to write the query (increment by bytes used)
 *            must not be changed if there is an error
 * @param query query to write
 * @return #GNUNET_SYSERR if @a query is invalid
 *         #GNUNET_NO if @a query did not fit
 *         #GNUNET_OK if @a query was added to @a dst
 */
int
GNUNET_DNSPARSER_builder_add_query (char *dst,
				    size_t dst_len,
				    size_t *off,
				    const struct GNUNET_DNSPARSER_Query *query)
{
  int ret;
  struct GNUNET_TUN_DnsQueryLine ql;

  ret = GNUNET_DNSPARSER_builder_add_name (dst, dst_len - sizeof (struct GNUNET_TUN_DnsQueryLine), off, query->name);
  if (ret != GNUNET_OK)
    return ret;
  ql.type = htons (query->type);
  ql.dns_traffic_class = htons (query->dns_traffic_class);
  GNUNET_memcpy (&dst[*off], &ql, sizeof (ql));
  (*off) += sizeof (ql);
  return GNUNET_OK;
}
Example #4
0
/**
 * Add an SRV record to the UDP packet at the given location.
 *
 * @param dst where to write the SRV record
 * @param dst_len number of bytes in @a dst
 * @param off pointer to offset where to write the SRV information (increment by bytes used)
 *            can also change if there was an error
 * @param srv SRV information to write
 * @return #GNUNET_SYSERR if @a srv is invalid
 *         #GNUNET_NO if @a srv did not fit
 *         #GNUNET_OK if @a srv was added to @a dst
 */
int
GNUNET_DNSPARSER_builder_add_srv (char *dst,
				  size_t dst_len,
				  size_t *off,
				  const struct GNUNET_DNSPARSER_SrvRecord *srv)
{
  struct GNUNET_TUN_DnsSrvRecord sd;
  int ret;

  if (*off + sizeof (struct GNUNET_TUN_DnsSrvRecord) > dst_len)
    return GNUNET_NO;
  sd.prio = htons (srv->priority);
  sd.weight = htons (srv->weight);
  sd.port = htons (srv->port);
  GNUNET_memcpy (&dst[*off], &sd, sizeof (sd));
  (*off) += sizeof (sd);
  if (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst,
				    dst_len,
				    off,
				    srv->target)))
    return ret;
  return GNUNET_OK;
}
Example #5
0
/**
 * Add a DNS record to the UDP packet at the given location.
 *
 * @param dst where to write the query
 * @param dst_len number of bytes in @a dst
 * @param off pointer to offset where to write the query (increment by bytes used)
 *            must not be changed if there is an error
 * @param record record to write
 * @return #GNUNET_SYSERR if @a record is invalid
 *         #GNUNET_NO if @a record did not fit
 *         #GNUNET_OK if @a record was added to @a dst
 */
static int
add_record (char *dst,
	    size_t dst_len,
	    size_t *off,
	    const struct GNUNET_DNSPARSER_Record *record)
{
  int ret;
  size_t start;
  size_t pos;
  struct GNUNET_TUN_DnsRecordLine rl;

  start = *off;
  ret = GNUNET_DNSPARSER_builder_add_name (dst,
                                           dst_len - sizeof (struct GNUNET_TUN_DnsRecordLine),
                                           off,
                                           record->name);
  if (GNUNET_OK != ret)
    return ret;
  /* '*off' is now the position where we will need to write the record line */

  pos = *off + sizeof (struct GNUNET_TUN_DnsRecordLine);
  switch (record->type)
  {
  case GNUNET_DNSPARSER_TYPE_MX:
    ret = GNUNET_DNSPARSER_builder_add_mx (dst, dst_len, &pos, record->data.mx);
    break;
  case GNUNET_DNSPARSER_TYPE_CERT:
    ret = GNUNET_DNSPARSER_builder_add_cert (dst, dst_len, &pos, record->data.cert);
    break;
  case GNUNET_DNSPARSER_TYPE_SOA:
    ret = GNUNET_DNSPARSER_builder_add_soa (dst, dst_len, &pos, record->data.soa);
    break;
  case GNUNET_DNSPARSER_TYPE_NS:
  case GNUNET_DNSPARSER_TYPE_CNAME:
  case GNUNET_DNSPARSER_TYPE_PTR:
    ret = GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &pos, record->data.hostname);
    break;
  case GNUNET_DNSPARSER_TYPE_SRV:
    ret = GNUNET_DNSPARSER_builder_add_srv (dst, dst_len, &pos, record->data.srv);
    break;
  default:
    if (pos + record->data.raw.data_len > dst_len)
    {
      ret = GNUNET_NO;
      break;
    }
    GNUNET_memcpy (&dst[pos], record->data.raw.data, record->data.raw.data_len);
    pos += record->data.raw.data_len;
    ret = GNUNET_OK;
    break;
  }
  if (GNUNET_OK != ret)
  {
    *off = start;
    return GNUNET_NO;
  }

  if (pos - (*off + sizeof (struct GNUNET_TUN_DnsRecordLine)) > UINT16_MAX)
  {
    /* record data too long */
    *off = start;
    return GNUNET_NO;
  }
  rl.type = htons (record->type);
  rl.dns_traffic_class = htons (record->dns_traffic_class);
  rl.ttl = htonl (GNUNET_TIME_absolute_get_remaining (record->expiration_time).rel_value_us / 1000LL / 1000LL); /* in seconds */
  rl.data_len = htons ((uint16_t) (pos - (*off + sizeof (struct GNUNET_TUN_DnsRecordLine))));
  GNUNET_memcpy (&dst[*off], &rl, sizeof (struct GNUNET_TUN_DnsRecordLine));
  *off = pos;
  return GNUNET_OK;
}
Example #6
0
/**
 * Convert human-readable version of a 'value' of a record to the binary
 * representation.
 *
 * @param cls closure, unused
 * @param type type of the record
 * @param s human-readable string
 * @param data set to value in binary encoding (will be allocated)
 * @param data_size set to number of bytes in @a data
 * @return #GNUNET_OK on success
 */
static int
gns_string_to_value (void *cls,
                     uint32_t type,
                     const char *s,
                     void **data,
                     size_t *data_size)
{
  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;

  if (NULL == s)
    return GNUNET_SYSERR;
  switch (type)
  {

  case GNUNET_GNSRECORD_TYPE_PKEY:
    if (GNUNET_OK !=
	GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
           _("Unable to parse PKEY record `%s'\n"),
           s);
      return GNUNET_SYSERR;
    }
    *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
    memcpy (*data, &pkey, sizeof (pkey));
    *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
    return GNUNET_OK;

  case GNUNET_GNSRECORD_TYPE_NICK:
    *data = GNUNET_strdup (s);
    *data_size = strlen (s);
    return GNUNET_OK;
  case GNUNET_GNSRECORD_TYPE_LEHO:
    *data = GNUNET_strdup (s);
    *data_size = strlen (s);
    return GNUNET_OK;
  case GNUNET_GNSRECORD_TYPE_GNS2DNS:
    {
      char nsbuf[514];
      char *cpy;
      char *at;
      size_t off;

      cpy = GNUNET_strdup (s);
      at = strchr (cpy, '@');
      if (NULL == at)
      {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                    _("Unable to parse GNS2DNS record `%s'\n"),
                    s);
        GNUNET_free (cpy);
        return GNUNET_SYSERR;
      }
      *at = '\0';
      at++;

      off = 0;
      if ( (GNUNET_OK !=
            GNUNET_DNSPARSER_builder_add_name (nsbuf,
                                               sizeof (nsbuf),
                                               &off,
                                               cpy)) ||
           (GNUNET_OK !=
            GNUNET_DNSPARSER_builder_add_name (nsbuf,
                                               sizeof (nsbuf),
                                               &off,
                                               at)) )
      {
	GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                    _("Failed to serialize GNS2DNS record with value `%s'\n"),
                    s);
        GNUNET_free (cpy);
	return GNUNET_SYSERR;
      }
      GNUNET_free (cpy);
      *data_size = off;
      *data = GNUNET_malloc (off);
      memcpy (*data, nsbuf, off);
      return GNUNET_OK;
    }
  case GNUNET_GNSRECORD_TYPE_VPN:
    {
      struct GNUNET_TUN_GnsVpnRecord *vpn;
      char s_peer[103 + 1];
      char s_serv[253 + 1];
      unsigned int proto;

      if (3 != SSCANF (s,
                       "%u %103s %253s",
                       &proto, s_peer, s_serv))
      {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                    _("Unable to parse VPN record string `%s'\n"),
                    s);
        return GNUNET_SYSERR;
      }
      *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1;
      *data = vpn = GNUNET_malloc (*data_size);
      if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer,
                                                                   strlen (s_peer),
                                                                   &vpn->peer.public_key))
      {
        GNUNET_free (vpn);
        *data_size = 0;
        return GNUNET_SYSERR;
      }
      vpn->proto = htons ((uint16_t) proto);
      strcpy ((char*)&vpn[1], s_serv);
      return GNUNET_OK;
    }
  case GNUNET_GNSRECORD_TYPE_BOX:
    {
      struct GNUNET_GNSRECORD_BoxRecord *box;
      size_t rest;
      unsigned int protocol;
      unsigned int service;
      unsigned int record_type;
      void *bval;
      size_t bval_size;

      if (3 != SSCANF (s,
                       "%u %u %u ",
                       &protocol,
                       &service,
                       &record_type))
      {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                    _("Unable to parse BOX record string `%s'\n"),
                    s);
        return GNUNET_SYSERR;
      }
      rest = snprintf (NULL, 0,
                       "%u %u %u ",
                       protocol,
                       service,
                       record_type);
      if (GNUNET_OK !=
          GNUNET_GNSRECORD_string_to_value (record_type,
                                            &s[rest],
                                            &bval,
                                            &bval_size))
        return GNUNET_SYSERR;
      *data_size = sizeof (struct GNUNET_GNSRECORD_BoxRecord) + bval_size;
      *data = box = GNUNET_malloc (*data_size);
      box->protocol = htons (protocol);
      box->service = htons (service);
      box->record_type = htonl (record_type);
      memcpy (&box[1],
              bval,
              bval_size);
      GNUNET_free (bval);
      return GNUNET_OK;
    }
  default:
    return GNUNET_SYSERR;
  }
}
Example #7
0
/**
 * Convert human-readable version of a 'value' of a record to the binary
 * representation.
 *
 * @param cls closure, unused
 * @param type type of the record
 * @param s human-readable string
 * @param data set to value in binary encoding (will be allocated)
 * @param data_size set to number of bytes in @a data
 * @return #GNUNET_OK on success
 */
static int
gns_string_to_value (void *cls,
                     uint32_t type,
                     const char *s,
                     void **data,
                     size_t *data_size)
{
  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;

  if (NULL == s)
    return GNUNET_SYSERR;
  switch (type)
  {

    case GNUNET_GNSRECORD_TYPE_PKEY:
      if (GNUNET_OK !=
          GNUNET_CRYPTO_ecdsa_public_key_from_string (s, strlen (s), &pkey))
      {
        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                    _("Unable to parse PKEY record `%s'\n"),
                    s);
        return GNUNET_SYSERR;
      }
      *data = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPublicKey);
      GNUNET_memcpy (*data, &pkey, sizeof (pkey));
      *data_size = sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey);
      return GNUNET_OK;

    case GNUNET_GNSRECORD_TYPE_NICK:
      *data = GNUNET_strdup (s);
      *data_size = strlen (s);
      return GNUNET_OK;
    case GNUNET_GNSRECORD_TYPE_LEHO:
      *data = GNUNET_strdup (s);
      *data_size = strlen (s);
      return GNUNET_OK;
    case GNUNET_GNSRECORD_TYPE_GNS2DNS:
      {
        char nsbuf[514];
        char *cpy;
        char *at;
        size_t off;

        cpy = GNUNET_strdup (s);
        at = strchr (cpy, '@');
        if (NULL == at)
        {
          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                      _("Unable to parse GNS2DNS record `%s'\n"),
                      s);
          GNUNET_free (cpy);
          return GNUNET_SYSERR;
        }
        *at = '\0';
        at++;

        off = 0;
        if ( (GNUNET_OK !=
              GNUNET_DNSPARSER_builder_add_name (nsbuf,
                                                 sizeof (nsbuf),
                                                 &off,
                                                 cpy)) ||
             (GNUNET_OK !=
              GNUNET_DNSPARSER_builder_add_name (nsbuf,
                                                 sizeof (nsbuf),
                                                 &off,
                                                 at)) )
        {
          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                      _("Failed to serialize GNS2DNS record with value `%s'\n"),
                      s);
          GNUNET_free (cpy);
          return GNUNET_SYSERR;
        }
        GNUNET_free (cpy);
        *data_size = off;
        *data = GNUNET_malloc (off);
        GNUNET_memcpy (*data, nsbuf, off);
        return GNUNET_OK;
      }
    case GNUNET_GNSRECORD_TYPE_VPN:
      {
        struct GNUNET_TUN_GnsVpnRecord *vpn;
        char s_peer[103 + 1];
        char s_serv[253 + 1];
        unsigned int proto;

        if (3 != SSCANF (s,
                         "%u %103s %253s",
                         &proto, s_peer, s_serv))
        {
          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                      _("Unable to parse VPN record string `%s'\n"),
                      s);
          return GNUNET_SYSERR;
        }
        *data_size = sizeof (struct GNUNET_TUN_GnsVpnRecord) + strlen (s_serv) + 1;
        *data = vpn = GNUNET_malloc (*data_size);
        if (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string ((char*) s_peer,
                                                                     strlen (s_peer),
                                                                     &vpn->peer.public_key))
        {
          GNUNET_free (vpn);
          *data_size = 0;
          return GNUNET_SYSERR;
        }
        vpn->proto = htons ((uint16_t) proto);
        strcpy ((char*)&vpn[1], s_serv);
        return GNUNET_OK;
      }
    case GNUNET_GNSRECORD_TYPE_BOX:
      {
        struct GNUNET_GNSRECORD_BoxRecord *box;
        size_t rest;
        unsigned int protocol;
        unsigned int service;
        unsigned int record_type;
        void *bval;
        size_t bval_size;

        if (3 != SSCANF (s,
                         "%u %u %u ",
                         &protocol,
                         &service,
                         &record_type))
        {
          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                      _("Unable to parse BOX record string `%s'\n"),
                      s);
          return GNUNET_SYSERR;
        }
        rest = snprintf (NULL, 0,
                         "%u %u %u ",
                         protocol,
                         service,
                         record_type);
        if (GNUNET_OK !=
            GNUNET_GNSRECORD_string_to_value (record_type,
                                              &s[rest],
                                              &bval,
                                              &bval_size))
          return GNUNET_SYSERR;
        *data_size = sizeof (struct GNUNET_GNSRECORD_BoxRecord) + bval_size;
        *data = box = GNUNET_malloc (*data_size);
        box->protocol = htons (protocol);
        box->service = htons (service);
        box->record_type = htonl (record_type);
        GNUNET_memcpy (&box[1],
                       bval,
                       bval_size);
        GNUNET_free (bval);
        return GNUNET_OK;
      }
    case GNUNET_GNSRECORD_TYPE_REVERSE:
      {
        struct GNUNET_GNSRECORD_ReverseRecord *rev;
        char known_by[253 + 1];
        struct GNUNET_TIME_Absolute expiration;

        /* TODO: From crypto_ecc.c
         * Why is this not a constant???
         */
        size_t enclen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
        if (enclen % 5 > 0)
          enclen += 5 - enclen % 5;
        enclen /= 5; /* 260/5 = 52 */
        char pkey_str[enclen + 1];

        if (3 != SSCANF (s,
                         "%253s %52s %"SCNu64,
                         known_by,
                         pkey_str,
                         &expiration.abs_value_us))
        {
          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                      _("Unable to parse REVERSE record string `%s'\n"),
                      s);
          return GNUNET_SYSERR;
        }
        *data_size = sizeof (struct GNUNET_GNSRECORD_ReverseRecord) + strlen (known_by) + 1;
        *data = rev = GNUNET_malloc (*data_size);
        GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str,
                                                    strlen (pkey_str),
                                                    &rev->pkey);
        rev->expiration = expiration;
        GNUNET_memcpy (&rev[1],
                       known_by,
                       strlen (known_by));
        return GNUNET_OK;
      }
    default:
      return GNUNET_SYSERR;
  }
}