1: /*
2: mtr -- a network diagnostic tool
3: Copyright (C) 1997,1998 Matt Kimball
4:
5: This program is free software; you can redistribute it and/or modify
6: it under the terms of the GNU General Public License version 2 as
7: published by the Free Software Foundation.
8:
9: This program is distributed in the hope that it will be useful,
10: but WITHOUT ANY WARRANTY; without even the implied warranty of
11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12: GNU General Public License for more details.
13:
14: You should have received a copy of the GNU General Public License
15: along with this program; if not, write to the Free Software
16: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17: */
18:
19: #include <config.h>
20: #include <sys/types.h>
21: #include <sys/time.h>
22: #include <stdlib.h>
23: #include <stdio.h>
24: #include <unistd.h>
25: #include <time.h>
26: #include <sys/select.h>
27: #include <string.h>
28: #include <math.h>
29: #include <errno.h>
30:
31: #include "mtr.h"
32: #include "display.h"
33: #include "dns.h"
34: #include "net.h"
35: #ifndef NO_IPINFO
36: #include "asn.h"
37: #endif
38:
39: extern int Interactive;
40: extern int MaxPing;
41: extern int ForceMaxPing;
42: extern float WaitTime;
43: double dnsinterval;
44: extern int mtrtype;
45:
46: static struct timeval intervaltime;
47: int display_offset = 0;
48:
49:
50: void select_loop(void) {
51: fd_set readfd;
52: fd_set writefd;
53: int anyset = 0;
54: int maxfd = 0;
55: int dnsfd, netfd;
56: #ifdef ENABLE_IPV6
57: int dnsfd6;
58: #endif
59: int NumPing = 0;
60: int paused = 0;
61: struct timeval lasttime, thistime, selecttime;
62: int dt;
63: int rv;
64:
65: gettimeofday(&lasttime, NULL);
66:
67: while(1) {
68: dt = calc_deltatime (WaitTime);
69: intervaltime.tv_sec = dt / 1000000;
70: intervaltime.tv_usec = dt % 1000000;
71:
72: FD_ZERO(&readfd);
73: FD_ZERO(&writefd);
74:
75: maxfd = 0;
76:
77: if(Interactive) {
78: FD_SET(0, &readfd);
79: maxfd = 1;
80: }
81:
82: #ifdef ENABLE_IPV6
83: if (dns) {
84: dnsfd6 = dns_waitfd6();
85: FD_SET(dnsfd6, &readfd);
86: if(dnsfd6 >= maxfd) maxfd = dnsfd6 + 1;
87: } else
88: dnsfd6 = 0;
89: #endif
90: if (dns) {
91: dnsfd = dns_waitfd();
92: FD_SET(dnsfd, &readfd);
93: if(dnsfd >= maxfd) maxfd = dnsfd + 1;
94: } else
95: dnsfd = 0;
96:
97: netfd = net_waitfd();
98: FD_SET(netfd, &readfd);
99: if(netfd >= maxfd) maxfd = netfd + 1;
100:
101: if (mtrtype == IPPROTO_TCP)
102: net_add_fds(&writefd, &maxfd);
103:
104: do {
105: if(anyset || paused) {
106: selecttime.tv_sec = 0;
107: selecttime.tv_usec = 0;
108:
109: rv = select(maxfd, (void *)&readfd, &writefd, NULL, &selecttime);
110:
111: } else {
112: if(Interactive) display_redraw();
113:
114: gettimeofday(&thistime, NULL);
115:
116: if(thistime.tv_sec > lasttime.tv_sec + intervaltime.tv_sec ||
117: (thistime.tv_sec == lasttime.tv_sec + intervaltime.tv_sec &&
118: thistime.tv_usec >= lasttime.tv_usec + intervaltime.tv_usec)) {
119: lasttime = thistime;
120: if(NumPing >= MaxPing && (!Interactive || ForceMaxPing))
121: return;
122: if (net_send_batch())
123: NumPing++;
124: }
125:
126: selecttime.tv_usec = (thistime.tv_usec - lasttime.tv_usec);
127: selecttime.tv_sec = (thistime.tv_sec - lasttime.tv_sec);
128: if (selecttime.tv_usec < 0) {
129: --selecttime.tv_sec;
130: selecttime.tv_usec += 1000000;
131: }
132: selecttime.tv_usec = intervaltime.tv_usec - selecttime.tv_usec;
133: selecttime.tv_sec = intervaltime.tv_sec - selecttime.tv_sec;
134: if (selecttime.tv_usec < 0) {
135: --selecttime.tv_sec;
136: selecttime.tv_usec += 1000000;
137: }
138:
139: if (dns) {
140: if ((selecttime.tv_sec > (time_t)dnsinterval) ||
141: ((selecttime.tv_sec == (time_t)dnsinterval) &&
142: (selecttime.tv_usec > ((time_t)(dnsinterval * 1000000) % 1000000)))) {
143: selecttime.tv_sec = (time_t)dnsinterval;
144: selecttime.tv_usec = (time_t)(dnsinterval * 1000000) % 1000000;
145: }
146: }
147:
148: rv = select(maxfd, (void *)&readfd, NULL, NULL, &selecttime);
149: }
150: } while ((rv < 0) && (errno == EINTR));
151:
152: if (rv < 0) {
153: perror ("Select failed");
154: exit (1);
155: }
156: anyset = 0;
157:
158: /* Have we got new packets back? */
159: if(FD_ISSET(netfd, &readfd)) {
160: net_process_return();
161: anyset = 1;
162: }
163:
164: if (dns) {
165: /* Handle any pending resolver events */
166: dnsinterval = WaitTime;
167: dns_events(&dnsinterval);
168: }
169:
170: /* Have we finished a nameservice lookup? */
171: #ifdef ENABLE_IPV6
172: if(dns && FD_ISSET(dnsfd6, &readfd)) {
173: dns_ack6();
174: anyset = 1;
175: }
176: #endif
177: if(dns && FD_ISSET(dnsfd, &readfd)) {
178: dns_ack();
179: anyset = 1;
180: }
181:
182: /* Has a key been pressed? */
183: if(FD_ISSET(0, &readfd)) {
184: switch (display_keyaction()) {
185: case ActionQuit:
186: return;
187: break;
188: case ActionReset:
189: net_reset();
190: break;
191: case ActionDisplay:
192: display_mode = (display_mode+1) % 3;
193: break;
194: case ActionClear:
195: display_clear();
196: break;
197: case ActionPause:
198: paused=1;
199: break;
200: case ActionResume:
201: paused=0;
202: break;
203: case ActionMPLS:
204: enablempls = !enablempls;
205: display_clear();
206: break;
207: case ActionDNS:
208: if (dns) {
209: use_dns = !use_dns;
210: display_clear();
211: }
212: break;
213: #ifndef NO_IPINFO
214: case ActionII:
215: if (ipinfo_no >= 0) {
216: ipinfo_no++;
217: if (ipinfo_no > ipinfo_max)
218: ipinfo_no = 0;
219: }
220: break;
221: case ActionAS:
222: if (ipinfo_no >= 0)
223: ipinfo_no = ipinfo_no?0:ipinfo_max;
224: break;
225: #endif
226:
227: case ActionScrollDown:
228: display_offset += 5;
229: break;
230: case ActionScrollUp:
231: display_offset -= 5;
232: if (display_offset < 0) {
233: display_offset = 0;
234: }
235: break;
236: }
237: anyset = 1;
238: }
239:
240: /* Check for activity on open sockets */
241: if (mtrtype == IPPROTO_TCP)
242: net_process_fds(&writefd);
243: }
244: return;
245: }
246:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>