]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/traceroute/as.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / traceroute / as.c
1 /* $FreeBSD$ */
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  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <sys/cdefs.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <netdb.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <errno.h>
43 #include <err.h>
44 #include <stdio.h>
45
46 #include "as.h"
47
48 #define DEFAULT_AS_SERVER "whois.radb.net"
49 #undef AS_DEBUG_FILE
50
51 struct aslookup {
52         FILE *as_f;
53 #ifdef AS_DEBUG_FILE
54         FILE *as_debug;
55 #endif /* AS_DEBUG_FILE */
56 };
57
58 void *
59 as_setup(const char *server)
60 {
61         struct aslookup *asn;
62         struct addrinfo hints, *res0, *res;
63         FILE *f;
64         int s, error;
65
66         s = -1;
67         if (server == NULL)
68                 server = getenv("RA_SERVER");
69         if (server == NULL)
70                 server = DEFAULT_AS_SERVER;
71
72         memset(&hints, 0, sizeof(hints));
73         hints.ai_family = PF_UNSPEC;
74         hints.ai_socktype = SOCK_STREAM;
75         error = getaddrinfo(server, "whois", &hints, &res0);
76         if (error == EAI_SERVICE) {
77                 warnx("warning: whois/tcp service not found");
78                 error = getaddrinfo(server, "43", &hints, &res0);
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         asn->as_debug = fopen(AS_DEBUG_FILE, "w");
112         if (asn->as_debug) {
113                 (void)fprintf(asn->as_debug, ">> !!\n");
114                 (void)fflush(asn->as_debug);
115         }
116 #endif /* AS_DEBUG_FILE */
117
118         return (asn);
119 }
120
121 unsigned int
122 as_lookup(void *_asn, char *addr, sa_family_t family)
123 {
124         struct aslookup *asn = _asn;
125         char buf[1024];
126         unsigned int as;
127         int rc, dlen, plen;
128
129         as = 0;
130         rc = dlen = 0;
131         plen = (family == AF_INET6) ? 128 : 32;
132         (void)fprintf(asn->as_f, "!r%s/%d,l\n", addr, plen);
133         (void)fflush(asn->as_f);
134
135 #ifdef AS_DEBUG_FILE
136         if (asn->as_debug) {
137                 (void)fprintf(asn->as_debug, ">> !r%s/%d,l\n", addr, plen);
138                 (void)fflush(asn->as_debug);
139         }
140 #endif /* AS_DEBUG_FILE */
141
142         while (fgets(buf, sizeof(buf), asn->as_f) != NULL) {
143                 buf[sizeof(buf) - 1] = '\0';
144
145 #ifdef AS_DEBUG_FILE
146                 if (asn->as_debug) {
147                         (void)fprintf(asn->as_debug, "<< %s", buf);
148                         (void)fflush(asn->as_debug);
149                 }
150 #endif /* AS_DEBUG_FILE */
151
152                 if (rc == 0) {
153                         rc = buf[0];
154                         switch (rc) {
155                             case 'A':
156                                 /* A - followed by # bytes of answer */
157                                 sscanf(buf, "A%d\n", &dlen);
158 #ifdef AS_DEBUG_FILE
159                                 if (asn->as_debug) {
160                                         (void)fprintf(asn->as_debug,
161                                              "dlen: %d\n", dlen);
162                                         (void)fflush(asn->as_debug);
163                                 }
164 #endif /* AS_DEBUG_FILE */
165                                 break;
166                             case 'C':
167                             case 'D':
168                             case 'E':
169                             case 'F':
170                                 /* C - no data returned */
171                                 /* D - key not found */
172                                 /* E - multiple copies of key */
173                                 /* F - some other error */
174                                 break;
175                         }
176                         if (rc == 'A')
177                                 /* skip to next input line */
178                                 continue;
179                 }
180
181                 if (dlen == 0)
182                         /* out of data, next char read is end code */
183                         rc = buf[0];
184                 if (rc != 'A')
185                         /* either an error off the bat, or a done code */
186                         break;
187
188                 /* data received, thank you */
189                 dlen -= strlen(buf);
190
191                 /* origin line is the interesting bit */
192                 if (as == 0 && strncasecmp(buf, "origin:", 7) == 0) {
193                         sscanf(buf + 7, " AS%u", &as);
194 #ifdef AS_DEBUG_FILE
195                         if (asn->as_debug) {
196                                 (void)fprintf(asn->as_debug, "as: %d\n", as);
197                                 (void)fflush(asn->as_debug);
198                         }
199 #endif /* AS_DEBUG_FILE */
200                 }
201         }
202
203         return (as);
204 }
205
206 void
207 as_shutdown(void *_asn)
208 {
209         struct aslookup *asn = _asn;
210
211         (void)fprintf(asn->as_f, "!q\n");
212         (void)fclose(asn->as_f);
213
214 #ifdef AS_DEBUG_FILE
215         if (asn->as_debug) {
216                 (void)fprintf(asn->as_debug, ">> !q\n");
217                 (void)fclose(asn->as_debug);
218         }
219 #endif /* AS_DEBUG_FILE */
220
221         free(asn);
222 }