2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-08-31 06:15:55 +00:00

[master] Fixed concatenation of "Dc" formatted options such as domain-search

Merges in rt20558.
This commit is contained in:
Thomas Markwalder
2014-11-25 15:21:39 -05:00
parent f3a44c1037
commit 04daf4fe4b
8 changed files with 414 additions and 1 deletions

View File

@@ -645,3 +645,145 @@ dn_find(const u_char *domain, const u_char *msg,
errno = ENOENT;
return (-1);
}
/*!
* \brief Creates a string of comma-separated domain-names from a
* compressed list
*
* Produces a null-terminated string of comma-separated domain-names from
* a buffer containing a compressed list of domain-names. The names will
* be dotted and without enclosing quotes. For example:
* If a compressed list contains the follwoing two domain names:
*
* a. one.two.com
* b. three.four.com
*
* The compressed data will look like this:
*
* 03 6f 6e 65 03 74 77 6f 03 63 6f 6d 00 05 74 68
* 72 65 65 04 66 6f 75 72 c0 08
*
* and will decompress into:
*
* one.two.com,three.four.com
*
* \param buf - buffer containing the compressed list of domain-names
* \param buflen - length of compressed list of domain-names
* \param dst_buf - buffer to receive the decompressed list
* \param dst_size - size of the destination buffer
*
* \return the length of the decompressed string when successful, -1 on
* error.
*/
int MRns_name_uncompress_list(const unsigned char* buf, int buflen,
char* dst_buf, size_t dst_size)
{
const unsigned char* src = buf;
char* dst = dst_buf;
int consumed = 1;
int dst_remaining = dst_size;
int added_len = 0;
int first_pass = 1;
if (!buf || buflen == 0 || *buf == 0x00) {
/* nothing to do */
*dst = 0;
return (0);
}
while ((consumed > 0) && (src < (buf + buflen)))
{
if (dst_remaining <= 0) {
errno = EMSGSIZE;
return (-1);
}
if (!first_pass) {
*dst++ = ',';
*dst = '\0';
dst_remaining--;
}
consumed = MRns_name_uncompress(buf, buf + buflen, src,
dst, dst_remaining);
if (consumed < 0) {
return (-1);
}
src += consumed;
added_len = strlen(dst);
dst_remaining -= added_len;
dst += added_len;
first_pass = 0;
}
*dst='\0';
/* return the length of the uncompressed list string */
return (strlen(dst_buf));
}
/*!
* \brief Creates a compressed list from a string of comma-separated
* domain-names
*
* Produces a buffer containing a compressed data version of a list of
* domain-names extracted from a comma-separated string. Given a string
* containing:
*
* one.two.com,three.four.com
*
* It will compress this into:
*
* 03 6f 6e 65 03 74 77 6f 03 63 6f 6d 00 05 74 68
* 72 65 65 04 66 6f 75 72 c0 08
*
* \param buf - buffer containing the uncompressed string of domain-names
* \param buflen - length of uncompressed string of domain-names
* \param compbuf - buffer to receive the compressed list
* \param compbuf_size - size of the compression buffer
*
* \return the length of the compressed data when successful, -1 on error.
*/
int MRns_name_compress_list(const char* buf, int buflen,
unsigned char* compbuf, size_t compbuf_size)
{
char cur_name[NS_MAXCDNAME];
const unsigned char *dnptrs[256], **lastdnptr;
const char* src;
const char* src_end;
unsigned clen = 0;
int result = 0;
memset(compbuf, 0, compbuf_size);
memset(dnptrs, 0, sizeof(dnptrs));
dnptrs[0] = compbuf;
lastdnptr = &dnptrs[255];
src = buf;
src_end = buf + buflen;
while (src < src_end) {
char *comma = strchr(src, ',');
int copylen = ((comma != NULL) ? comma - src : strlen(src));
if (copylen > (sizeof(cur_name) - 1)) {
errno = EMSGSIZE;
return (-1);
}
memcpy(cur_name, src, copylen);
cur_name[copylen] = '\0';
src += copylen + 1;
result = MRns_name_compress(cur_name, compbuf + clen,
compbuf_size - clen,
dnptrs, lastdnptr);
if (result < 0) {
return (-1);
}
clen += result;
}
/* return size of compressed list */
return(clen);
}