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