00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef lint
00025 static const char rcsid[] = "$Id: ns_name.c,v 1.2 2009/10/28 04:12:29 sar Exp $";
00026 #endif
00027
00028 #include <sys/types.h>
00029
00030 #include <netinet/in.h>
00031 #include <sys/socket.h>
00032
00033 #include <errno.h>
00034 #include <string.h>
00035 #include <ctype.h>
00036
00037 #include "minires.h"
00038 #include "arpa/nameser.h"
00039
00040
00041
00042 static const char digits[] = "0123456789";
00043
00044
00045
00046 static int special(int);
00047 static int printable(int);
00048 static int dn_find(const u_char *, const u_char *,
00049 const u_char * const *,
00050 const u_char * const *);
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 int
00064 MRns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
00065 const u_char *cp;
00066 char *dn, *eom;
00067 u_char c;
00068 u_int n;
00069
00070 cp = src;
00071 dn = dst;
00072 eom = dst + dstsiz;
00073
00074 while ((n = *cp++) != 0) {
00075 if ((n & NS_CMPRSFLGS) != 0) {
00076
00077 errno = EMSGSIZE;
00078 return (-1);
00079 }
00080 if (dn != dst) {
00081 if (dn >= eom) {
00082 errno = EMSGSIZE;
00083 return (-1);
00084 }
00085 *dn++ = '.';
00086 }
00087 if (dn + n >= eom) {
00088 errno = EMSGSIZE;
00089 return (-1);
00090 }
00091 for ((void)NULL; n > 0; n--) {
00092 c = *cp++;
00093 if (special(c)) {
00094 if (dn + 1 >= eom) {
00095 errno = EMSGSIZE;
00096 return (-1);
00097 }
00098 *dn++ = '\\';
00099 *dn++ = (char)c;
00100 } else if (!printable(c)) {
00101 if (dn + 3 >= eom) {
00102 errno = EMSGSIZE;
00103 return (-1);
00104 }
00105 *dn++ = '\\';
00106 *dn++ = digits[c / 100];
00107 *dn++ = digits[(c % 100) / 10];
00108 *dn++ = digits[c % 10];
00109 } else {
00110 if (dn >= eom) {
00111 errno = EMSGSIZE;
00112 return (-1);
00113 }
00114 *dn++ = (char)c;
00115 }
00116 }
00117 }
00118 if (dn == dst) {
00119 if (dn >= eom) {
00120 errno = EMSGSIZE;
00121 return (-1);
00122 }
00123 *dn++ = '.';
00124 }
00125 if (dn >= eom) {
00126 errno = EMSGSIZE;
00127 return (-1);
00128 }
00129 *dn++ = '\0';
00130 return (dn - dst);
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 int
00145 MRns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
00146 u_char *label, *bp, *eom;
00147 int c, n, escaped;
00148 char *cp;
00149
00150 escaped = 0;
00151 bp = dst;
00152 eom = dst + dstsiz;
00153 label = bp++;
00154
00155 while ((c = *src++) != 0) {
00156 if (escaped) {
00157 if ((cp = strchr(digits, c)) != NULL) {
00158 n = (cp - digits) * 100;
00159 if ((c = *src++) == 0 ||
00160 (cp = strchr(digits, c)) == NULL) {
00161 errno = EMSGSIZE;
00162 return (-1);
00163 }
00164 n += (cp - digits) * 10;
00165 if ((c = *src++) == 0 ||
00166 (cp = strchr(digits, c)) == NULL) {
00167 errno = EMSGSIZE;
00168 return (-1);
00169 }
00170 n += (cp - digits);
00171 if (n > 255) {
00172 errno = EMSGSIZE;
00173 return (-1);
00174 }
00175 c = n;
00176 }
00177 escaped = 0;
00178 } else if (c == '\\') {
00179 escaped = 1;
00180 continue;
00181 } else if (c == '.') {
00182 c = (bp - label - 1);
00183 if ((c & NS_CMPRSFLGS) != 0) {
00184 errno = EMSGSIZE;
00185 return (-1);
00186 }
00187 if (label >= eom) {
00188 errno = EMSGSIZE;
00189 return (-1);
00190 }
00191 *label = c;
00192
00193 if (*src == '\0') {
00194 if (c != 0) {
00195 if (bp >= eom) {
00196 errno = EMSGSIZE;
00197 return (-1);
00198 }
00199 *bp++ = '\0';
00200 }
00201 if ((bp - dst) > MAXCDNAME) {
00202 errno = EMSGSIZE;
00203 return (-1);
00204 }
00205 return (1);
00206 }
00207 if (c == 0 || *src == '.') {
00208 errno = EMSGSIZE;
00209 return (-1);
00210 }
00211 label = bp++;
00212 continue;
00213 }
00214 if (bp >= eom) {
00215 errno = EMSGSIZE;
00216 return (-1);
00217 }
00218 *bp++ = (u_char)c;
00219 }
00220 c = (bp - label - 1);
00221 if ((c & NS_CMPRSFLGS) != 0) {
00222 errno = EMSGSIZE;
00223 return (-1);
00224 }
00225 if (label >= eom) {
00226 errno = EMSGSIZE;
00227 return (-1);
00228 }
00229 *label = c;
00230 if (c != 0) {
00231 if (bp >= eom) {
00232 errno = EMSGSIZE;
00233 return (-1);
00234 }
00235 *bp++ = 0;
00236 }
00237 if ((bp - dst) > MAXCDNAME) {
00238 errno = EMSGSIZE;
00239 return (-1);
00240 }
00241 return (0);
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 int
00254 MRns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) {
00255 const u_char *cp;
00256 u_char *dn, *eom;
00257 u_char c;
00258 u_int n;
00259
00260 cp = src;
00261 dn = dst;
00262 eom = dst + dstsiz;
00263
00264 if (dn >= eom) {
00265 errno = EMSGSIZE;
00266 return (-1);
00267 }
00268 while ((n = *cp++) != 0) {
00269 if ((n & NS_CMPRSFLGS) != 0) {
00270
00271 errno = EMSGSIZE;
00272 return (-1);
00273 }
00274 *dn++ = n;
00275 if (dn + n >= eom) {
00276 errno = EMSGSIZE;
00277 return (-1);
00278 }
00279 for ((void)NULL; n > 0; n--) {
00280 c = *cp++;
00281 if (isupper(c))
00282 *dn++ = tolower(c);
00283 else
00284 *dn++ = c;
00285 }
00286 }
00287 *dn++ = '\0';
00288 return (dn - dst);
00289 }
00290
00291
00292
00293
00294
00295
00296
00297 int
00298 MRns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
00299 u_char *dst, size_t dstsiz)
00300 {
00301 const u_char *srcp, *dstlim;
00302 u_char *dstp;
00303 unsigned n;
00304 int len;
00305 int checked;
00306
00307 len = -1;
00308 checked = 0;
00309 dstp = dst;
00310 srcp = src;
00311 dstlim = dst + dstsiz;
00312 if (srcp < msg || srcp >= eom) {
00313 errno = EMSGSIZE;
00314 return (-1);
00315 }
00316
00317 while ((n = *srcp++) != 0) {
00318
00319 switch (n & NS_CMPRSFLGS) {
00320 case 0:
00321
00322 if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
00323 errno = EMSGSIZE;
00324 return (-1);
00325 }
00326 checked += n + 1;
00327 *dstp++ = n;
00328 memcpy(dstp, srcp, n);
00329 dstp += n;
00330 srcp += n;
00331 break;
00332
00333 case NS_CMPRSFLGS:
00334 if (srcp >= eom) {
00335 errno = EMSGSIZE;
00336 return (-1);
00337 }
00338 if (len < 0)
00339 len = srcp - src + 1;
00340 srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
00341 if (srcp < msg || srcp >= eom) {
00342 errno = EMSGSIZE;
00343 return (-1);
00344 }
00345 checked += 2;
00346
00347
00348
00349
00350
00351 if (checked >= eom - msg) {
00352 errno = EMSGSIZE;
00353 return (-1);
00354 }
00355 break;
00356
00357 default:
00358 errno = EMSGSIZE;
00359 return (-1);
00360 }
00361 }
00362 *dstp = '\0';
00363 if (len < 0)
00364 len = srcp - src;
00365 return (len);
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 int
00386 MRns_name_pack(const u_char *src, u_char *dst, unsigned dstsiz,
00387 const u_char **dnptrs, const u_char **lastdnptr)
00388 {
00389 u_char *dstp;
00390 const u_char **cpp, **lpp, *eob, *msg;
00391 const u_char *srcp;
00392 unsigned n;
00393 int l;
00394
00395 srcp = src;
00396 dstp = dst;
00397 eob = dstp + dstsiz;
00398 lpp = cpp = NULL;
00399 if (dnptrs != NULL) {
00400 if ((msg = *dnptrs++) != NULL) {
00401 for (cpp = dnptrs; *cpp != NULL; cpp++)
00402 (void)NULL;
00403 lpp = cpp;
00404 }
00405 } else
00406 msg = NULL;
00407
00408
00409 l = 0;
00410 do {
00411 n = *srcp;
00412 if ((n & NS_CMPRSFLGS) != 0) {
00413 errno = EMSGSIZE;
00414 return (-1);
00415 }
00416 l += n + 1;
00417 if (l > MAXCDNAME) {
00418 errno = EMSGSIZE;
00419 return (-1);
00420 }
00421 srcp += n + 1;
00422 } while (n != 0);
00423
00424
00425 srcp = src;
00426 do {
00427
00428 n = *srcp;
00429 if (n != 0 && msg != NULL) {
00430 l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
00431 (const u_char * const *)lpp);
00432 if (l >= 0) {
00433 if (dstp + 1 >= eob) {
00434 goto cleanup;
00435 }
00436 *dstp++ = (l >> 8) | NS_CMPRSFLGS;
00437 *dstp++ = l % 256;
00438 return (dstp - dst);
00439 }
00440
00441 if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
00442 (dstp - msg) < 0x4000) {
00443 *cpp++ = dstp;
00444 *cpp = NULL;
00445 }
00446 }
00447
00448 if (n & NS_CMPRSFLGS) {
00449 goto cleanup;
00450 }
00451 if (dstp + 1 + n >= eob) {
00452 goto cleanup;
00453 }
00454 memcpy(dstp, srcp, n + 1);
00455 srcp += n + 1;
00456 dstp += n + 1;
00457 } while (n != 0);
00458
00459 if (dstp > eob) {
00460 cleanup:
00461 if (msg != NULL)
00462 *lpp = NULL;
00463 errno = EMSGSIZE;
00464 return (-1);
00465 }
00466 return (dstp - dst);
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 int
00478 MRns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
00479 char *dst, size_t dstsiz)
00480 {
00481 u_char tmp[NS_MAXCDNAME];
00482 int n;
00483
00484 if ((n = MRns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
00485 return (-1);
00486 if (MRns_name_ntop(tmp, dst, dstsiz) == -1)
00487 return (-1);
00488 return (n);
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 int
00506 MRns_name_compress(const char *src, u_char *dst, size_t dstsiz,
00507 const u_char **dnptrs, const u_char **lastdnptr)
00508 {
00509 u_char tmp[NS_MAXCDNAME];
00510
00511 if (MRns_name_pton(src, tmp, sizeof tmp) == -1)
00512 return (-1);
00513 return (MRns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
00514 }
00515
00516
00517
00518
00519
00520
00521
00522 int
00523 MRns_name_skip(const u_char **ptrptr, const u_char *eom) {
00524 const u_char *cp;
00525 u_int n;
00526
00527 cp = *ptrptr;
00528 while (cp < eom && (n = *cp++) != 0) {
00529
00530 switch (n & NS_CMPRSFLGS) {
00531 case 0:
00532 cp += n;
00533 continue;
00534 case NS_CMPRSFLGS:
00535 cp++;
00536 break;
00537 default:
00538 errno = EMSGSIZE;
00539 return (-1);
00540 }
00541 break;
00542 }
00543 if (cp > eom) {
00544 errno = EMSGSIZE;
00545 return (-1);
00546 }
00547 *ptrptr = cp;
00548 return (0);
00549 }
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 static int
00561 special(int ch) {
00562 switch (ch) {
00563 case 0x22:
00564 case 0x2E:
00565 case 0x3B:
00566 case 0x5C:
00567
00568 case 0x40:
00569 case 0x24:
00570 return (1);
00571 default:
00572 return (0);
00573 }
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583 static int
00584 printable(int ch) {
00585 return (ch > 0x20 && ch < 0x7f);
00586 }
00587
00588
00589
00590
00591
00592 static int
00593 mklower(int ch) {
00594 if (ch >= 0x41 && ch <= 0x5A)
00595 return (ch + 0x20);
00596 return (ch);
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 static int
00609 dn_find(const u_char *domain, const u_char *msg,
00610 const u_char * const *dnptrs,
00611 const u_char * const *lastdnptr)
00612 {
00613 const u_char *dn, *cp, *sp;
00614 const u_char * const *cpp;
00615 u_int n;
00616
00617 for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
00618 dn = domain;
00619 sp = cp = *cpp;
00620 while ((n = *cp++) != 0) {
00621
00622
00623
00624 switch (n & NS_CMPRSFLGS) {
00625 case 0:
00626 if (n != *dn++)
00627 goto next;
00628 for ((void)NULL; n > 0; n--)
00629 if (mklower(*dn++) != mklower(*cp++))
00630 goto next;
00631
00632 if (*dn == '\0' && *cp == '\0')
00633 return (sp - msg);
00634 if (*dn)
00635 continue;
00636 goto next;
00637
00638 case NS_CMPRSFLGS:
00639 cp = msg + (((n & 0x3f) << 8) | *cp);
00640 break;
00641
00642 default:
00643 errno = EMSGSIZE;
00644 return (-1);
00645 }
00646 }
00647 next: ;
00648 }
00649 errno = ENOENT;
00650 return (-1);
00651 }