From owner-p4-projects@FreeBSD.ORG Fri Aug 10 12:33:34 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 66D6A16A41B; Fri, 10 Aug 2007 12:33:34 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 113B316A418 for ; Fri, 10 Aug 2007 12:33:34 +0000 (UTC) (envelope-from fli@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 00F8313C459 for ; Fri, 10 Aug 2007 12:33:34 +0000 (UTC) (envelope-from fli@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id l7ACXXsH011516 for ; Fri, 10 Aug 2007 12:33:33 GMT (envelope-from fli@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id l7ACXX3H011512 for perforce@freebsd.org; Fri, 10 Aug 2007 12:33:33 GMT (envelope-from fli@FreeBSD.org) Date: Fri, 10 Aug 2007 12:33:33 GMT Message-Id: <200708101233.l7ACXX3H011512@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to fli@FreeBSD.org using -f From: Fredrik Lindberg To: Perforce Change Reviews Cc: Subject: PERFORCE change 125012 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Aug 2007 12:33:34 -0000 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 #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); +}