Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Aug 2007 12:33:33 GMT
From:      Fredrik Lindberg <fli@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 125012 for review
Message-ID:  <200708101233.l7ACXX3H011512@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=125012

Change 125012 by fli@fli_nexus on 2007/08/10 12:33:25

	- Add a name validation function that verifies name length,
	  label length, removes duplicated label separators and make
	  sure names are properly dot-terminated.
	- Add a (correct) TXT resource encoding function.
	- Some minor whitespace fixes.

Affected files ...

.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdns.h#7 edit
.. //depot/projects/soc2007/fli-mdns_sd/mdnsd/stack_util.c#5 edit

Differences ...

==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/mdns.h#7 (text+ko) ====

@@ -99,7 +99,7 @@
 		char *bufptr; /* Direct buffer data pointer */
 		char **offsets; /* Section offset pointers */
 		int last_offset;
-		TAILQ_HEAD(, mdns_pkg_res) res_head; 
+		TAILQ_HEAD(, mdns_pkg_res) res_head;
 	} p_data[4];
 #define p_buf(x) p_data[x].bufptr
 #define p_bufseg(x) p_data[x].buf
@@ -292,5 +292,6 @@
 int mdns_type_atoi(const char *);
 void * mdns_res_encode(uint16_t, uint16_t, void *, int, size_t, size_t *);
 char * mdns_name_encode(wchar_t *, size_t, int);
+int mdns_name_validate(char *, size_t *, size_t);
 
 #endif /* _MDNS_H_ */

==== //depot/projects/soc2007/fli-mdns_sd/mdnsd/stack_util.c#5 (text+ko) ====

@@ -37,6 +37,7 @@
 #include <strings.h>
 
 #include "mdns.h"
+#include "stack_mdns.h"
 #include "utf8.h"
 
 struct char2type {
@@ -270,7 +271,7 @@
 }
 
 /*
- * Resource data encoder to CNAME,TXT
+ * Resource data encoder to CNAME
  */
 static void *
 enc_in_string(void *data, int flags, size_t dlen, size_t *rlen)
@@ -297,6 +298,41 @@
 }
 
 /*
+ * Resource data encoder to TXT
+ */
+static void *
+enc_in_text(void *data, int flags, size_t dlen, size_t *rlen)
+{
+	char *r, *p, *q;
+	size_t len;
+
+	r = NULL;
+	if (flags & (MDNS_ENC_CHAR | MDNS_ENC_WCHAR)) {
+		p = data;
+		if (flags & MDNS_ENC_WCHAR) {
+			p = q = malloc(255);
+			len = wcstombs(q, data, 255);
+		}
+
+		len = dlen & 0xff;
+		r = malloc(len + 1);
+		*r = len;
+		memcpy(r+1, p, len);
+		if (flags & MDNS_ENC_CHAR)
+			free(q);
+		*rlen = len + 1;
+	}
+	else if (flags & MDNS_ENC_BINARY) {
+		len = dlen & 0xff;
+		r = malloc(len + 1);
+		*r = len;
+		memcpy(r+1, data, len);
+		*rlen = len + 1;
+	}
+	return (r);
+}
+
+/*
  * Table of recognized IN types for which a resource encoding
  * function exists.
  */
@@ -307,7 +343,7 @@
 #endif
 	{ .em_type = mdns_in_ptr, .em_encoder = enc_in_ptr },
 	{ .em_type = mdns_in_cname, .em_encoder = enc_in_string },
-	{ .em_type = mdns_in_txt, .em_encoder = enc_in_string }
+	{ .em_type = mdns_in_txt, .em_encoder = enc_in_text }
 };
 static int res_enc_table_size = sizeof(res_enc_table) / sizeof(struct encmap);
 
@@ -333,6 +369,7 @@
 {
 	char *p, *res = NULL;
 	size_t rlen;
+	int error;
 	char addr[MDNS_RECORD_LEN];
 
 	/*
@@ -364,12 +401,70 @@
 #endif
 	}
 
-	if (flags & MDNS_ENC_ADDR)
+	if (flags & MDNS_ENC_ADDR) {
 		res = enc_in_ptr(data, flags | MDNS_ENC_WCHAR, dlen, &rlen);
+	}
 	else {
 		res = malloc(MDNS_RECORD_LEN);
-		utf8_encode(data, res, MDNS_RECORD_LEN);
+		rlen = utf8_encode(data, res, MDNS_RECORD_LEN);
+		if ((ssize_t)rlen <= 0) {
+			free(res);
+			res = NULL;
+		}
+	}
+
+	if (res != NULL) {
+		error = mdns_name_validate(res, &rlen, MDNS_RECORD_LEN);
+		if (error < 0) {
+			free(res);
+			res = NULL;
+		}
 	}
 
 	return (res);
 }
+
+/*
+ * Validate a name and fix errors where possible.
+ */
+int
+mdns_name_validate(char *name, size_t *namlen, size_t buflen)
+{
+	char *p;
+	size_t len, llen;
+
+	/*
+	 * Length check, the maximum length on-wire is 255, which
+	 * in pratice results in maximum 254 real chars (incl. final dot).
+	 */
+	if (name[*namlen] != '.' && *namlen >= (MDNS_RECORD_LEN - 1))
+		return (-1);
+	else if (*namlen >= MDNS_RECORD_LEN)
+		return (-1);
+
+	len = *namlen;
+	llen = 0;
+	for (p = name; *p != '\0'; p++) {
+		if (*p == '.') {
+			/* Remove duplicate zero length labels */
+			if (llen == 0)
+				memmove(p - 1, p, --len);
+			llen = 0;
+		}
+		/* Validate label length */
+		else if (++llen > MDNS_PKG_LABEL_LEN)
+			return (-1);
+	}
+
+	/* Make sure name is dot-terminated */
+	if (*(p - 1) != '.') {
+		if (len >= buflen)
+			return (-1);
+		*p = '.';
+		*++p = '\0';
+		len++;
+	}
+
+	*namlen = len;
+	return (0);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200708101233.l7ACXX3H011512>