]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/traceroute/as.c
libarchive: merge from vendor branch
[FreeBSD/FreeBSD.git] / usr.sbin / traceroute / as.c
1 /*      $NetBSD: as.c,v 1.1 2001/11/04 23:14:36 atatat 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         if (error != 0) {
80                 warnx("%s: %s", server, gai_strerror(error));
81                 return (NULL);
82         }
83
84         for (res = res0; res; res = res->ai_next) {
85                 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
86                 if (s < 0)
87                         continue;
88                 if (connect(s, res->ai_addr, res->ai_addrlen) >= 0)
89                         break;
90                 close(s);
91                 s = -1;
92         }
93         freeaddrinfo(res0);
94         if (s < 0) {
95                 warn("connect");
96                 return (NULL);
97         }
98
99         f = fdopen(s, "r+");
100         (void)fprintf(f, "!!\n");
101         (void)fflush(f);
102
103         asn = malloc(sizeof(struct aslookup));
104         if (asn == NULL)
105                 (void)fclose(f);
106         else
107                 asn->as_f = f;
108
109 #ifdef AS_DEBUG_FILE
110         asn->as_debug = fopen(AS_DEBUG_FILE, "w");
111         if (asn->as_debug) {
112                 (void)fprintf(asn->as_debug, ">> !!\n");
113                 (void)fflush(asn->as_debug);
114         }
115 #endif /* AS_DEBUG_FILE */
116
117         return (asn);
118 }
119
120 unsigned int
121 as_lookup(void *_asn, char *addr, sa_family_t family)
122 {
123         struct aslookup *asn = _asn;
124         char buf[1024];
125         unsigned int as;
126         int rc, dlen, plen;
127
128         as = 0;
129         rc = dlen = 0;
130         plen = (family == AF_INET6) ? 128 : 32;
131         (void)fprintf(asn->as_f, "!r%s/%d,l\n", addr, plen);
132         (void)fflush(asn->as_f);
133
134 #ifdef AS_DEBUG_FILE
135         if (asn->as_debug) {
136                 (void)fprintf(asn->as_debug, ">> !r%s/%d,l\n", addr, plen);
137                 (void)fflush(asn->as_debug);
138         }
139 #endif /* AS_DEBUG_FILE */
140
141         while (fgets(buf, sizeof(buf), asn->as_f) != NULL) {
142                 buf[sizeof(buf) - 1] = '\0';
143
144 #ifdef AS_DEBUG_FILE
145                 if (asn->as_debug) {
146                         (void)fprintf(asn->as_debug, "<< %s", buf);
147                         (void)fflush(asn->as_debug);
148                 }
149 #endif /* AS_DEBUG_FILE */
150
151                 if (rc == 0) {
152                         rc = buf[0];
153                         switch (rc) {
154                             case 'A':
155                                 /* A - followed by # bytes of answer */
156                                 sscanf(buf, "A%d\n", &dlen);
157 #ifdef AS_DEBUG_FILE
158                                 if (asn->as_debug) {
159                                         (void)fprintf(asn->as_debug,
160                                              "dlen: %d\n", dlen);
161                                         (void)fflush(asn->as_debug);
162                                 }
163 #endif /* AS_DEBUG_FILE */
164                                 break;
165                             case 'C':
166                             case 'D':
167                             case 'E':
168                             case 'F':
169                                 /* C - no data returned */
170                                 /* D - key not found */
171                                 /* E - multiple copies of key */
172                                 /* F - some other error */
173                                 break;
174                         }
175                         if (rc == 'A')
176                                 /* skip to next input line */
177                                 continue;
178                 }
179
180                 if (dlen == 0)
181                         /* out of data, next char read is end code */
182                         rc = buf[0];
183                 if (rc != 'A')
184                         /* either an error off the bat, or a done code */
185                         break;
186
187                 /* data received, thank you */
188                 dlen -= strlen(buf);
189
190                 /* origin line is the interesting bit */
191                 if (as == 0 && strncasecmp(buf, "origin:", 7) == 0) {
192                         sscanf(buf + 7, " AS%u", &as);
193 #ifdef AS_DEBUG_FILE
194                         if (asn->as_debug) {
195                                 (void)fprintf(asn->as_debug, "as: %d\n", as);
196                                 (void)fflush(asn->as_debug);
197                         }
198 #endif /* AS_DEBUG_FILE */
199                 }
200         }
201
202         return (as);
203 }
204
205 void
206 as_shutdown(void *_asn)
207 {
208         struct aslookup *asn = _asn;
209
210         (void)fprintf(asn->as_f, "!q\n");
211         (void)fclose(asn->as_f);
212
213 #ifdef AS_DEBUG_FILE
214         if (asn->as_debug) {
215                 (void)fprintf(asn->as_debug, ">> !q\n");
216                 (void)fclose(asn->as_debug);
217         }
218 #endif /* AS_DEBUG_FILE */
219
220         free(asn);
221 }