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