/*
This file is part of GNUnet
Copyright (C) 2010-2014 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
GNUnet is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file dns/dnsparser.c
* @brief helper library to parse DNS packets.
* @author Philipp Toelke
* @author Christian Grothoff
*/
#include "platform.h"
#include <idna.h>
#if WINDOWS
#include <idn-free.h>
#endif
#include "gnunet_util_lib.h"
#include "gnunet_dnsparser_lib.h"
#include "gnunet_tun_lib.h"
/**
* Check if a label in UTF-8 format can be coded into valid IDNA.
* This can fail if the ASCII-conversion becomes longer than 63 characters.
*
* @param label label to check (UTF-8 string)
* @return #GNUNET_OK if the label can be converted to IDNA,
* #GNUNET_SYSERR if the label is not valid for DNS names
*/
int
GNUNET_DNSPARSER_check_label (const char *label)
{
char *output;
size_t slen;
if (NULL != strchr (label, '.'))
return GNUNET_SYSERR; /* not a label! Did you mean GNUNET_DNSPARSER_check_name? */
if (IDNA_SUCCESS !=
idna_to_ascii_8z (label, &output, IDNA_ALLOW_UNASSIGNED))
return GNUNET_SYSERR;
slen = strlen (output);
#if WINDOWS
idn_free (output);
#else
free (output);
#endif
return (slen > 63) ? GNUNET_SYSERR : GNUNET_OK;
}
/**
* Check if a label in UTF-8 format can be coded into valid IDNA.
* This can fail if the ASCII-conversion becomes longer than 253 characters.
*
* @param name name to check (UTF-8 string)
* @return #GNUNET_OK if the label can be converted to IDNA,
* #GNUNET_SYSERR if the label is not valid for DNS names
*/
int
GNUNET_DNSPARSER_check_name (const char *name)
{
char *ldup;
char *output;
size_t slen;
char *tok;
ldup = GNUNET_strdup (name);
for (tok = strtok (ldup, "."); NULL != tok; tok = strtok (NULL, "."))
if (GNUNET_OK !=
GNUNET_DNSPARSER_check_label (tok))
{
GNUNET_free (ldup);
return GNUNET_SYSERR;
}
GNUNET_free (ldup);
if (IDNA_SUCCESS !=
idna_to_ascii_8z (name, &output, IDNA_ALLOW_UNASSIGNED))
return GNUNET_SYSERR;
slen = strlen (output);
#if WINDOWS
idn_free (output);
#else
free (output);
#endif
return (slen > 253) ? GNUNET_SYSERR : GNUNET_OK;
}
/**
* Free SOA information record.
*
* @param soa record to free
*/
void
GNUNET_DNSPARSER_free_soa (