import of dnsmasq-2.51.tar.gz
diff --git a/src/util.c b/src/util.c
index e9fe27d..ce77f05 100644
--- a/src/util.c
+++ b/src/util.c
@@ -24,6 +24,9 @@
#include <sys/times.h>
#endif
+#ifdef LOCALEDIR
+#include <idna.h>
+#endif
#ifdef HAVE_ARC4RANDOM
void rand_init(void)
@@ -95,48 +98,110 @@
#endif
-
-int legal_char(char c)
+static int check_name(char *in)
{
- /* check for legal char a-z A-Z 0-9 -
- (also / , used for RFC2317 and _ used in windows queries
- and space, for DNS-SD stuff) */
- if ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= '0' && c <= '9') ||
- c == '-' || c == '/' || c == '_' || c == ' ')
- return 1;
-
- return 0;
-}
-
-int canonicalise(char *s)
-{
- /* check for legal chars and remove trailing .
+ /* remove trailing .
also fail empty string and label > 63 chars */
- size_t dotgap = 0, l = strlen(s);
+ size_t dotgap = 0, l = strlen(in);
char c;
int nowhite = 0;
-
+
if (l == 0 || l > MAXDNAME) return 0;
-
- if (s[l-1] == '.')
+
+ if (in[l-1] == '.')
{
if (l == 1) return 0;
- s[l-1] = 0;
+ in[l-1] = 0;
}
- while ((c = *s))
+ for (; (c = *in); in++)
{
if (c == '.')
dotgap = 0;
- else if (!legal_char(c) || (++dotgap > MAXLABEL))
+ else if (++dotgap > MAXLABEL)
return 0;
+ else if (isascii(c) && iscntrl(c))
+ /* iscntrl only gives expected results for ascii */
+ return 0;
+#ifndef LOCALEDIR
+ else if (!isascii(c))
+ return 0;
+#endif
else if (c != ' ')
nowhite = 1;
- s++;
}
- return nowhite;
+
+ if (!nowhite)
+ return 0;
+
+ return 1;
+}
+
+/* Hostnames have a more limited valid charset than domain names
+ so check for legal char a-z A-Z 0-9 - _
+ Note that this may receive a FQDN, so only check the first label
+ for the tighter criteria. */
+int legal_hostname(char *name)
+{
+ char c;
+
+ if (!check_name(name))
+ return 0;
+
+ for (; (c = *name); name++)
+ /* check for legal char a-z A-Z 0-9 - _ . */
+ {
+ if ((c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') ||
+ c == '-' || c == '_')
+ continue;
+
+ /* end of hostname part */
+ if (c == '.')
+ return 1;
+
+ return 0;
+ }
+
+ return 1;
+}
+
+char *canonicalise(char *in, int *nomem)
+{
+ char *ret = NULL;
+#ifdef LOCALEDIR
+ int rc;
+#endif
+
+ if (nomem)
+ *nomem = 0;
+
+ if (!check_name(in))
+ return NULL;
+
+#ifdef LOCALEDIR
+ if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
+ {
+ if (ret)
+ free(ret);
+
+ if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
+ {
+ my_syslog(LOG_ERR, _("failed to allocate memory"));
+ *nomem = 1;
+ }
+
+ return NULL;
+ }
+#else
+ if ((ret = whine_malloc(strlen(in)+1)))
+ strcpy(ret, in);
+ else if (nomem)
+ *nomem = 1;
+#endif
+
+ return ret;
}
unsigned char *do_rfc1035_name(unsigned char *p, char *sval)