1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)res_comp.c 5.4 (Berkeley) 09/14/85"; 9 #endif not lint 10 11 #include <sys/types.h> 12 #include <stdio.h> 13 #include <ctype.h> 14 #include <arpa/nameser.h> 15 16 17 /* 18 * Expand compressed domain name 'comp_dn' to full domain name. 19 * Expanded names are converted to lower case. 20 * 'msg' is a pointer to the begining of the message, 21 * 'exp_dn' is a pointer to a buffer of size 'length' for the result. 22 * Return size of compressed name or -1 if there was an error. 23 */ 24 dn_expand(msg, comp_dn, exp_dn, length) 25 char *msg, *comp_dn, *exp_dn; 26 int length; 27 { 28 register char *cp, *dn; 29 register int n, c; 30 char *eom; 31 int len = -1; 32 33 dn = exp_dn; 34 cp = comp_dn; 35 eom = exp_dn + length - 1; 36 /* 37 * fetch next label in domain name 38 */ 39 while (n = *cp++) { 40 /* 41 * Check for indirection 42 */ 43 switch (n & INDIR_MASK) { 44 case 0: 45 if (dn != exp_dn) { 46 if (dn >= eom) 47 return (-1); 48 *dn++ = '.'; 49 } 50 if (dn+n >= eom) 51 return (-1); 52 while (--n >= 0) 53 if (isupper(c = *cp++)) 54 *dn++ = tolower(c); 55 else { 56 if (c == '.') { 57 if (dn+n+1 >= eom) 58 return (-1); 59 *dn++ = '\\'; 60 } 61 *dn++ = c; 62 } 63 break; 64 65 case INDIR_MASK: 66 if (len < 0) 67 len = cp - comp_dn + 1; 68 cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff)); 69 break; 70 71 default: 72 return (-1); /* flag error */ 73 } 74 } 75 *dn = '\0'; 76 if (len < 0) 77 len = cp - comp_dn; 78 return (len); 79 } 80 81 /* 82 * Compress domain name 'exp_dn' into 'comp_dn'. 83 * Return the size of the compressed name or -1. 84 * 'length' is the size of the array pointed to by 'comp_dn'. 85 * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0] 86 * is a pointer to the beginning of the message. The list ends with NULL. 87 * 'lastdnptr' is a pointer to the end of the arrary pointed to 88 * by 'dnptrs'. Side effect is to update the list of pointers for 89 * labels inserted into the message as we compress the name. 90 * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' 91 * is NULL, we don't update the list. 92 */ 93 dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) 94 char *exp_dn, *comp_dn; 95 int length; 96 char **dnptrs, **lastdnptr; 97 { 98 register char *cp, *dn; 99 register int c, l; 100 char **cpp, **lpp, *sp, *eob; 101 char *msg; 102 103 dn = exp_dn; 104 cp = comp_dn; 105 eob = comp_dn + length; 106 if (dnptrs != NULL) { 107 if ((msg = *dnptrs++) != NULL) { 108 for (cpp = dnptrs; *cpp != NULL; cpp++) 109 ; 110 lpp = cpp; /* end of list to search */ 111 } 112 } else 113 msg = NULL; 114 for (c = *dn++; c != '\0'; ) { 115 /* look to see if we can use pointers */ 116 if (msg != NULL) { 117 if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) { 118 if (cp+1 >= eob) 119 return (-1); 120 *cp++ = (l >> 8) | INDIR_MASK; 121 *cp++ = l; 122 return (cp - comp_dn); 123 } 124 /* not found, save it */ 125 if (lastdnptr != NULL && cpp < lastdnptr-1) { 126 *cpp++ = cp; 127 *cpp = NULL; 128 } 129 } 130 sp = cp++; /* save ptr to length byte */ 131 do { 132 if (c == '.') { 133 c = *dn++; 134 break; 135 } 136 if (c == '\\') { 137 if ((c = *dn++) == '\0') 138 break; 139 } 140 if (cp >= eob) 141 return (-1); 142 *cp++ = c; 143 } while ((c = *dn++) != '\0'); 144 /* catch trailing '.'s but not '..' */ 145 if ((l = cp - sp - 1) == 0 && c == '\0') { 146 cp--; 147 break; 148 } 149 if (l <= 0 || l > MAXLABEL) 150 return (-1); 151 *sp = l; 152 } 153 if (cp >= eob) 154 return (-1); 155 *cp++ = '\0'; 156 return (cp - comp_dn); 157 } 158 159 /* 160 * Skip over a compressed domain name. Return the size or -1. 161 */ 162 dn_skip(comp_dn) 163 char *comp_dn; 164 { 165 register char *cp; 166 register int n; 167 168 cp = comp_dn; 169 while (n = *cp++) { 170 /* 171 * check for indirection 172 */ 173 switch (n & INDIR_MASK) { 174 case 0: /* normal case, n == len */ 175 cp += n; 176 continue; 177 default: /* illegal type */ 178 return (-1); 179 case INDIR_MASK: /* indirection */ 180 cp++; 181 } 182 break; 183 } 184 return (cp - comp_dn); 185 } 186 187 /* 188 * Search for expanded name from a list of previously compressed names. 189 * Return the offset from msg if found or -1. 190 */ 191 dn_find(exp_dn, msg, dnptrs, lastdnptr) 192 char *exp_dn, *msg; 193 char **dnptrs, **lastdnptr; 194 { 195 register char *dn, *cp, **cpp; 196 register int n; 197 char *sp; 198 199 for (cpp = dnptrs; cpp < lastdnptr; cpp++) { 200 dn = exp_dn; 201 sp = cp = *cpp; 202 while (n = *cp++) { 203 /* 204 * check for indirection 205 */ 206 switch (n & INDIR_MASK) { 207 case 0: /* normal case, n == len */ 208 while (--n >= 0) { 209 if (*dn == '\\') 210 dn++; 211 if (*dn++ != *cp++) 212 goto next; 213 } 214 if ((n = *dn++) == '\0' && *cp == '\0') 215 return (sp - msg); 216 if (n == '.') 217 continue; 218 goto next; 219 220 default: /* illegal type */ 221 return (-1); 222 223 case INDIR_MASK: /* indirection */ 224 cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff)); 225 } 226 } 227 if (*dn == '\0') 228 return (sp - msg); 229 next: ; 230 } 231 return (-1); 232 } 233 234 /* 235 * Routines to insert/extract short/long's. Must account for byte 236 * order and non-alignment problems. This code at least has the 237 * advantage of being portable. 238 */ 239 240 u_short 241 getshort(msgp) 242 char *msgp; 243 { 244 register u_char *p = (u_char *) msgp; 245 register u_short u; 246 247 u = *p++ << 8; 248 return (u | *p); 249 } 250 251 u_long 252 getlong(msgp) 253 char *msgp; 254 { 255 register u_char *p = (u_char *) msgp; 256 register u_long u; 257 258 u = *p++; u <<= 8; 259 u |= *p++; u <<= 8; 260 u |= *p++; u <<= 8; 261 return (u | *p); 262 } 263 264 265 putshort(s, msgp) 266 register u_short s; 267 register char *msgp; 268 { 269 270 msgp[1] = s; 271 msgp[0] = s >> 8; 272 } 273 274 putlong(l, msgp) 275 register u_long l; 276 register char *msgp; 277 { 278 279 msgp[3] = l; 280 msgp[2] = (l >>= 8); 281 msgp[1] = (l >>= 8); 282 msgp[0] = l >> 8; 283 } 284