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>