是否有任何内置的C/C++库函数将域名编码为DHCP选项代码119域搜索列表



将域名编码到DHCP选项代码119域搜索列表的任何内置C/C++库函数

示例:我想转换";google.com";至";0x06'谷歌'0x03'com'0x00';

任何经过优化的程序样本也会有所帮助。

下面是一个示例实现:

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void compress(char **data, size_t *data_len, const char *domain) {
char *tmp = realloc(*data, *data_len + 1 + strlen(domain) + 1);
if(!tmp) {
printf("realloc failedn");
return;
}
*data = tmp;
size_t old_data_len = *data_len;
for(size_t j = 0;;) {
const char *sep = strchr(domain + j, '.');
size_t len = sep ? sep - domain - j : strlen(domain + j);
if(len > 255) {
printf("TBD: long labelsn");
return;
}
(*data)[*data_len] = len;
strncpy(*data + *data_len + 1, domain + j, len);
j += len + 1;
*data_len += 1 + len;
if(!sep) {
(*data)[(*data_len)++] = '';
break;
}
}
// Can we compress the string by using a pointer?
for(size_t j = old_data_len; j < *data_len; ) {
char *p = memmem(*data, old_data_len, *data + j, *data_len - j);
if(p) {
if(*data - p > 0x3f) {
printf("overflown");
return;
}
(*data)[j] = 0xc0 | (*data - p);
*data_len = j + 1;
char *tmp = realloc(*data, *data_len);
if(!tmp) {
printf("realloc failedn");
return;
}
*data = tmp;
break;
}
j += 1 + (*data)[j];
}
}

int main() {
char *data = NULL;
size_t data_len = 0;
compress(&data, &data_len, "example.com");
compress(&data, &data_len, "www.example.com");
write(STDOUT_FILENO, data, data_len);
free(data);
}

结果是:

$ ./a.out | od -c
0000000  a   e   x   a   m   p   l   e 003   c   o   m   003   w   w
0000020   w 300
0000022

您可以通过让调用者分配足够的内存(堆栈或堆(来优化这一点,然后在压缩完成时如果堆realloc。我还没有测量过,但通过反向查看每个连续的标签,可以更快地搜索指针。您可能需要一个size_t[],其中包含每个网络字符串的长度。这样做的好处是,只调用memmem()而不是3ish就不会返回匹配。

对于DHCP,您可以将数据拆分为option_length的块,并在每个块前面加上两个字节{119,option_length}。