/*
* Copyright (c) 1985 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#ifndef lint
-static char sccsid[] = "@(#)res_comp.c 5.1 (Berkeley) %G%";
-#endif not lint
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)res_comp.c 6.16 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <stdio.h>
-#include <ctype.h>
-#include <nameser.h>
+#include <arpa/nameser.h>
+
+static dn_find();
/*
* Expand compressed domain name 'comp_dn' to full domain name.
- * Expanded names are converted to upper case.
* 'msg' is a pointer to the begining of the message,
+ * 'eomorig' points to the first location after the message,
* 'exp_dn' is a pointer to a buffer of size 'length' for the result.
* Return size of compressed name or -1 if there was an error.
*/
-dn_expand(msg, comp_dn, exp_dn, length)
- char *msg, *comp_dn, *exp_dn;
+dn_expand(msg, eomorig, comp_dn, exp_dn, length)
+ u_char *msg, *eomorig, *comp_dn, *exp_dn;
int length;
{
- register char *cp, *dn;
+ register u_char *cp, *dn;
register int n, c;
- char *eom;
- int len = -1;
+ u_char *eom;
+ int len = -1, checked = 0;
dn = exp_dn;
cp = comp_dn;
- eom = exp_dn + length - 1;
+ eom = exp_dn + length;
/*
* fetch next label in domain name
*/
}
if (dn+n >= eom)
return (-1);
- while (--n >= 0)
- if (islower(c = *cp++))
- *dn++ = toupper(c);
- else {
- if (c == '.') {
- if (dn+n+1 >= eom)
- return (-1);
- *dn++ = '\\';
- }
- *dn++ = c;
+ checked += n + 1;
+ while (--n >= 0) {
+ if ((c = *cp++) == '.') {
+ if (dn+n+1 >= eom)
+ return (-1);
+ *dn++ = '\\';
}
+ *dn++ = c;
+ if (cp >= eomorig) /* out of range */
+ return(-1);
+ }
break;
case INDIR_MASK:
if (len < 0)
len = cp - comp_dn + 1;
cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
+ if (cp < msg || cp >= eomorig) /* out of range */
+ return(-1);
+ checked += 2;
+ /*
+ * Check for loops in the compressed name;
+ * if we've looked at the whole message,
+ * there must be a loop.
+ */
+ if (checked >= eomorig - msg)
+ return (-1);
break;
default:
* is NULL, we don't update the list.
*/
dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
- char *exp_dn, *comp_dn;
+ u_char *exp_dn, *comp_dn;
int length;
- char **dnptrs, **lastdnptr;
+ u_char **dnptrs, **lastdnptr;
{
- register char *cp, *dn;
+ register u_char *cp, *dn;
register int c, l;
- char **cpp, **lpp, *sp, *eob;
- char *msg;
+ u_char **cpp, **lpp, *sp, *eob;
+ u_char *msg;
dn = exp_dn;
cp = comp_dn;
- eob = comp_dn + length;
+ eob = cp + length;
if (dnptrs != NULL) {
if ((msg = *dnptrs++) != NULL) {
for (cpp = dnptrs; *cpp != NULL; cpp++)
if (cp+1 >= eob)
return (-1);
*cp++ = (l >> 8) | INDIR_MASK;
- *cp++ = l;
+ *cp++ = l % 256;
return (cp - comp_dn);
}
/* not found, save it */
if ((c = *dn++) == '\0')
break;
}
- if (cp >= eob)
+ if (cp >= eob) {
+ if (msg != NULL)
+ *lpp = NULL;
return (-1);
+ }
*cp++ = c;
} while ((c = *dn++) != '\0');
/* catch trailing '.'s but not '..' */
cp--;
break;
}
- if (l <= 0 || l > MAXLABEL)
+ if (l <= 0 || l > MAXLABEL) {
+ if (msg != NULL)
+ *lpp = NULL;
return (-1);
+ }
*sp = l;
}
- if (cp >= eob)
+ if (cp >= eob) {
+ if (msg != NULL)
+ *lpp = NULL;
return (-1);
+ }
*cp++ = '\0';
return (cp - comp_dn);
}
/*
* Skip over a compressed domain name. Return the size or -1.
*/
-dn_skip(comp_dn)
- char *comp_dn;
+dn_skipname(comp_dn, eom)
+ u_char *comp_dn, *eom;
{
- register char *cp;
+ register u_char *cp;
register int n;
cp = comp_dn;
- while (n = *cp++) {
+ while (cp < eom && (n = *cp++)) {
/*
* check for indirection
*/
/*
* Search for expanded name from a list of previously compressed names.
* Return the offset from msg if found or -1.
+ * dnptrs is the pointer to the first name on the list,
+ * not the pointer to the start of the message.
*/
+static
dn_find(exp_dn, msg, dnptrs, lastdnptr)
- char *exp_dn, *msg;
- char **dnptrs, **lastdnptr;
+ u_char *exp_dn, *msg;
+ u_char **dnptrs, **lastdnptr;
{
- register char *dn, *cp, **cpp;
+ register u_char *dn, *cp, **cpp;
register int n;
- char *sp;
+ u_char *sp;
for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
dn = exp_dn;
switch (n & INDIR_MASK) {
case 0: /* normal case, n == len */
while (--n >= 0) {
+ if (*dn == '.')
+ goto next;
if (*dn == '\\')
dn++;
if (*dn++ != *cp++)
return (-1);
case INDIR_MASK: /* indirection */
- cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
+ cp = msg + (((n & 0x3f) << 8) | *cp);
}
}
if (*dn == '\0')
* Routines to insert/extract short/long's. Must account for byte
* order and non-alignment problems. This code at least has the
* advantage of being portable.
+ *
+ * used by sendmail.
*/
u_short
-getshort(msgp)
- char *msgp;
+_getshort(msgp)
+ u_char *msgp;
{
register u_char *p = (u_char *) msgp;
+#ifdef vax
+ /*
+ * vax compiler doesn't put shorts in registers
+ */
+ register u_long u;
+#else
+ register u_short u;
+#endif
- return ((*p++ << 8) | *p);
+ u = *p++ << 8;
+ return ((u_short)(u | *p));
}
u_long
-getlong(msgp)
- char *msgp;
+_getlong(msgp)
+ u_char *msgp;
{
register u_char *p = (u_char *) msgp;
+ register u_long u;
- return ((((((*p++ << 8) | *p++) << 8) | *p++) << 8) | *p);
+ u = *p++; u <<= 8;
+ u |= *p++; u <<= 8;
+ u |= *p++; u <<= 8;
+ return (u | *p);
}
-u_short
+
putshort(s, msgp)
register u_short s;
- register char *msgp;
+ register u_char *msgp;
{
msgp[1] = s;
msgp[0] = s >> 8;
}
-u_long
putlong(l, msgp)
register u_long l;
- register char *msgp;
+ register u_char *msgp;
{
msgp[3] = l;