Home | History | Annotate | Line # | Download | only in traceroute
      1 /*	$NetBSD: as.c,v 1.4 2011/05/10 01:52:49 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Andrew Brown.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #include <sys/types.h>
     34 #include <sys/socket.h>
     35 #include <netinet/in.h>
     36 #include <arpa/inet.h>
     37 #include <netdb.h>
     38 #include <unistd.h>
     39 #include <string.h>
     40 #include <stdlib.h>
     41 #include <errno.h>
     42 #include <err.h>
     43 #include <stdio.h>
     44 
     45 #include "as.h"
     46 
     47 #define DEFAULT_AS_SERVER "whois.radb.net"
     48 #undef AS_DEBUG_FILE
     49 
     50 struct aslookup {
     51 	FILE *as_f;
     52 #ifdef AS_DEBUG_FILE
     53 	FILE *as_debug;
     54 #endif /* AS_DEBUG_FILE */
     55 };
     56 
     57 void *
     58 as_setup(const char *server)
     59 {
     60 	struct aslookup *asn;
     61 	struct addrinfo hints, *res0, *res;
     62 	FILE *f;
     63 	int s, error;
     64 
     65 	s = -1;
     66 	if (server == NULL)
     67 		server = getenv("RA_SERVER");
     68 	if (server == NULL)
     69 		server = DEFAULT_AS_SERVER;
     70 
     71 	memset(&hints, 0, sizeof(hints));
     72 	hints.ai_family = PF_UNSPEC;
     73 	hints.ai_socktype = SOCK_STREAM;
     74 	error = getaddrinfo(server, "whois", &hints, &res0);
     75 	if (error == EAI_SERVICE) {
     76 		warnx("warning: whois/tcp service not found");
     77 		error = getaddrinfo(server, "43", &hints, &res0);
     78 	}
     79 
     80 	if (error != 0) {
     81 		warnx("%s: %s", server, gai_strerror(error));
     82 		return (NULL);
     83 	}
     84 
     85 	for (res = res0; res; res = res->ai_next) {
     86 		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
     87 		if (s < 0)
     88 			continue;
     89 		if (connect(s, res->ai_addr, res->ai_addrlen) >= 0)
     90 			break;
     91 		close(s);
     92 		s = -1;
     93 	}
     94 	freeaddrinfo(res0);
     95 	if (s < 0) {
     96 		warn("connect");
     97 		return (NULL);
     98 	}
     99 
    100 	f = fdopen(s, "r+");
    101 	(void)fprintf(f, "!!\n");
    102 	(void)fflush(f);
    103 
    104 	asn = malloc(sizeof(struct aslookup));
    105 	if (asn == NULL)
    106 		(void)fclose(f);
    107 	else
    108 		asn->as_f = f;
    109 
    110 #ifdef AS_DEBUG_FILE
    111 	if (asn) {
    112 		asn->as_debug = fopen(AS_DEBUG_FILE, "w");
    113 		if (asn->as_debug) {
    114 			(void)fprintf(asn->as_debug, ">> !!\n");
    115 			(void)fflush(asn->as_debug);
    116 		}
    117 	}
    118 #endif /* AS_DEBUG_FILE */
    119 
    120 	return (asn);
    121 }
    122 
    123 unsigned int
    124 as_lookup(void *_asn, char *addr, sa_family_t family)
    125 {
    126 	struct aslookup *asn = _asn;
    127 	char buf[1024];
    128 	unsigned int as;
    129 	int rc, dlen, plen;
    130 
    131 	as = 0;
    132 	rc = dlen = 0;
    133 	plen = (family == AF_INET6) ? 128 : 32;
    134 	(void)fprintf(asn->as_f, "!r%s/%d,l\n", addr, plen);
    135 	(void)fflush(asn->as_f);
    136 
    137 #ifdef AS_DEBUG_FILE
    138 	if (asn->as_debug) {
    139 		(void)fprintf(asn->as_debug, ">> !r%s/%d,l\n", addr, plen);
    140 		(void)fflush(asn->as_debug);
    141 	}
    142 #endif /* AS_DEBUG_FILE */
    143 
    144 	while (fgets(buf, sizeof(buf), asn->as_f) != NULL) {
    145 		buf[sizeof(buf) - 1] = '\0';
    146 
    147 #ifdef AS_DEBUG_FILE
    148 		if (asn->as_debug) {
    149 			(void)fprintf(asn->as_debug, "<< %s", buf);
    150 			(void)fflush(asn->as_debug);
    151 		}
    152 #endif /* AS_DEBUG_FILE */
    153 
    154 		if (rc == 0) {
    155 			rc = buf[0];
    156 			switch (rc) {
    157 			    case 'A':
    158 				/* A - followed by # bytes of answer */
    159 				sscanf(buf, "A%d\n", &dlen);
    160 #ifdef AS_DEBUG_FILE
    161 				if (asn->as_debug) {
    162 					(void)fprintf(asn->as_debug,
    163 					     "dlen: %d\n", dlen);
    164 					(void)fflush(asn->as_debug);
    165 				}
    166 #endif /* AS_DEBUG_FILE */
    167 				break;
    168 			    case 'C':
    169 			    case 'D':
    170 			    case 'E':
    171 			    case 'F':
    172 				/* C - no data returned */
    173 				/* D - key not found */
    174 				/* E - multiple copies of key */
    175 				/* F - some other error */
    176 				break;
    177 			}
    178 			if (rc == 'A')
    179 				/* skip to next input line */
    180 				continue;
    181 		}
    182 
    183 		if (dlen == 0)
    184 			/* out of data, next char read is end code */
    185 			rc = buf[0];
    186 		if (rc != 'A')
    187 			/* either an error off the bat, or a done code */
    188 			break;
    189 
    190 		/* data received, thank you */
    191 		dlen -= strlen(buf);
    192 
    193 		/* origin line is the interesting bit */
    194 		if (as == 0 && strncasecmp(buf, "origin:", 7) == 0) {
    195 			sscanf(buf + 7, " AS%u", &as);
    196 #ifdef AS_DEBUG_FILE
    197 			if (asn->as_debug) {
    198 				(void)fprintf(asn->as_debug, "as: %d\n", as);
    199 				(void)fflush(asn->as_debug);
    200 			}
    201 #endif /* AS_DEBUG_FILE */
    202 		}
    203 	}
    204 
    205 	return (as);
    206 }
    207 
    208 void
    209 as_shutdown(void *_asn)
    210 {
    211 	struct aslookup *asn = _asn;
    212 
    213 	(void)fprintf(asn->as_f, "!q\n");
    214 	(void)fclose(asn->as_f);
    215 
    216 #ifdef AS_DEBUG_FILE
    217 	if (asn->as_debug) {
    218 		(void)fprintf(asn->as_debug, ">> !q\n");
    219 		(void)fclose(asn->as_debug);
    220 	}
    221 #endif /* AS_DEBUG_FILE */
    222 
    223 	free(asn);
    224 }
    225