10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 70Sstevel@tonic-gate * with the License. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 110Sstevel@tonic-gate * See the License for the specific language governing permissions 120Sstevel@tonic-gate * and limitations under the License. 130Sstevel@tonic-gate * 140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 190Sstevel@tonic-gate * 200Sstevel@tonic-gate * CDDL HEADER END 210Sstevel@tonic-gate */ 220Sstevel@tonic-gate /* 23*237Sanay * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 280Sstevel@tonic-gate /* All Rights Reserved */ 290Sstevel@tonic-gate 300Sstevel@tonic-gate /* 310Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 320Sstevel@tonic-gate * The Regents of the University of California 330Sstevel@tonic-gate * All Rights Reserved 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 360Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 370Sstevel@tonic-gate * contributors. 380Sstevel@tonic-gate */ 390Sstevel@tonic-gate 400Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 410Sstevel@tonic-gate 420Sstevel@tonic-gate #include "synonyms.h" 430Sstevel@tonic-gate 440Sstevel@tonic-gate #include <sys/types.h> 450Sstevel@tonic-gate #include <stdio.h> 460Sstevel@tonic-gate #include <arpa/nameser.h> 470Sstevel@tonic-gate 48*237Sanay static int dn_find(u_char *exp_dn, u_char *msg, u_char **dnptrs, 49*237Sanay u_char **lastdnptr); 500Sstevel@tonic-gate 510Sstevel@tonic-gate 520Sstevel@tonic-gate /* 530Sstevel@tonic-gate * Expand compressed domain name 'comp_dn' to full domain name. 540Sstevel@tonic-gate * 'msg' is a pointer to the begining of the message, 550Sstevel@tonic-gate * 'eomorig' points to the first location after the message, 560Sstevel@tonic-gate * 'exp_dn' is a pointer to a buffer of size 'length' for the result. 570Sstevel@tonic-gate * Return size of compressed name or -1 if there was an error. 580Sstevel@tonic-gate */ 59*237Sanay int 600Sstevel@tonic-gate dn_expand(msg, eomorig, comp_dn, exp_dn, length) 610Sstevel@tonic-gate u_char *msg, *eomorig, *comp_dn, *exp_dn; 620Sstevel@tonic-gate int length; 630Sstevel@tonic-gate { 640Sstevel@tonic-gate register u_char *cp, *dn; 650Sstevel@tonic-gate register int n, c; 660Sstevel@tonic-gate u_char *eom; 670Sstevel@tonic-gate int len = -1, checked = 0; 680Sstevel@tonic-gate 690Sstevel@tonic-gate dn = exp_dn; 700Sstevel@tonic-gate cp = comp_dn; 710Sstevel@tonic-gate eom = exp_dn + length; 720Sstevel@tonic-gate /* 730Sstevel@tonic-gate * fetch next label in domain name 740Sstevel@tonic-gate */ 750Sstevel@tonic-gate while (n = *cp++) { 760Sstevel@tonic-gate /* 770Sstevel@tonic-gate * Check for indirection 780Sstevel@tonic-gate */ 790Sstevel@tonic-gate switch (n & INDIR_MASK) { 800Sstevel@tonic-gate case 0: 810Sstevel@tonic-gate if (dn != exp_dn) { 820Sstevel@tonic-gate if (dn >= eom) 830Sstevel@tonic-gate return (-1); 840Sstevel@tonic-gate *dn++ = '.'; 850Sstevel@tonic-gate } 860Sstevel@tonic-gate if (dn+n >= eom) 870Sstevel@tonic-gate return (-1); 880Sstevel@tonic-gate checked += n + 1; 890Sstevel@tonic-gate while (--n >= 0) { 900Sstevel@tonic-gate if ((c = *cp++) == '.') { 910Sstevel@tonic-gate if (dn + n + 2 >= eom) 920Sstevel@tonic-gate return (-1); 930Sstevel@tonic-gate *dn++ = '\\'; 940Sstevel@tonic-gate } 950Sstevel@tonic-gate *dn++ = c; 960Sstevel@tonic-gate if (cp >= eomorig) /* out of range */ 970Sstevel@tonic-gate return (-1); 980Sstevel@tonic-gate } 990Sstevel@tonic-gate break; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate case INDIR_MASK: 1020Sstevel@tonic-gate if (len < 0) 1030Sstevel@tonic-gate len = cp - comp_dn + 1; 1040Sstevel@tonic-gate cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff)); 1050Sstevel@tonic-gate if (cp < msg || cp >= eomorig) /* out of range */ 1060Sstevel@tonic-gate return (-1); 1070Sstevel@tonic-gate checked += 2; 1080Sstevel@tonic-gate /* 1090Sstevel@tonic-gate * Check for loops in the compressed name; 1100Sstevel@tonic-gate * if we've looked at the whole message, 1110Sstevel@tonic-gate * there must be a loop. 1120Sstevel@tonic-gate */ 1130Sstevel@tonic-gate if (checked >= eomorig - msg) 1140Sstevel@tonic-gate return (-1); 1150Sstevel@tonic-gate break; 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate default: 1180Sstevel@tonic-gate return (-1); /* flag error */ 1190Sstevel@tonic-gate } 1200Sstevel@tonic-gate } 1210Sstevel@tonic-gate *dn = '\0'; 1220Sstevel@tonic-gate if (len < 0) 1230Sstevel@tonic-gate len = cp - comp_dn; 1240Sstevel@tonic-gate return (len); 1250Sstevel@tonic-gate } 1260Sstevel@tonic-gate 1270Sstevel@tonic-gate /* 1280Sstevel@tonic-gate * Compress domain name 'exp_dn' into 'comp_dn'. 1290Sstevel@tonic-gate * Return the size of the compressed name or -1. 1300Sstevel@tonic-gate * 'length' is the size of the array pointed to by 'comp_dn'. 1310Sstevel@tonic-gate * 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0] 1320Sstevel@tonic-gate * is a pointer to the beginning of the message. The list ends with NULL. 1330Sstevel@tonic-gate * 'lastdnptr' is a pointer to the end of the arrary pointed to 1340Sstevel@tonic-gate * by 'dnptrs'. Side effect is to update the list of pointers for 1350Sstevel@tonic-gate * labels inserted into the message as we compress the name. 1360Sstevel@tonic-gate * If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' 1370Sstevel@tonic-gate * is NULL, we don't update the list. 1380Sstevel@tonic-gate */ 139*237Sanay int 1400Sstevel@tonic-gate dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr) 1410Sstevel@tonic-gate u_char *exp_dn, *comp_dn; 1420Sstevel@tonic-gate int length; 1430Sstevel@tonic-gate u_char **dnptrs, **lastdnptr; 1440Sstevel@tonic-gate { 1450Sstevel@tonic-gate register u_char *cp, *dn; 1460Sstevel@tonic-gate register int c, l; 1470Sstevel@tonic-gate u_char **cpp, **lpp, *sp, *eob; 1480Sstevel@tonic-gate u_char *msg; 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate dn = exp_dn; 1510Sstevel@tonic-gate cp = comp_dn; 1520Sstevel@tonic-gate eob = cp + length; 1530Sstevel@tonic-gate if (dnptrs != NULL) { 1540Sstevel@tonic-gate if ((msg = *dnptrs++) != NULL) { 1550Sstevel@tonic-gate for (cpp = dnptrs; *cpp != NULL; cpp++) 1560Sstevel@tonic-gate ; 1570Sstevel@tonic-gate lpp = cpp; /* end of list to search */ 1580Sstevel@tonic-gate } 1590Sstevel@tonic-gate } else 1600Sstevel@tonic-gate msg = NULL; 1610Sstevel@tonic-gate for (c = *dn++; c != '\0'; /*EMPTY*/) { 1620Sstevel@tonic-gate /* look to see if we can use pointers */ 1630Sstevel@tonic-gate if (msg != NULL) { 1640Sstevel@tonic-gate if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) { 1650Sstevel@tonic-gate if (cp+1 >= eob) 1660Sstevel@tonic-gate return (-1); 1670Sstevel@tonic-gate *cp++ = (l >> 8) | INDIR_MASK; 1680Sstevel@tonic-gate *cp++ = l % 256; 1690Sstevel@tonic-gate return (cp - comp_dn); 1700Sstevel@tonic-gate } 1710Sstevel@tonic-gate /* not found, save it */ 1720Sstevel@tonic-gate if (lastdnptr != NULL && cpp < lastdnptr-1) { 1730Sstevel@tonic-gate *cpp++ = cp; 1740Sstevel@tonic-gate *cpp = NULL; 1750Sstevel@tonic-gate } 1760Sstevel@tonic-gate } 1770Sstevel@tonic-gate sp = cp++; /* save ptr to length byte */ 1780Sstevel@tonic-gate do { 1790Sstevel@tonic-gate if (c == '.') { 1800Sstevel@tonic-gate c = *dn++; 1810Sstevel@tonic-gate break; 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate if (c == '\\') { 1840Sstevel@tonic-gate if ((c = *dn++) == '\0') 1850Sstevel@tonic-gate break; 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate if (cp >= eob) { 1880Sstevel@tonic-gate if (msg != NULL) 1890Sstevel@tonic-gate *lpp = NULL; 1900Sstevel@tonic-gate return (-1); 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate *cp++ = c; 1930Sstevel@tonic-gate } while ((c = *dn++) != '\0'); 1940Sstevel@tonic-gate /* catch trailing '.'s but not '..' */ 1950Sstevel@tonic-gate if ((l = cp - sp - 1) == 0 && c == '\0') { 1960Sstevel@tonic-gate cp--; 1970Sstevel@tonic-gate break; 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate if (l <= 0 || l > MAXLABEL) { 2000Sstevel@tonic-gate if (msg != NULL) 2010Sstevel@tonic-gate *lpp = NULL; 2020Sstevel@tonic-gate return (-1); 2030Sstevel@tonic-gate } 2040Sstevel@tonic-gate *sp = l; 2050Sstevel@tonic-gate } 2060Sstevel@tonic-gate if (cp >= eob) { 2070Sstevel@tonic-gate if (msg != NULL) 2080Sstevel@tonic-gate *lpp = NULL; 2090Sstevel@tonic-gate return (-1); 2100Sstevel@tonic-gate } 2110Sstevel@tonic-gate *cp++ = '\0'; 2120Sstevel@tonic-gate return (cp - comp_dn); 2130Sstevel@tonic-gate } 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate /* 2160Sstevel@tonic-gate * Skip over a compressed domain name. Return the size or -1. 2170Sstevel@tonic-gate */ 218*237Sanay int 2190Sstevel@tonic-gate dn_skipname(comp_dn, eom) 2200Sstevel@tonic-gate u_char *comp_dn, *eom; 2210Sstevel@tonic-gate { 2220Sstevel@tonic-gate register u_char *cp; 2230Sstevel@tonic-gate register int n; 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate cp = comp_dn; 2260Sstevel@tonic-gate while (cp < eom && (n = *cp++)) { 2270Sstevel@tonic-gate /* 2280Sstevel@tonic-gate * check for indirection 2290Sstevel@tonic-gate */ 2300Sstevel@tonic-gate switch (n & INDIR_MASK) { 2310Sstevel@tonic-gate case 0: /* normal case, n == len */ 2320Sstevel@tonic-gate cp += n; 2330Sstevel@tonic-gate continue; 2340Sstevel@tonic-gate default: /* illegal type */ 2350Sstevel@tonic-gate return (-1); 2360Sstevel@tonic-gate case INDIR_MASK: /* indirection */ 2370Sstevel@tonic-gate cp++; 2380Sstevel@tonic-gate } 2390Sstevel@tonic-gate break; 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate return (cp - comp_dn); 2420Sstevel@tonic-gate } 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate /* 2450Sstevel@tonic-gate * Search for expanded name from a list of previously compressed names. 2460Sstevel@tonic-gate * Return the offset from msg if found or -1. 2470Sstevel@tonic-gate * dnptrs is the pointer to the first name on the list, 2480Sstevel@tonic-gate * not the pointer to the start of the message. 2490Sstevel@tonic-gate */ 250*237Sanay static int 251*237Sanay dn_find(u_char *exp_dn, u_char *msg, u_char **dnptrs, u_char **lastdnptr) 2520Sstevel@tonic-gate { 2530Sstevel@tonic-gate register u_char *dn, *cp, **cpp; 2540Sstevel@tonic-gate register int n; 2550Sstevel@tonic-gate u_char *sp; 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate for (cpp = dnptrs; cpp < lastdnptr; cpp++) { 2580Sstevel@tonic-gate dn = exp_dn; 2590Sstevel@tonic-gate sp = cp = *cpp; 2600Sstevel@tonic-gate while (n = *cp++) { 2610Sstevel@tonic-gate /* 2620Sstevel@tonic-gate * check for indirection 2630Sstevel@tonic-gate */ 2640Sstevel@tonic-gate switch (n & INDIR_MASK) { 2650Sstevel@tonic-gate case 0: /* normal case, n == len */ 2660Sstevel@tonic-gate while (--n >= 0) { 2670Sstevel@tonic-gate if (*dn == '.') 2680Sstevel@tonic-gate goto next; 2690Sstevel@tonic-gate if (*dn == '\\') 2700Sstevel@tonic-gate dn++; 2710Sstevel@tonic-gate if (*dn++ != *cp++) 2720Sstevel@tonic-gate goto next; 2730Sstevel@tonic-gate } 2740Sstevel@tonic-gate if ((n = *dn++) == '\0' && *cp == '\0') 2750Sstevel@tonic-gate return (sp - msg); 2760Sstevel@tonic-gate if (n == '.') 2770Sstevel@tonic-gate continue; 2780Sstevel@tonic-gate goto next; 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate default: /* illegal type */ 2810Sstevel@tonic-gate return (-1); 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate case INDIR_MASK: /* indirection */ 2840Sstevel@tonic-gate cp = msg + (((n & 0x3f) << 8) | *cp); 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate } 2870Sstevel@tonic-gate if (*dn == '\0') 2880Sstevel@tonic-gate return (sp - msg); 2890Sstevel@tonic-gate next: /*EMPTY*/; 2900Sstevel@tonic-gate } 2910Sstevel@tonic-gate return (-1); 2920Sstevel@tonic-gate } 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate /* 2950Sstevel@tonic-gate * Routines to insert/extract short/long's. Must account for byte 2960Sstevel@tonic-gate * order and non-alignment problems. This code at least has the 2970Sstevel@tonic-gate * advantage of being portable. 2980Sstevel@tonic-gate * 2990Sstevel@tonic-gate * used by sendmail. 3000Sstevel@tonic-gate */ 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate u_short 3030Sstevel@tonic-gate _getshort(msgp) 3040Sstevel@tonic-gate u_char *msgp; 3050Sstevel@tonic-gate { 3060Sstevel@tonic-gate register u_char *p = (u_char *) msgp; 3070Sstevel@tonic-gate #ifdef vax 3080Sstevel@tonic-gate /* 3090Sstevel@tonic-gate * vax compiler doesn't put shorts in registers 3100Sstevel@tonic-gate */ 3110Sstevel@tonic-gate register u_long u; 3120Sstevel@tonic-gate #else 3130Sstevel@tonic-gate register u_short u; 3140Sstevel@tonic-gate #endif 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate u = *p++ << 8; 3170Sstevel@tonic-gate return ((u_short)(u | *p)); 3180Sstevel@tonic-gate } 3190Sstevel@tonic-gate 3200Sstevel@tonic-gate u_long 3210Sstevel@tonic-gate _getlong(msgp) 3220Sstevel@tonic-gate u_char *msgp; 3230Sstevel@tonic-gate { 3240Sstevel@tonic-gate register u_char *p = (u_char *) msgp; 3250Sstevel@tonic-gate register u_long u; 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate u = *p++; u <<= 8; 3280Sstevel@tonic-gate u |= *p++; u <<= 8; 3290Sstevel@tonic-gate u |= *p++; u <<= 8; 3300Sstevel@tonic-gate return (u | *p); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate 333*237Sanay void 3340Sstevel@tonic-gate putshort(s, msgp) 3350Sstevel@tonic-gate register u_short s; 3360Sstevel@tonic-gate register u_char *msgp; 3370Sstevel@tonic-gate { 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate msgp[1] = s; 3400Sstevel@tonic-gate msgp[0] = s >> 8; 3410Sstevel@tonic-gate } 3420Sstevel@tonic-gate 343*237Sanay void 3440Sstevel@tonic-gate putlong(l, msgp) 3450Sstevel@tonic-gate register u_long l; 3460Sstevel@tonic-gate register u_char *msgp; 3470Sstevel@tonic-gate { 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate msgp[3] = l; 3500Sstevel@tonic-gate msgp[2] = (l >>= 8); 3510Sstevel@tonic-gate msgp[1] = (l >>= 8); 3520Sstevel@tonic-gate msgp[0] = l >> 8; 3530Sstevel@tonic-gate } 354