118579Sfenner/* $FreeBSD$ */
2100787Sfenner/*	$NetBSD: as.c,v 1.1 2001/11/04 23:14:36 atatat Exp $	*/
318579Sfenner
418579Sfenner/*
518579Sfenner * Copyright (c) 2001 The NetBSD Foundation, Inc.
618579Sfenner * All rights reserved.
718579Sfenner *
818579Sfenner * This code is derived from software contributed to The NetBSD Foundation
918579Sfenner * by Andrew Brown.
1018579Sfenner *
1118579Sfenner * Redistribution and use in source and binary forms, with or without
1218579Sfenner * modification, are permitted provided that the following conditions
1318579Sfenner * are met:
1418579Sfenner * 1. Redistributions of source code must retain the above copyright
1518579Sfenner *    notice, this list of conditions and the following disclaimer.
1618579Sfenner * 2. Redistributions in binary form must reproduce the above copyright
1718579Sfenner *    notice, this list of conditions and the following disclaimer in the
1818579Sfenner *    documentation and/or other materials provided with the distribution.
1918579Sfenner *
2018579Sfenner * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2118579Sfenner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2218579Sfenner * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2318579Sfenner * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24100787Sfenner * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2518579Sfenner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2658835Sshin * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2718579Sfenner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28100787Sfenner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2918579Sfenner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3058835Sshin * POSSIBILITY OF SUCH DAMAGE.
3158835Sshin */
3258835Sshin
3318579Sfenner#include <sys/cdefs.h>
3418579Sfenner#include <sys/types.h>
3518579Sfenner#include <sys/socket.h>
3618579Sfenner#include <netinet/in.h>
3718579Sfenner#include <arpa/inet.h>
3818579Sfenner#include <netdb.h>
3918579Sfenner#include <unistd.h>
4018579Sfenner#include <string.h>
4118579Sfenner#include <stdlib.h>
4218579Sfenner#include <errno.h>
4377816Sru#include <err.h>
4477816Sru#include <stdio.h>
4577816Sru
4618579Sfenner#include "as.h"
4718579Sfenner
4818579Sfenner#define DEFAULT_AS_SERVER "whois.radb.net"
4918579Sfenner#undef AS_DEBUG_FILE
5018579Sfenner
5118579Sfennerstruct aslookup {
5218579Sfenner	FILE *as_f;
5318579Sfenner#ifdef AS_DEBUG_FILE
5418579Sfenner	FILE *as_debug;
5518579Sfenner#endif /* AS_DEBUG_FILE */
5618579Sfenner};
5718579Sfenner
5818579Sfennervoid *
5918579Sfenneras_setup(const char *server)
6077816Sru{
6118579Sfenner	struct aslookup *asn;
6218579Sfenner	struct addrinfo hints, *res0, *res;
6318579Sfenner	FILE *f;
6418579Sfenner	int s, error;
6518579Sfenner
6618579Sfenner	s = -1;
6718579Sfenner	if (server == NULL)
6818579Sfenner		server = getenv("RA_SERVER");
6918579Sfenner	if (server == NULL)
7018579Sfenner		server = DEFAULT_AS_SERVER;
7118579Sfenner
7218579Sfenner	memset(&hints, 0, sizeof(hints));
7318579Sfenner	hints.ai_family = PF_UNSPEC;
7418579Sfenner	hints.ai_socktype = SOCK_STREAM;
7518579Sfenner	error = getaddrinfo(server, "whois", &hints, &res0);
7618579Sfenner	if (error == EAI_SERVICE) {
7718579Sfenner		warnx("warning: whois/tcp service not found");
7818579Sfenner		error = getaddrinfo(server, "43", &hints, &res0);
7918579Sfenner	}
8077816Sru	if (error != 0) {
8118579Sfenner		warnx("%s: %s", server, gai_strerror(error));
8218579Sfenner		return (NULL);
8318579Sfenner	}
8418579Sfenner
8518579Sfenner	for (res = res0; res; res = res->ai_next) {
8618579Sfenner		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
8718579Sfenner		if (s < 0)
8818579Sfenner			continue;
8918579Sfenner		if (connect(s, res->ai_addr, res->ai_addrlen) >= 0)
9018579Sfenner			break;
9118579Sfenner		close(s);
9218579Sfenner		s = -1;
9318579Sfenner	}
9418579Sfenner	freeaddrinfo(res0);
9518579Sfenner	if (s < 0) {
9618579Sfenner		warn("connect");
9718579Sfenner		return (NULL);
9818579Sfenner	}
9918579Sfenner
10018579Sfenner	f = fdopen(s, "r+");
10118579Sfenner	(void)fprintf(f, "!!\n");
10218579Sfenner	(void)fflush(f);
10318579Sfenner
10418579Sfenner	asn = malloc(sizeof(struct aslookup));
10518579Sfenner	if (asn == NULL)
10618579Sfenner		(void)fclose(f);
10718579Sfenner	else
10818579Sfenner		asn->as_f = f;
10918579Sfenner
11018579Sfenner#ifdef AS_DEBUG_FILE
11118579Sfenner	asn->as_debug = fopen(AS_DEBUG_FILE, "w");
11218579Sfenner	if (asn->as_debug) {
11318579Sfenner		(void)fprintf(asn->as_debug, ">> !!\n");
11418579Sfenner		(void)fflush(asn->as_debug);
11518579Sfenner	}
11618579Sfenner#endif /* AS_DEBUG_FILE */
11718579Sfenner
11818579Sfenner	return (asn);
11918579Sfenner}
12018579Sfenner
12118579Sfennerunsigned int
12218579Sfenneras_lookup(void *_asn, char *addr, sa_family_t family)
12318579Sfenner{
12418579Sfenner	struct aslookup *asn = _asn;
12518579Sfenner	char buf[1024];
12618579Sfenner	unsigned int as;
12718579Sfenner	int rc, dlen, plen;
12818579Sfenner
12918579Sfenner	as = 0;
13018579Sfenner	rc = dlen = 0;
13118579Sfenner	plen = (family == AF_INET6) ? 128 : 32;
13218579Sfenner	(void)fprintf(asn->as_f, "!r%s/%d,l\n", addr, plen);
13318579Sfenner	(void)fflush(asn->as_f);
13418579Sfenner
13518579Sfenner#ifdef AS_DEBUG_FILE
13618579Sfenner	if (asn->as_debug) {
13718579Sfenner		(void)fprintf(asn->as_debug, ">> !r%s/%d,l\n", addr, plen);
13818579Sfenner		(void)fflush(asn->as_debug);
13918579Sfenner	}
14018579Sfenner#endif /* AS_DEBUG_FILE */
14118579Sfenner
14218579Sfenner	while (fgets(buf, sizeof(buf), asn->as_f) != NULL) {
14318579Sfenner		buf[sizeof(buf) - 1] = '\0';
14418579Sfenner
14518579Sfenner#ifdef AS_DEBUG_FILE
14618579Sfenner		if (asn->as_debug) {
14718579Sfenner			(void)fprintf(asn->as_debug, "<< %s", buf);
14818579Sfenner			(void)fflush(asn->as_debug);
14918579Sfenner		}
15018579Sfenner#endif /* AS_DEBUG_FILE */
15118579Sfenner
15218579Sfenner		if (rc == 0) {
15318579Sfenner			rc = buf[0];
15418579Sfenner			switch (rc) {
15518579Sfenner			    case 'A':
15618579Sfenner				/* A - followed by # bytes of answer */
15718579Sfenner				sscanf(buf, "A%d\n", &dlen);
15818579Sfenner#ifdef AS_DEBUG_FILE
15918579Sfenner				if (asn->as_debug) {
16018579Sfenner					(void)fprintf(asn->as_debug,
16118579Sfenner					     "dlen: %d\n", dlen);
16218579Sfenner					(void)fflush(asn->as_debug);
16318579Sfenner				}
16418579Sfenner#endif /* AS_DEBUG_FILE */
16518579Sfenner				break;
16618579Sfenner			    case 'C':
16718579Sfenner			    case 'D':
16818579Sfenner			    case 'E':
16918579Sfenner			    case 'F':
17018579Sfenner				/* C - no data returned */
17118579Sfenner				/* D - key not found */
17218579Sfenner				/* E - multiple copies of key */
17318579Sfenner				/* F - some other error */
17418579Sfenner				break;
17518579Sfenner			}
17618579Sfenner			if (rc == 'A')
17718579Sfenner				/* skip to next input line */
17818579Sfenner				continue;
17918579Sfenner		}
18018579Sfenner
18118579Sfenner		if (dlen == 0)
18218579Sfenner			/* out of data, next char read is end code */
18318579Sfenner			rc = buf[0];
18418579Sfenner		if (rc != 'A')
18518579Sfenner			/* either an error off the bat, or a done code */
18618579Sfenner			break;
18718579Sfenner
18818579Sfenner		/* data received, thank you */
18918579Sfenner		dlen -= strlen(buf);
19018579Sfenner
19118579Sfenner		/* origin line is the interesting bit */
19218579Sfenner		if (as == 0 && strncasecmp(buf, "origin:", 7) == 0) {
19318579Sfenner			sscanf(buf + 7, " AS%u", &as);
19418579Sfenner#ifdef AS_DEBUG_FILE
19518579Sfenner			if (asn->as_debug) {
19618579Sfenner				(void)fprintf(asn->as_debug, "as: %d\n", as);
19718579Sfenner				(void)fflush(asn->as_debug);
19818579Sfenner			}
19918579Sfenner#endif /* AS_DEBUG_FILE */
20018579Sfenner		}
20118579Sfenner	}
20218579Sfenner
20318579Sfenner	return (as);
20418579Sfenner}
20518579Sfenner
20618579Sfennervoid
20718579Sfenneras_shutdown(void *_asn)
20818579Sfenner{
20918579Sfenner	struct aslookup *asn = _asn;
21018579Sfenner
21118579Sfenner	(void)fprintf(asn->as_f, "!q\n");
21277816Sru	(void)fclose(asn->as_f);
21377816Sru
21477816Sru#ifdef AS_DEBUG_FILE
21518579Sfenner	if (asn->as_debug) {
21618579Sfenner		(void)fprintf(asn->as_debug, ">> !q\n");
21718579Sfenner		(void)fclose(asn->as_debug);
21818579Sfenner	}
21918579Sfenner#endif /* AS_DEBUG_FILE */
22018579Sfenner
22118579Sfenner	free(asn);
22218579Sfenner}
22346542Sarchie