res_comp.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:8k
开发平台:

MultiPlatform

  1. /* res_comp.c - expands and compresses domain names in a messge  */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1985 Regents of the University of California.
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  * This product includes software developed by the University of
  19.  * California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36. /*
  37. modification history
  38. --------------------
  39. 01b,17sep01,vvv  fixed compilation warnings
  40. 01a,13dec96,jag  Cleaned up and rename functions with the resolv prefix.  The
  41.                  man pages for these functions appear in resolvLib
  42. */
  43. #include <resolvLib.h>
  44. #include <stdio.h>
  45. static int dn_find();
  46. /*
  47.  * Expand compressed domain name 'comp_dn' to full domain name.
  48.  * 'msg' is a pointer to the begining of the message,
  49.  * 'eomorig' points to the first location after the message,
  50.  * 'exp_dn' is a pointer to a buffer of size 'length' for the result.
  51.  * Return size of compressed name or -1 if there was an error.
  52.  */
  53. int 
  54. resolvDNExpand(msg, eomorig, comp_dn, exp_dn, length)
  55. const u_char *msg, *eomorig, *comp_dn;
  56. u_char *exp_dn;
  57. int length;
  58. {
  59. register u_char *cp, *dn;
  60. register int n, c;
  61. u_char *eom;
  62. int len = -1, checked = 0;
  63. dn = exp_dn;
  64. cp = (u_char *)comp_dn;
  65. eom = exp_dn + length;
  66. /*
  67.  * fetch next label in domain name
  68.  */
  69. while ((n = *cp++)) {
  70. /*
  71.  * Check for indirection
  72.  */
  73. switch (n & INDIR_MASK) {
  74. case 0:
  75. if (dn != exp_dn) {
  76. if (dn >= eom)
  77. return (-1);
  78. *dn++ = '.';
  79. }
  80. if (dn+n >= eom)
  81. return (-1);
  82. checked += n + 1;
  83. while (--n >= 0) {
  84. if ((c = *cp++) == '.') {
  85. if (dn + n + 2 >= eom)
  86. return (-1);
  87. *dn++ = '\';
  88. }
  89. *dn++ = c;
  90. if (cp >= eomorig) /* out of range */
  91. return(-1);
  92. }
  93. break;
  94. case INDIR_MASK:
  95. if (len < 0)
  96. len = cp - comp_dn + 1;
  97. cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff));
  98. if (cp < msg || cp >= eomorig) /* out of range */
  99. return(-1);
  100. checked += 2;
  101. /*
  102.  * Check for loops in the compressed name;
  103.  * if we've looked at the whole message,
  104.  * there must be a loop.
  105.  */
  106. if (checked >= eomorig - msg)
  107. return (-1);
  108. break;
  109. default:
  110. return (-1); /* flag error */
  111. }
  112. }
  113. *dn = '';
  114. if (len < 0)
  115. len = cp - comp_dn;
  116. return (len);
  117. }
  118. /*
  119.  * Compress domain name 'exp_dn' into 'comp_dn'.
  120.  * Return the size of the compressed name or -1.
  121.  * 'length' is the size of the array pointed to by 'comp_dn'.
  122.  * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
  123.  * is a pointer to the beginning of the message. The list ends with NULL.
  124.  * 'lastdnptr' is a pointer to the end of the arrary pointed to
  125.  * by 'dnptrs'. Side effect is to update the list of pointers for
  126.  * labels inserted into the message as we compress the name.
  127.  * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
  128.  * is NULL, we don't update the list.
  129.  */
  130. int resolvDNComp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
  131. const u_char *exp_dn;
  132. u_char *comp_dn;
  133.         int length;
  134.         u_char **dnptrs, **lastdnptr;
  135. {
  136. register u_char *cp, *dn;
  137. register int c, l;
  138. u_char **cpp = NULL, **lpp = NULL, *sp, *eob;
  139. u_char *msg;
  140. dn = (u_char *)exp_dn;
  141. cp = comp_dn;
  142. eob = cp + length;
  143. if (dnptrs != NULL) {
  144. if ((msg = *dnptrs++) != NULL) {
  145. for (cpp = dnptrs; *cpp != NULL; cpp++)
  146. ;
  147. lpp = cpp; /* end of list to search */
  148. }
  149. } else
  150. msg = NULL;
  151. for (c = *dn++; c != ''; ) {
  152. /* look to see if we can use pointers */
  153. if (msg != NULL) {
  154. if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
  155. if (cp+1 >= eob)
  156. return (-1);
  157. *cp++ = (l >> 8) | INDIR_MASK;
  158. *cp++ = l % 256;
  159. return (cp - comp_dn);
  160. }
  161. /* not found, save it */
  162. if (lastdnptr != NULL && cpp < lastdnptr-1) {
  163. *cpp++ = cp;
  164. *cpp = NULL;
  165. }
  166. }
  167. sp = cp++; /* save ptr to length byte */
  168. do {
  169. if (c == '.') {
  170. c = *dn++;
  171. break;
  172. }
  173. if (c == '\') {
  174. if ((c = *dn++) == '')
  175. break;
  176. }
  177. if (cp >= eob) {
  178. if (msg != NULL)
  179. *lpp = NULL;
  180. return (-1);
  181. }
  182. *cp++ = c;
  183. } while ((c = *dn++) != '');
  184. /* catch trailing '.'s but not '..' */
  185. if ((l = cp - sp - 1) == 0 && c == '') {
  186. cp--;
  187. break;
  188. }
  189. if (l <= 0 || l > MAXLABEL) {
  190. if (msg != NULL)
  191. *lpp = NULL;
  192. return (-1);
  193. }
  194. *sp = l;
  195. }
  196. if (cp >= eob) {
  197. if (msg != NULL)
  198. *lpp = NULL;
  199. return (-1);
  200. }
  201. *cp++ = '';
  202. return (cp - comp_dn);
  203. }
  204. /*
  205.  * Skip over a compressed domain name. Return the size or -1.
  206.  */
  207. int __dn_skipname(comp_dn, eom)
  208. const u_char *comp_dn, *eom;
  209. {
  210. register u_char *cp;
  211. register int n;
  212. cp = (u_char *)comp_dn;
  213. while (cp < eom && (n = *cp++)) {
  214. /*
  215.  * check for indirection
  216.  */
  217. switch (n & INDIR_MASK) {
  218. case 0: /* normal case, n == len */
  219. cp += n;
  220. continue;
  221. case INDIR_MASK: /* indirection */
  222. cp++;
  223. break;
  224. default: /* illegal type */
  225. return (-1);
  226. }
  227. break;
  228. }
  229. if (cp > eom)
  230. return -1;
  231. return (cp - comp_dn);
  232. }
  233. /*
  234.  * Search for expanded name from a list of previously compressed names.
  235.  * Return the offset from msg if found or -1.
  236.  * dnptrs is the pointer to the first name on the list,
  237.  * not the pointer to the start of the message.
  238.  */
  239. static int
  240. dn_find(exp_dn, msg, dnptrs, lastdnptr)
  241. u_char *exp_dn, *msg;
  242. u_char **dnptrs, **lastdnptr;
  243. {
  244. register u_char *dn, *cp, **cpp;
  245. register int n;
  246. u_char *sp;
  247. for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
  248. dn = exp_dn;
  249. sp = cp = *cpp;
  250. while ((n = *cp++)) {
  251. /*
  252.  * check for indirection
  253.  */
  254. switch (n & INDIR_MASK) {
  255. case 0: /* normal case, n == len */
  256. while (--n >= 0) {
  257. if (*dn == '.')
  258. goto next;
  259. if (*dn == '\')
  260. dn++;
  261. if (*dn++ != *cp++)
  262. goto next;
  263. }
  264. if ((n = *dn++) == '' && *cp == '')
  265. return (sp - msg);
  266. if (n == '.')
  267. continue;
  268. goto next;
  269. default: /* illegal type */
  270. return (-1);
  271. case INDIR_MASK: /* indirection */
  272. cp = msg + (((n & 0x3f) << 8) | *cp);
  273. }
  274. }
  275. if (*dn == '')
  276. return (sp - msg);
  277. next: ;
  278. }
  279. return (-1);
  280. }
  281. /*
  282.  * Routines to insert/extract short/long's. Must account for byte
  283.  * order and non-alignment problems. This code at least has the
  284.  * advantage of being portable.
  285.  *
  286.  * used by sendmail.
  287.  */
  288. u_short
  289. _getshort(msgp)
  290. register u_char *msgp;
  291. {
  292. register u_short u;
  293. GETSHORT(u, msgp);
  294. return (u);
  295. }
  296. uint32_t
  297. _getlong(msgp)
  298. u_char *msgp;
  299. {
  300. register uint32_t u;
  301. GETLONG(u, msgp);
  302. return (u);
  303. }
  304. void
  305. #ifdef __STDC__
  306. __putshort(register uint16_t s, register u_char *msgp)
  307. #else
  308. __putshort(s, msgp)
  309. register uint16_t s;
  310. register u_char *msgp;
  311. #endif
  312. {
  313. PUTSHORT(s, msgp);
  314. }
  315. void
  316. __putlong(l, msgp)
  317. register uint32_t l;
  318. register u_char *msgp;
  319. {
  320. PUTLONG(l, msgp);
  321. }