Home | History | Annotate | Line # | Download | only in net
getnetnamadr.c revision 1.1.1.1
      1 /* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
      2  *	Dep. Matematica Universidade de Coimbra, Portugal, Europe
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  */
      8 /*
      9  * Copyright (c) 1983, 1993
     10  *	The Regents of the University of California.  All rights reserved.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. All advertising materials mentioning features or use of this software
     21  *    must display the following acknowledgement:
     22  *	This product includes software developed by the University of
     23  *	California, Berkeley and its contributors.
     24  * 4. Neither the name of the University nor the names of its contributors
     25  *    may be used to endorse or promote products derived from this software
     26  *    without specific prior written permission.
     27  *
     28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     38  * SUCH DAMAGE.
     39  */
     40 
     41 #if defined(LIBC_SCCS) && !defined(lint)
     42 static char sccsid[] = "@(#)getnetbyaddr.c	8.1 (Berkeley) 6/4/93";
     43 static char sccsid_[] = "from getnetnamadr.c	1.4 (Coimbra) 93/06/03";
     44 static char rcsid[] = "$Id: getnetnamadr.c,v 8.8 1997/06/01 20:34:37 vixie Exp ";
     45 #endif /* LIBC_SCCS and not lint */
     46 
     47 #include <sys/types.h>
     48 #include <sys/param.h>
     49 #include <sys/socket.h>
     50 #include <netinet/in.h>
     51 #include <arpa/inet.h>
     52 #include <arpa/nameser.h>
     53 
     54 #include <stdio.h>
     55 #include <netdb.h>
     56 #include <resolv.h>
     57 #include <ctype.h>
     58 #include <errno.h>
     59 #include <string.h>
     60 
     61 extern int h_errno;
     62 
     63 #if defined(mips) && defined(SYSTYPE_BSD43)
     64 extern int errno;
     65 #endif
     66 
     67 struct netent *_getnetbyaddr __P((long net, int type));
     68 struct netent *_getnetbyname __P((const char *name));
     69 
     70 #define BYADDR 0
     71 #define BYNAME 1
     72 #define	MAXALIASES	35
     73 
     74 #if PACKETSZ > 1024
     75 #define	MAXPACKET	PACKETSZ
     76 #else
     77 #define	MAXPACKET	1024
     78 #endif
     79 
     80 typedef union {
     81 	HEADER	hdr;
     82 	u_char	buf[MAXPACKET];
     83 } querybuf;
     84 
     85 typedef union {
     86 	long	al;
     87 	char	ac;
     88 } align;
     89 
     90 static struct netent *
     91 getnetanswer(answer, anslen, net_i)
     92 	querybuf *answer;
     93 	int anslen;
     94 	int net_i;
     95 {
     96 
     97 	register HEADER *hp;
     98 	register u_char *cp;
     99 	register int n;
    100 	u_char *eom;
    101 	int type, class, buflen, ancount, qdcount, haveanswer, i, nchar;
    102 	char aux1[30], aux2[30], ans[30], *in, *st, *pauxt, *bp, **ap,
    103 		*paux1 = &aux1[0], *paux2 = &aux2[0], flag = 0;
    104 static	struct netent net_entry;
    105 static	char *net_aliases[MAXALIASES], netbuf[PACKETSZ];
    106 
    107 	/*
    108 	 * find first satisfactory answer
    109 	 *
    110 	 *      answer --> +------------+  ( MESSAGE )
    111 	 *		   |   Header   |
    112 	 *		   +------------+
    113 	 *		   |  Question  | the question for the name server
    114 	 *		   +------------+
    115 	 *		   |   Answer   | RRs answering the question
    116 	 *		   +------------+
    117 	 *		   | Authority  | RRs pointing toward an authority
    118 	 *		   | Additional | RRs holding additional information
    119 	 *		   +------------+
    120 	 */
    121 	eom = answer->buf + anslen;
    122 	hp = &answer->hdr;
    123 	ancount = ntohs(hp->ancount); /* #/records in the answer section */
    124 	qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
    125 	bp = netbuf;
    126 	buflen = sizeof(netbuf);
    127 	cp = answer->buf + HFIXEDSZ;
    128 	if (!qdcount) {
    129 		if (hp->aa)
    130 			h_errno = HOST_NOT_FOUND;
    131 		else
    132 			h_errno = TRY_AGAIN;
    133 		return (NULL);
    134 	}
    135 	while (qdcount-- > 0)
    136 		cp += __dn_skipname(cp, eom) + QFIXEDSZ;
    137 	ap = net_aliases;
    138 	*ap = NULL;
    139 	net_entry.n_aliases = net_aliases;
    140 	haveanswer = 0;
    141 	while (--ancount >= 0 && cp < eom) {
    142 		n = dn_expand(answer->buf, eom, cp, bp, buflen);
    143 		if ((n < 0) || !res_dnok(bp))
    144 			break;
    145 		cp += n;
    146 		ans[0] = '\0';
    147 		(void)strcpy(&ans[0], bp);
    148 		GETSHORT(type, cp);
    149 		GETSHORT(class, cp);
    150 		cp += INT32SZ;		/* TTL */
    151 		GETSHORT(n, cp);
    152 		if (class == C_IN && type == T_PTR) {
    153 			n = dn_expand(answer->buf, eom, cp, bp, buflen);
    154 			if ((n < 0) || !res_hnok(bp)) {
    155 				cp += n;
    156 				return (NULL);
    157 			}
    158 			cp += n;
    159 			*ap++ = bp;
    160 			bp += strlen(bp) + 1;
    161 			net_entry.n_addrtype =
    162 				(class == C_IN) ? AF_INET : AF_UNSPEC;
    163 			haveanswer++;
    164 		}
    165 	}
    166 	if (haveanswer) {
    167 		*ap = NULL;
    168 		switch (net_i) {
    169 		case BYADDR:
    170 			net_entry.n_name = *net_entry.n_aliases;
    171 			net_entry.n_net = 0L;
    172 			break;
    173 		case BYNAME:
    174 			in = *net_entry.n_aliases;
    175 			net_entry.n_name = &ans[0];
    176 			aux2[0] = '\0';
    177 			for (i = 0; i < 4; i++) {
    178 				for (st = in, nchar = 0;
    179 				     *st != '.';
    180 				     st++, nchar++)
    181 					;
    182 				if (nchar != 1 || *in != '0' || flag) {
    183 					flag = 1;
    184 					(void)strncpy(paux1,
    185 						      (i==0) ? in : in-1,
    186 						      (i==0) ?nchar : nchar+1);
    187 					paux1[(i==0) ? nchar : nchar+1] = '\0';
    188 					pauxt = paux2;
    189 					paux2 = strcat(paux1, paux2);
    190 					paux1 = pauxt;
    191 				}
    192 				in = ++st;
    193 			}
    194 			net_entry.n_net = inet_network(paux2);
    195 			break;
    196 		}
    197 		net_entry.n_aliases++;
    198 		return (&net_entry);
    199 	}
    200 	h_errno = TRY_AGAIN;
    201 	return (NULL);
    202 }
    203 
    204 struct netent *
    205 getnetbyaddr(net, net_type)
    206 	register u_long net;
    207 	register int net_type;
    208 {
    209 	unsigned int netbr[4];
    210 	int nn, anslen;
    211 	querybuf buf;
    212 	char qbuf[MAXDNAME];
    213 	unsigned long net2;
    214 	struct netent *net_entry;
    215 
    216 	if (net_type != AF_INET)
    217 		return (_getnetbyaddr(net, net_type));
    218 
    219 	for (nn = 4, net2 = net; net2; net2 >>= 8)
    220 		netbr[--nn] = net2 & 0xff;
    221 	switch (nn) {
    222 	case 3: 	/* Class A */
    223 		sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]);
    224 		break;
    225 	case 2: 	/* Class B */
    226 		sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]);
    227 		break;
    228 	case 1: 	/* Class C */
    229 		sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
    230 		    netbr[1]);
    231 		break;
    232 	case 0: 	/* Class D - E */
    233 		sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
    234 		    netbr[1], netbr[0]);
    235 		break;
    236 	}
    237 	anslen = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
    238 	if (anslen < 0) {
    239 #ifdef DEBUG
    240 		if (_res.options & RES_DEBUG)
    241 			printf("res_query failed\n");
    242 #endif
    243 		if (errno == ECONNREFUSED)
    244 			return (_getnetbyaddr(net, net_type));
    245 		return (NULL);
    246 	}
    247 	net_entry = getnetanswer(&buf, anslen, BYADDR);
    248 	if (net_entry) {
    249 		unsigned u_net = net;	/* maybe net should be unsigned ? */
    250 
    251 		/* Strip trailing zeros */
    252 		while ((u_net & 0xff) == 0 && u_net != 0)
    253 			u_net >>= 8;
    254 		net_entry->n_net = u_net;
    255 		return (net_entry);
    256 	}
    257 	return (_getnetbyaddr(net, net_type));
    258 }
    259 
    260 struct netent *
    261 getnetbyname(net)
    262 	register const char *net;
    263 {
    264 	int anslen;
    265 	querybuf buf;
    266 	char qbuf[MAXDNAME];
    267 	struct netent *net_entry;
    268 
    269 	if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
    270 		h_errno = NETDB_INTERNAL;
    271 		return (NULL);
    272 	}
    273 	strcpy(&qbuf[0], net);
    274 	anslen = res_search(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
    275 	if (anslen < 0) {
    276 #ifdef DEBUG
    277 		if (_res.options & RES_DEBUG)
    278 			printf("res_query failed\n");
    279 #endif
    280 		if (errno == ECONNREFUSED)
    281 			return (_getnetbyname(net));
    282 		return (_getnetbyname(net));
    283 	}
    284 	net_entry = getnetanswer(&buf, anslen, BYNAME);
    285 	if (net_entry)
    286 		return (net_entry);
    287 	return (_getnetbyname(net));
    288 }
    289