]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/traceroute/as.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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(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
140 int
141 as_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
225 void
226 as_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 }