1*18140Sralph #ifndef lint 2*18140Sralph static char sccsid[] = "@(#)res_comp.c 4.1 (Berkeley) 03/01/85"; 3*18140Sralph #endif 4*18140Sralph 5*18140Sralph #include <sys/types.h> 6*18140Sralph #include <stdio.h> 7*18140Sralph #include <ctype.h> 8*18140Sralph #include <nameser.h> 9*18140Sralph 10*18140Sralph 11*18140Sralph /* 12*18140Sralph * Expand compressed domain name format to full domain name. 13*18140Sralph * Return size of compressed name or -1 if there was an error. 14*18140Sralph */ 15*18140Sralph dn_expand(msg, comp_dn, exp_dn, length) 16*18140Sralph char *msg, *comp_dn, *exp_dn; 17*18140Sralph int length; 18*18140Sralph { 19*18140Sralph register char *cp, *dn; 20*18140Sralph register int n, c; 21*18140Sralph char *eom; 22*18140Sralph int len = 0; 23*18140Sralph 24*18140Sralph dn = exp_dn; 25*18140Sralph cp = comp_dn; 26*18140Sralph eom = exp_dn + length - 1; 27*18140Sralph /* 28*18140Sralph * fetch next label in domain name 29*18140Sralph */ 30*18140Sralph while (n = *cp++) { 31*18140Sralph /* 32*18140Sralph * Check for indirection 33*18140Sralph */ 34*18140Sralph switch (n & INDIR_MASK) { 35*18140Sralph case 0: 36*18140Sralph if (dn != exp_dn) 37*18140Sralph *dn++ = '.'; 38*18140Sralph if (dn+n >= eom) 39*18140Sralph return (-1); 40*18140Sralph while (--n >= 0) 41*18140Sralph if (islower(c = *cp++)) 42*18140Sralph *dn++ = toupper(c); 43*18140Sralph else 44*18140Sralph *dn++ = c; 45*18140Sralph break; 46*18140Sralph 47*18140Sralph case INDIR_MASK: 48*18140Sralph if (len == 0) 49*18140Sralph len = cp - comp_dn + 1; 50*18140Sralph cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff)); 51*18140Sralph break; 52*18140Sralph 53*18140Sralph default: 54*18140Sralph return (-1); /* flag error */ 55*18140Sralph } 56*18140Sralph } 57*18140Sralph *dn = '\0'; 58*18140Sralph if (len == 0) 59*18140Sralph len = cp - comp_dn; 60*18140Sralph return (len); 61*18140Sralph } 62*18140Sralph 63*18140Sralph /* 64*18140Sralph * Compress domain name. Return the size of the compressed name or -1. 65*18140Sralph * Dnptrs is a list of pointers to previous compressed names. dnptrs[0] 66*18140Sralph * is a pointer to the beginning of the message. The list ends with NULL. 67*18140Sralph */ 68*18140Sralph dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) 69*18140Sralph char *exp_dn, *comp_dn; 70*18140Sralph int length; 71*18140Sralph char **dnptrs, **lastdnptr; 72*18140Sralph { 73*18140Sralph register char *cp, *dn; 74*18140Sralph register int c, l; 75*18140Sralph char **cpp, **lpp, *sp, *eob; 76*18140Sralph char *msg; 77*18140Sralph 78*18140Sralph dn = exp_dn; 79*18140Sralph cp = comp_dn; 80*18140Sralph eob = comp_dn + length; 81*18140Sralph if (dnptrs != NULL) { 82*18140Sralph if ((msg = *dnptrs++) != NULL) { 83*18140Sralph for (cpp = dnptrs; *cpp != NULL; cpp++) 84*18140Sralph ; 85*18140Sralph lpp = cpp; /* end of list to search */ 86*18140Sralph } 87*18140Sralph } else 88*18140Sralph msg = NULL; 89*18140Sralph for (c = *dn++; c != '\0'; ) { 90*18140Sralph /* look to see if we can use pointers */ 91*18140Sralph if (msg != NULL) { 92*18140Sralph if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) { 93*18140Sralph if (cp+1 >= eob) 94*18140Sralph return (-1); 95*18140Sralph *cp++ = (l >> 8) | INDIR_MASK; 96*18140Sralph *cp++ = l; 97*18140Sralph return (cp - comp_dn); 98*18140Sralph } 99*18140Sralph /* not found, save it */ 100*18140Sralph if (lastdnptr != NULL && cpp < lastdnptr-1) { 101*18140Sralph *cpp++ = cp; 102*18140Sralph *cpp = NULL; 103*18140Sralph } 104*18140Sralph } 105*18140Sralph sp = cp++; /* save ptr to length byte */ 106*18140Sralph do { 107*18140Sralph if (c == '.') { 108*18140Sralph c = *dn++; 109*18140Sralph break; 110*18140Sralph } 111*18140Sralph if (cp >= eob) 112*18140Sralph return (-1); 113*18140Sralph *cp++ = c; 114*18140Sralph } while ((c = *dn++) != '\0'); 115*18140Sralph if ((l = cp - sp - 1) <= 0 || l > MAXLABEL) 116*18140Sralph return (-1); 117*18140Sralph *sp = l; 118*18140Sralph } 119*18140Sralph if (cp >= eob) 120*18140Sralph return (-1); 121*18140Sralph *cp++ = '\0'; 122*18140Sralph return (cp - comp_dn); 123*18140Sralph } 124*18140Sralph 125*18140Sralph /* 126*18140Sralph * Skip over a compressed domain name. Return the size. 127*18140Sralph */ 128*18140Sralph dn_skip(buf) 129*18140Sralph char *buf; 130*18140Sralph { 131*18140Sralph register char *cp; 132*18140Sralph register int n; 133*18140Sralph 134*18140Sralph cp = buf; 135*18140Sralph while (n = *cp++) { 136*18140Sralph /* 137*18140Sralph * check for indirection 138*18140Sralph */ 139*18140Sralph switch (n & INDIR_MASK) { 140*18140Sralph case 0: /* normal case, n == len */ 141*18140Sralph cp += n; 142*18140Sralph continue; 143*18140Sralph default: /* illegal type */ 144*18140Sralph return (-1); 145*18140Sralph case INDIR_MASK: /* indirection */ 146*18140Sralph cp++; 147*18140Sralph } 148*18140Sralph break; 149*18140Sralph } 150*18140Sralph return (cp - buf); 151*18140Sralph } 152*18140Sralph 153*18140Sralph /* 154*18140Sralph * Search for expanded name from a list of previously compressed names. 155*18140Sralph * Return the offset from msg if found or -1. 156*18140Sralph */ 157*18140Sralph dn_find(exp_dn, msg, dnptrs, lastdnptr) 158*18140Sralph char *exp_dn, *msg; 159*18140Sralph char **dnptrs, **lastdnptr; 160*18140Sralph { 161*18140Sralph register char *dn, *cp, **cpp; 162*18140Sralph register int n; 163*18140Sralph char *sp; 164*18140Sralph 165*18140Sralph for (cpp = dnptrs; cpp < lastdnptr; cpp++) { 166*18140Sralph dn = exp_dn; 167*18140Sralph sp = cp = *cpp; 168*18140Sralph while (n = *cp++) { 169*18140Sralph /* 170*18140Sralph * check for indirection 171*18140Sralph */ 172*18140Sralph switch (n & INDIR_MASK) { 173*18140Sralph case 0: /* normal case, n == len */ 174*18140Sralph while (--n >= 0) 175*18140Sralph if (*dn++ != *cp++) 176*18140Sralph goto next; 177*18140Sralph if ((n = *dn++) == '\0' && *cp == '\0') 178*18140Sralph return (sp - msg); 179*18140Sralph if (n == '.') 180*18140Sralph continue; 181*18140Sralph goto next; 182*18140Sralph 183*18140Sralph default: /* illegal type */ 184*18140Sralph return (-1); 185*18140Sralph 186*18140Sralph case INDIR_MASK: /* indirection */ 187*18140Sralph cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff)); 188*18140Sralph } 189*18140Sralph } 190*18140Sralph if (*dn == '\0') 191*18140Sralph return (sp - msg); 192*18140Sralph next: ; 193*18140Sralph } 194*18140Sralph return (-1); 195*18140Sralph } 196