1176428Srpaulo/* $FreeBSD$ */ 2176428Srpaulo/* $NetBSD: as.c,v 1.1 2001/11/04 23:14:36 atatat Exp $ */ 3176428Srpaulo 4176428Srpaulo/* 5176428Srpaulo * Copyright (c) 2001 The NetBSD Foundation, Inc. 6176428Srpaulo * All rights reserved. 7176428Srpaulo * 8176428Srpaulo * This code is derived from software contributed to The NetBSD Foundation 9176428Srpaulo * by Andrew Brown. 10176428Srpaulo * 11176428Srpaulo * Redistribution and use in source and binary forms, with or without 12176428Srpaulo * modification, are permitted provided that the following conditions 13176428Srpaulo * are met: 14176428Srpaulo * 1. Redistributions of source code must retain the above copyright 15176428Srpaulo * notice, this list of conditions and the following disclaimer. 16176428Srpaulo * 2. Redistributions in binary form must reproduce the above copyright 17176428Srpaulo * notice, this list of conditions and the following disclaimer in the 18176428Srpaulo * documentation and/or other materials provided with the distribution. 19176428Srpaulo * 20176428Srpaulo * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21176428Srpaulo * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22176428Srpaulo * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23176428Srpaulo * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24176428Srpaulo * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25176428Srpaulo * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26176428Srpaulo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27176428Srpaulo * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28176428Srpaulo * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29176428Srpaulo * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30176428Srpaulo * POSSIBILITY OF SUCH DAMAGE. 31176428Srpaulo */ 32176428Srpaulo 33176428Srpaulo#include <sys/cdefs.h> 34176428Srpaulo#include <sys/types.h> 35176428Srpaulo#include <sys/socket.h> 36176428Srpaulo#include <netinet/in.h> 37176428Srpaulo#include <arpa/inet.h> 38176428Srpaulo#include <netdb.h> 39176428Srpaulo#include <unistd.h> 40176428Srpaulo#include <string.h> 41176428Srpaulo#include <stdlib.h> 42176428Srpaulo#include <errno.h> 43176428Srpaulo#include <err.h> 44176428Srpaulo#include <stdio.h> 45176428Srpaulo 46176428Srpaulo#include "as.h" 47176428Srpaulo 48176428Srpaulo#define DEFAULT_AS_SERVER "whois.radb.net" 49176428Srpaulo#undef AS_DEBUG_FILE 50176428Srpaulo 51176428Srpaulostruct aslookup { 52176428Srpaulo FILE *as_f; 53176428Srpaulo#ifdef AS_DEBUG_FILE 54176428Srpaulo FILE *as_debug; 55176428Srpaulo#endif /* AS_DEBUG_FILE */ 56176428Srpaulo}; 57176428Srpaulo 58176428Srpaulovoid * 59216184Suqsas_setup(const char *server) 60176428Srpaulo{ 61176428Srpaulo struct aslookup *asn; 62196475Sume struct addrinfo hints, *res0, *res; 63176428Srpaulo FILE *f; 64196475Sume int s, error; 65176428Srpaulo 66216184Suqs s = -1; 67176428Srpaulo if (server == NULL) 68196475Sume server = getenv("RA_SERVER"); 69196475Sume if (server == NULL) 70176428Srpaulo server = DEFAULT_AS_SERVER; 71176428Srpaulo 72196475Sume memset(&hints, 0, sizeof(hints)); 73196475Sume hints.ai_family = PF_UNSPEC; 74196475Sume hints.ai_socktype = SOCK_STREAM; 75196475Sume error = getaddrinfo(server, "whois", &hints, &res0); 76196475Sume if (error == EAI_SERVICE) { 77176428Srpaulo warnx("warning: whois/tcp service not found"); 78196475Sume error = getaddrinfo(server, "43", &hints, &res0); 79176428Srpaulo } 80196475Sume if (error != 0) { 81196475Sume warnx("%s: %s", server, gai_strerror(error)); 82176428Srpaulo return (NULL); 83176428Srpaulo } 84176428Srpaulo 85196475Sume for (res = res0; res; res = res->ai_next) { 86196475Sume s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 87196475Sume if (s < 0) 88196475Sume continue; 89196475Sume if (connect(s, res->ai_addr, res->ai_addrlen) >= 0) 90176428Srpaulo break; 91196475Sume close(s); 92196475Sume s = -1; 93196475Sume } 94196475Sume freeaddrinfo(res0); 95196475Sume if (s < 0) { 96176428Srpaulo warn("connect"); 97176428Srpaulo return (NULL); 98176428Srpaulo } 99176428Srpaulo 100176428Srpaulo f = fdopen(s, "r+"); 101176428Srpaulo (void)fprintf(f, "!!\n"); 102176428Srpaulo (void)fflush(f); 103176428Srpaulo 104176428Srpaulo asn = malloc(sizeof(struct aslookup)); 105176428Srpaulo if (asn == NULL) 106176428Srpaulo (void)fclose(f); 107176428Srpaulo else 108176428Srpaulo asn->as_f = f; 109176428Srpaulo 110176428Srpaulo#ifdef AS_DEBUG_FILE 111176428Srpaulo asn->as_debug = fopen(AS_DEBUG_FILE, "w"); 112176428Srpaulo if (asn->as_debug) { 113176428Srpaulo (void)fprintf(asn->as_debug, ">> !!\n"); 114176428Srpaulo (void)fflush(asn->as_debug); 115176428Srpaulo } 116176428Srpaulo#endif /* AS_DEBUG_FILE */ 117176428Srpaulo 118176428Srpaulo return (asn); 119176428Srpaulo} 120176428Srpaulo 121196475Sumeunsigned int 122196475Sumeas_lookup(void *_asn, char *addr, sa_family_t family) 123176428Srpaulo{ 124176428Srpaulo struct aslookup *asn = _asn; 125176428Srpaulo char buf[1024]; 126196475Sume unsigned int as; 127196475Sume int rc, dlen, plen; 128176428Srpaulo 129196475Sume as = 0; 130196475Sume rc = dlen = 0; 131196475Sume plen = (family == AF_INET6) ? 128 : 32; 132196475Sume (void)fprintf(asn->as_f, "!r%s/%d,l\n", addr, plen); 133176428Srpaulo (void)fflush(asn->as_f); 134176428Srpaulo 135176428Srpaulo#ifdef AS_DEBUG_FILE 136176428Srpaulo if (asn->as_debug) { 137196475Sume (void)fprintf(asn->as_debug, ">> !r%s/%d,l\n", addr, plen); 138176428Srpaulo (void)fflush(asn->as_debug); 139176428Srpaulo } 140176428Srpaulo#endif /* AS_DEBUG_FILE */ 141176428Srpaulo 142176428Srpaulo while (fgets(buf, sizeof(buf), asn->as_f) != NULL) { 143176428Srpaulo buf[sizeof(buf) - 1] = '\0'; 144176428Srpaulo 145176428Srpaulo#ifdef AS_DEBUG_FILE 146176428Srpaulo if (asn->as_debug) { 147176428Srpaulo (void)fprintf(asn->as_debug, "<< %s", buf); 148176428Srpaulo (void)fflush(asn->as_debug); 149176428Srpaulo } 150176428Srpaulo#endif /* AS_DEBUG_FILE */ 151176428Srpaulo 152176428Srpaulo if (rc == 0) { 153176428Srpaulo rc = buf[0]; 154176428Srpaulo switch (rc) { 155176428Srpaulo case 'A': 156176428Srpaulo /* A - followed by # bytes of answer */ 157176428Srpaulo sscanf(buf, "A%d\n", &dlen); 158176428Srpaulo#ifdef AS_DEBUG_FILE 159176428Srpaulo if (asn->as_debug) { 160176428Srpaulo (void)fprintf(asn->as_debug, 161176428Srpaulo "dlen: %d\n", dlen); 162176428Srpaulo (void)fflush(asn->as_debug); 163176428Srpaulo } 164176428Srpaulo#endif /* AS_DEBUG_FILE */ 165176428Srpaulo break; 166196475Sume case 'C': 167176428Srpaulo case 'D': 168176428Srpaulo case 'E': 169176428Srpaulo case 'F': 170176428Srpaulo /* C - no data returned */ 171176428Srpaulo /* D - key not found */ 172176428Srpaulo /* E - multiple copies of key */ 173176428Srpaulo /* F - some other error */ 174176428Srpaulo break; 175176428Srpaulo } 176176428Srpaulo if (rc == 'A') 177176428Srpaulo /* skip to next input line */ 178176428Srpaulo continue; 179176428Srpaulo } 180176428Srpaulo 181176428Srpaulo if (dlen == 0) 182176428Srpaulo /* out of data, next char read is end code */ 183176428Srpaulo rc = buf[0]; 184176428Srpaulo if (rc != 'A') 185176428Srpaulo /* either an error off the bat, or a done code */ 186176428Srpaulo break; 187176428Srpaulo 188176428Srpaulo /* data received, thank you */ 189176428Srpaulo dlen -= strlen(buf); 190176428Srpaulo 191176428Srpaulo /* origin line is the interesting bit */ 192176428Srpaulo if (as == 0 && strncasecmp(buf, "origin:", 7) == 0) { 193196475Sume sscanf(buf + 7, " AS%u", &as); 194176428Srpaulo#ifdef AS_DEBUG_FILE 195176428Srpaulo if (asn->as_debug) { 196176428Srpaulo (void)fprintf(asn->as_debug, "as: %d\n", as); 197176428Srpaulo (void)fflush(asn->as_debug); 198176428Srpaulo } 199176428Srpaulo#endif /* AS_DEBUG_FILE */ 200176428Srpaulo } 201176428Srpaulo } 202176428Srpaulo 203176428Srpaulo return (as); 204176428Srpaulo} 205176428Srpaulo 206176428Srpaulovoid 207196475Sumeas_shutdown(void *_asn) 208176428Srpaulo{ 209176428Srpaulo struct aslookup *asn = _asn; 210176428Srpaulo 211176428Srpaulo (void)fprintf(asn->as_f, "!q\n"); 212176428Srpaulo (void)fclose(asn->as_f); 213176428Srpaulo 214176428Srpaulo#ifdef AS_DEBUG_FILE 215176428Srpaulo if (asn->as_debug) { 216176428Srpaulo (void)fprintf(asn->as_debug, ">> !q\n"); 217176428Srpaulo (void)fclose(asn->as_debug); 218176428Srpaulo } 219176428Srpaulo#endif /* AS_DEBUG_FILE */ 220176428Srpaulo 221176428Srpaulo free(asn); 222176428Srpaulo} 223