1#include "libc.h" 2#include <resolv.h> 3#include <string.h> 4 5/* RFC 1035 message compression */ 6 7/* label start offsets of a compressed domain name s */ 8static int getoffs(short* offs, const unsigned char* base, const unsigned char* s) { 9 int i = 0; 10 for (;;) { 11 while (*s & 0xc0) { 12 if ((*s & 0xc0) != 0xc0) 13 return 0; 14 s = base + ((s[0] & 0x3f) << 8 | s[1]); 15 } 16 if (!*s) 17 return i; 18 if (s - base >= 0x4000) 19 return 0; 20 offs[i++] = s - base; 21 s += *s + 1; 22 } 23} 24 25/* label lengths of an ascii domain name s */ 26static int getlens(unsigned char* lens, const char* s, int l) { 27 int i = 0, j = 0, k = 0; 28 for (;;) { 29 for (; j < l && s[j] != '.'; j++) 30 ; 31 if (j - k - 1u > 62) 32 return 0; 33 lens[i++] = j - k; 34 if (j == l) 35 return i; 36 k = ++j; 37 } 38} 39 40/* longest suffix match of an ascii domain with a compressed domain name dn */ 41static int match(int* offset, const unsigned char* base, const unsigned char* dn, const char* end, 42 const unsigned char* lens, int nlen) { 43 int l, o, m = 0; 44 short offs[128]; 45 int noff = getoffs(offs, base, dn); 46 if (!noff) 47 return 0; 48 for (;;) { 49 l = lens[--nlen]; 50 o = offs[--noff]; 51 end -= l; 52 if (l != base[o] || memcmp(base + o + 1, end, l)) 53 return m; 54 *offset = o; 55 m += l; 56 if (nlen) 57 m++; 58 if (!nlen || !noff) 59 return m; 60 end--; 61 } 62} 63 64int __dn_comp(const char* src, unsigned char* dst, int space, unsigned char** dnptrs, 65 unsigned char** lastdnptr) { 66 int i, j, n, m = 0, offset = 0, bestlen = 0, bestoff = 0; 67 unsigned char lens[127]; 68 unsigned char** p; 69 const char* end; 70 size_t l = strnlen(src, 255); 71 if (l && src[l - 1] == '.') 72 l--; 73 if (l > 253 || space <= 0) 74 return -1; 75 if (!l) { 76 *dst = 0; 77 return 1; 78 } 79 end = src + l; 80 n = getlens(lens, src, l); 81 if (!n) 82 return -1; 83 84 p = dnptrs; 85 if (p && *p) 86 for (p++; *p; p++) { 87 m = match(&offset, *dnptrs, *p, end, lens, n); 88 if (m > bestlen) { 89 bestlen = m; 90 bestoff = offset; 91 if (m == l) 92 break; 93 } 94 } 95 96 /* encode unmatched part */ 97 if (space < l - bestlen + 2 + (bestlen - 1 < l - 1)) 98 return -1; 99 memcpy(dst + 1, src, l - bestlen); 100 for (i = j = 0; i < l - bestlen; i += lens[j++] + 1) 101 dst[i] = lens[j]; 102 103 /* add tail */ 104 if (bestlen) { 105 dst[i++] = 0xc0 | bestoff >> 8; 106 dst[i++] = bestoff; 107 } else 108 dst[i++] = 0; 109 110 /* save dst pointer */ 111 if (i > 2 && lastdnptr && dnptrs && *dnptrs) { 112 while (*p) 113 p++; 114 if (p + 1 < lastdnptr) { 115 *p++ = dst; 116 *p = 0; 117 } 118 } 119 return i; 120} 121 122weak_alias(__dn_comp, dn_comp); 123