Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/networking/udhcp/domain_codec.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/networking/udhcp/domain_codec.c
r1765 r2725 5 5 * Loosely based on the isc-dhcpd implementation by dhankins@isc.org 6 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 */ 9 10 #if ENABLE_FEATURE_RFC3397 11 12 #include "common.h" 13 #include "options.h" 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 */ 9 #ifdef DNS_COMPR_TESTING 10 # define FAST_FUNC /* nothing */ 11 # define xmalloc malloc 12 # include <stdlib.h> 13 # include <stdint.h> 14 # include <string.h> 15 # include <stdio.h> 16 #else 17 # include "common.h" 18 #endif 14 19 15 20 #define NS_MAXDNAME 1025 /* max domain name length */ … … 20 25 21 26 22 /* expand a RFC1035-compressed list of domain names "cstr", of length "clen";27 /* Expand a RFC1035-compressed list of domain names "cstr", of length "clen"; 23 28 * returns a newly allocated string containing the space-separated domains, 24 29 * prefixed with the contents of string pre, or NULL if an error occurs. 25 30 */ 26 char *dname_dec(const uint8_t *cstr, int clen, const char *pre) 27 { 28 const uint8_t *c; 29 int crtpos, retpos, depth, plen = 0, len = 0; 31 char* FAST_FUNC dname_dec(const uint8_t *cstr, int clen, const char *pre) 32 { 33 char *ret = ret; /* for compiler */ 30 34 char *dst = NULL; 31 32 if (!cstr)33 return NULL;34 35 if (pre)36 plen = strlen(pre);37 35 38 36 /* We make two passes over the cstr string. First, we compute … … 43 41 * buffer, then having to check if it's sufficiently large, etc. 44 42 */ 45 46 while (!dst) { 47 48 if (len > 0) { /* second pass? allocate dst buffer and copy pre */ 49 dst = xmalloc(len + plen); 50 memcpy(dst, pre, plen); 51 } 43 while (1) { 44 /* note: "return NULL" below are leak-safe since 45 * dst isn't yet allocated */ 46 const uint8_t *c; 47 unsigned crtpos, retpos, depth, len; 52 48 53 49 crtpos = retpos = depth = len = 0; 54 55 50 while (crtpos < clen) { 56 51 c = cstr + crtpos; 57 52 58 if ((*c & NS_CMPRSFLGS) != 0) { /* pointer */ 59 if (crtpos + 2 > clen) /* no offset to jump to? abort */ 53 if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) { 54 /* pointer */ 55 if (crtpos + 2 > clen) /* no offset to jump to? abort */ 60 56 return NULL; 61 if (retpos == 0) 57 if (retpos == 0) /* toplevel? save return spot */ 62 58 retpos = crtpos + 2; 63 59 depth++; 64 crtpos = ((*c & 0x3f) << 8) | (*(c + 1) & 0xff); /* jump */ 65 } else if (*c) { /* label */ 66 if (crtpos + *c + 1 > clen) /* label too long? abort */ 60 crtpos = ((c[0] & 0x3f) << 8) | c[1]; /* jump */ 61 } else if (*c) { 62 /* label */ 63 if (crtpos + *c + 1 > clen) /* label too long? abort */ 67 64 return NULL; 68 65 if (dst) 69 memcpy(dst + plen +len, c + 1, *c);66 memcpy(dst + len, c + 1, *c); 70 67 len += *c + 1; 71 68 crtpos += *c + 1; 72 69 if (dst) 73 *(dst + plen + len - 1) = '.'; 74 } else { /* null: end of current domain name */ 75 if (retpos == 0) { /* toplevel? keep going */ 70 dst[len - 1] = '.'; 71 } else { 72 /* NUL: end of current domain name */ 73 if (retpos == 0) { 74 /* toplevel? keep going */ 76 75 crtpos++; 77 } else { /* return to toplevel saved spot */ 76 } else { 77 /* return to toplevel saved spot */ 78 78 crtpos = retpos; 79 79 retpos = depth = 0; 80 80 } 81 81 if (dst) 82 *(dst + plen + len - 1) = ' '; 83 } 84 85 if (depth > NS_MAXDNSRCH || /* too many jumps? abort, it's a loop */ 86 len > NS_MAXDNAME * NS_MAXDNSRCH) /* result too long? abort */ 82 dst[len - 1] = ' '; 83 } 84 85 if (depth > NS_MAXDNSRCH /* too many jumps? abort, it's a loop */ 86 || len > NS_MAXDNAME * NS_MAXDNSRCH /* result too long? abort */ 87 ) { 87 88 return NULL; 88 } 89 90 if (!len) /* expanded string has 0 length? abort */ 89 } 90 } 91 92 if (!len) /* expanded string has 0 length? abort */ 91 93 return NULL; 92 94 93 if (dst) 94 *(dst + plen + len - 1) = '\0'; 95 } 96 97 return dst; 95 if (!dst) { /* first pass? */ 96 /* allocate dst buffer and copy pre */ 97 unsigned plen = strlen(pre); 98 ret = dst = xmalloc(plen + len); 99 memcpy(dst, pre, plen); 100 dst += plen; 101 } else { 102 dst[len - 1] = '\0'; 103 break; 104 } 105 } 106 107 return ret; 98 108 } 99 109 … … 104 114 static uint8_t *convert_dname(const char *src) 105 115 { 106 uint8_t c, *res, *l p, *rp;116 uint8_t c, *res, *lenptr, *dst; 107 117 int len; 108 118 109 119 res = xmalloc(strlen(src) + 2); 110 rp = lp= res;111 rp++;120 dst = lenptr = res; 121 dst++; 112 122 113 123 for (;;) { 114 124 c = (uint8_t)*src++; 115 if (c == '.' || c == '\0') { 116 len = rp - lp- 1;125 if (c == '.' || c == '\0') { /* end of label */ 126 len = dst - lenptr - 1; 117 127 /* label too long, too short, or two '.'s in a row? abort */ 118 128 if (len > NS_MAXLABEL || len == 0 || (c == '.' && *src == '.')) { … … 120 130 return NULL; 121 131 } 122 *lp = len; 123 lp = rp++; 124 if (c == '\0' || *src == '\0') /* end of dname */ 132 *lenptr = len; 133 if (c == '\0' || *src == '\0') /* "" or ".": end of src */ 125 134 break; 126 } else {127 if (c >= 0x41 && c <= 0x5A) /* uppercase? convert to lower */128 c += 0x20;129 *rp++ = c;130 }131 }132 133 *lp = 0; 134 if ( rp - res > NS_MAXCDNAME) {/* dname too long? abort */135 lenptr = dst++; 136 continue; 137 } 138 if (c >= 'A' && c <= 'Z') /* uppercase? convert to lower */ 139 c += ('a' - 'A'); 140 *dst++ = c; 141 } 142 143 if (dst - res >= NS_MAXCDNAME) { /* dname too long? abort */ 135 144 free(res); 136 145 return NULL; 137 146 } 147 148 *dst = 0; 138 149 return res; 139 150 } 140 151 141 /* returns the offset within cstr at which dname can be found, or -1 142 */ 152 /* Returns the offset within cstr at which dname can be found, or -1 */ 143 153 static int find_offset(const uint8_t *cstr, int clen, const uint8_t *dname) 144 154 { 145 155 const uint8_t *c, *d; 146 int off , inc;156 int off; 147 157 148 158 /* find all labels in cstr */ … … 151 161 c = cstr + off; 152 162 153 if ((*c & NS_CMPRSFLGS) != 0) {/* pointer, skip */163 if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) { /* pointer, skip */ 154 164 off += 2; 155 } else if (*c) { /* label, try matching dname */ 156 inc = *c + 1; 165 continue; 166 } 167 if (*c) { /* label, try matching dname */ 157 168 d = dname; 158 while (*c == *d && memcmp(c + 1, d + 1, *c) == 0) { 159 if (*c == 0) /* match, return offset */ 169 while (1) { 170 unsigned len1 = *c + 1; 171 if (memcmp(c, d, len1) != 0) 172 break; 173 if (len1 == 1) /* at terminating NUL - match, return offset */ 160 174 return off; 161 d += *c + 1; 162 c += *c + 1; 163 if ((*c & NS_CMPRSFLGS) != 0) /* pointer, jump */ 164 c = cstr + (((*c & 0x3f) << 8) | (*(c + 1) & 0xff)); 165 } 166 off += inc; 167 } else { /* null, skip */ 168 off++; 169 } 175 d += len1; 176 c += len1; 177 if ((*c & NS_CMPRSFLGS) == NS_CMPRSFLGS) /* pointer, jump */ 178 c = cstr + (((c[0] & 0x3f) << 8) | c[1]); 179 } 180 off += cstr[off] + 1; 181 continue; 182 } 183 /* NUL, skip */ 184 off++; 170 185 } 171 186 … … 173 188 } 174 189 175 /* computes string to be appended to cstr so that src would be added to190 /* Computes string to be appended to cstr so that src would be added to 176 191 * the compression (best case, it's a 2-byte pointer to some offset within 177 * cstr; worst case, it's all of src, converted to rfc3011format).192 * cstr; worst case, it's all of src, converted to <4>host<3>com<0> format). 178 193 * The computed string is returned directly; its length is returned via retlen; 179 194 * NULL and 0, respectively, are returned if an error occurs. 180 195 */ 181 uint8_t *dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen)196 uint8_t* FAST_FUNC dname_enc(const uint8_t *cstr, int clen, const char *src, int *retlen) 182 197 { 183 198 uint8_t *d, *dname; … … 190 205 } 191 206 192 for (d = dname; *d != 0; d += *d + 1) { 193 off = find_offset(cstr, clen, d); 194 if (off >= 0) { /* found a match, add pointer and terminate string */ 195 *d++ = NS_CMPRSFLGS; 196 *d = off; 197 break; 198 } 207 d = dname; 208 while (*d) { 209 if (cstr) { 210 off = find_offset(cstr, clen, d); 211 if (off >= 0) { /* found a match, add pointer and return */ 212 *d++ = NS_CMPRSFLGS | (off >> 8); 213 *d = off; 214 break; 215 } 216 } 217 d += *d + 1; 199 218 } 200 219 … … 203 222 } 204 223 205 #endif /* ENABLE_FEATURE_RFC3397 */ 224 #ifdef DNS_COMPR_TESTING 225 /* gcc -Wall -DDNS_COMPR_TESTING domain_codec.c -o domain_codec && ./domain_codec */ 226 int main(int argc, char **argv) 227 { 228 int len; 229 uint8_t *encoded; 230 231 #define DNAME_DEC(encoded,pre) dname_dec((uint8_t*)(encoded), sizeof(encoded), (pre)) 232 printf("'%s'\n", DNAME_DEC("\4host\3com\0", "test1:")); 233 printf("test2:'%s'\n", DNAME_DEC("\4host\3com\0\4host\3com\0", "")); 234 printf("test3:'%s'\n", DNAME_DEC("\4host\3com\0\xC0\0", "")); 235 printf("test4:'%s'\n", DNAME_DEC("\4host\3com\0\xC0\5", "")); 236 printf("test5:'%s'\n", DNAME_DEC("\4host\3com\0\xC0\5\1z\xC0\xA", "")); 237 238 #define DNAME_ENC(cache,source,lenp) dname_enc((uint8_t*)(cache), sizeof(cache), (source), (lenp)) 239 encoded = dname_enc(NULL, 0, "test.net", &len); 240 printf("test6:'%s' len:%d\n", dname_dec(encoded, len, ""), len); 241 encoded = DNAME_ENC("\3net\0", "test.net", &len); 242 printf("test7:'%s' len:%d\n", dname_dec(encoded, len, ""), len); 243 encoded = DNAME_ENC("\4test\3net\0", "test.net", &len); 244 printf("test8:'%s' len:%d\n", dname_dec(encoded, len, ""), len); 245 return 0; 246 } 247 #endif
Note:
See TracChangeset
for help on using the changeset viewer.