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