OLD | NEW |
(Empty) | |
| 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 */ |
| 8 static 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 */ |
| 24 static 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 */ |
| 37 static 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 |
| 58 int __dn_comp(const char *src, unsigned char *dst, int space, unsigned char **dn
ptrs, 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 |
| 110 weak_alias(__dn_comp, dn_comp); |
OLD | NEW |