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