17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <ctype.h>
47dd7cddfSDavid du Colombier #include <bio.h>
57dd7cddfSDavid du Colombier #include <ndb.h>
65e1edbcaSDavid du Colombier #include <ip.h>
75a354e27SDavid du Colombier #include "icmp.h"
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier enum{
107dd7cddfSDavid du Colombier Maxstring= 128,
117dd7cddfSDavid du Colombier Maxpath= 256,
127dd7cddfSDavid du Colombier };
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier typedef struct DS DS;
157dd7cddfSDavid du Colombier struct DS {
165a354e27SDavid du Colombier /* dial string */
177dd7cddfSDavid du Colombier char buf[Maxstring];
187dd7cddfSDavid du Colombier char *netdir;
197dd7cddfSDavid du Colombier char *proto;
207dd7cddfSDavid du Colombier char *rem;
217dd7cddfSDavid du Colombier };
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier char *argv0;
247dd7cddfSDavid du Colombier int debug;
257dd7cddfSDavid du Colombier
263ff48bf5SDavid du Colombier void histogram(long *t, int n, int buckets, long lo, long hi);
273ff48bf5SDavid du Colombier
287dd7cddfSDavid du Colombier void
usage(void)297dd7cddfSDavid du Colombier usage(void)
307dd7cddfSDavid du Colombier {
315a354e27SDavid du Colombier fprint(2,
325a354e27SDavid du Colombier "usage: %s [-n][-a tries][-h buckets][-t ttl][-x net] [protocol!]destination\n",
335a354e27SDavid du Colombier argv0);
347dd7cddfSDavid du Colombier exits("usage");
357dd7cddfSDavid du Colombier }
367dd7cddfSDavid du Colombier
377dd7cddfSDavid du Colombier static int
csquery(DS * ds,char * clone,char * dest)387dd7cddfSDavid du Colombier csquery(DS *ds, char *clone, char *dest)
397dd7cddfSDavid du Colombier {
407dd7cddfSDavid du Colombier int n, fd;
417dd7cddfSDavid du Colombier char *p, buf[Maxstring];
427dd7cddfSDavid du Colombier
437dd7cddfSDavid du Colombier /*
447dd7cddfSDavid du Colombier * open connection server
457dd7cddfSDavid du Colombier */
467dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/cs", ds->netdir);
477dd7cddfSDavid du Colombier fd = open(buf, ORDWR);
487dd7cddfSDavid du Colombier if(fd < 0){
497dd7cddfSDavid du Colombier if(!isdigit(*dest)){
507dd7cddfSDavid du Colombier werrstr("can't translate");
517dd7cddfSDavid du Colombier return -1;
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier
547dd7cddfSDavid du Colombier /* no connection server, don't translate */
557dd7cddfSDavid du Colombier snprint(clone, sizeof(clone), "%s/%s/clone", ds->netdir, ds->proto);
567dd7cddfSDavid du Colombier strcpy(dest, ds->rem);
577dd7cddfSDavid du Colombier return 0;
587dd7cddfSDavid du Colombier }
597dd7cddfSDavid du Colombier
607dd7cddfSDavid du Colombier /*
617dd7cddfSDavid du Colombier * ask connection server to translate
627dd7cddfSDavid du Colombier */
637dd7cddfSDavid du Colombier sprint(buf, "%s!%s", ds->proto, ds->rem);
647dd7cddfSDavid du Colombier if(write(fd, buf, strlen(buf)) < 0){
657dd7cddfSDavid du Colombier close(fd);
667dd7cddfSDavid du Colombier return -1;
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier /*
707dd7cddfSDavid du Colombier * get an address.
717dd7cddfSDavid du Colombier */
727dd7cddfSDavid du Colombier seek(fd, 0, 0);
737dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf) - 1);
747dd7cddfSDavid du Colombier close(fd);
757dd7cddfSDavid du Colombier if(n <= 0){
767dd7cddfSDavid du Colombier werrstr("problem with cs");
777dd7cddfSDavid du Colombier return -1;
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier
807dd7cddfSDavid du Colombier buf[n] = 0;
817dd7cddfSDavid du Colombier p = strchr(buf, ' ');
827dd7cddfSDavid du Colombier if(p == 0){
837dd7cddfSDavid du Colombier werrstr("problem with cs");
847dd7cddfSDavid du Colombier return -1;
857dd7cddfSDavid du Colombier }
867dd7cddfSDavid du Colombier
877dd7cddfSDavid du Colombier *p++ = 0;
887dd7cddfSDavid du Colombier strcpy(clone, buf);
897dd7cddfSDavid du Colombier strcpy(dest, p);
907dd7cddfSDavid du Colombier return 0;
917dd7cddfSDavid du Colombier }
927dd7cddfSDavid du Colombier
937dd7cddfSDavid du Colombier /*
947dd7cddfSDavid du Colombier * call the dns process and have it try to resolve the mx request
957dd7cddfSDavid du Colombier */
967dd7cddfSDavid du Colombier static int
dodnsquery(DS * ds,char * ip,char * dom)977dd7cddfSDavid du Colombier dodnsquery(DS *ds, char *ip, char *dom)
987dd7cddfSDavid du Colombier {
997dd7cddfSDavid du Colombier char *p;
1007dd7cddfSDavid du Colombier Ndbtuple *t, *nt;
1017dd7cddfSDavid du Colombier
1027dd7cddfSDavid du Colombier p = strchr(ip, '!');
1037dd7cddfSDavid du Colombier if(p)
1047dd7cddfSDavid du Colombier *p = 0;
1057dd7cddfSDavid du Colombier
1067dd7cddfSDavid du Colombier t = dnsquery(ds->netdir, ip, "ptr");
1077dd7cddfSDavid du Colombier for(nt = t; nt != nil; nt = nt->entry)
1087dd7cddfSDavid du Colombier if(strcmp(nt->attr, "dom") == 0){
1097dd7cddfSDavid du Colombier strcpy(dom, nt->val);
1107dd7cddfSDavid du Colombier ndbfree(t);
1117dd7cddfSDavid du Colombier return 0;
1127dd7cddfSDavid du Colombier }
1137dd7cddfSDavid du Colombier ndbfree(t);
1147dd7cddfSDavid du Colombier return -1;
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier
1177dd7cddfSDavid du Colombier /* for connection oriented protocols (il, tcp) we just need
1187dd7cddfSDavid du Colombier * to try dialing. resending is up to it.
1197dd7cddfSDavid du Colombier */
1207dd7cddfSDavid du Colombier static int
tcpilprobe(int cfd,int dfd,char * dest,int interval)1217dd7cddfSDavid du Colombier tcpilprobe(int cfd, int dfd, char *dest, int interval)
1227dd7cddfSDavid du Colombier {
1237dd7cddfSDavid du Colombier int n;
1247dd7cddfSDavid du Colombier char msg[Maxstring];
1257dd7cddfSDavid du Colombier
1267dd7cddfSDavid du Colombier USED(dfd);
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier n = snprint(msg, sizeof msg, "connect %s", dest);
1297dd7cddfSDavid du Colombier alarm(interval);
1307dd7cddfSDavid du Colombier n = write(cfd, msg, n);
1317dd7cddfSDavid du Colombier alarm(0);
1327dd7cddfSDavid du Colombier return n;
1337dd7cddfSDavid du Colombier }
1347dd7cddfSDavid du Colombier
1357dd7cddfSDavid du Colombier /*
1367dd7cddfSDavid du Colombier * for udp, we keep sending to an improbable port
1377dd7cddfSDavid du Colombier * till we timeout or someone complains
1387dd7cddfSDavid du Colombier */
1397dd7cddfSDavid du Colombier static int
udpprobe(int cfd,int dfd,char * dest,int interval)1407dd7cddfSDavid du Colombier udpprobe(int cfd, int dfd, char *dest, int interval)
1417dd7cddfSDavid du Colombier {
1427dd7cddfSDavid du Colombier int n, i, rv;
1437dd7cddfSDavid du Colombier char msg[Maxstring];
1447dd7cddfSDavid du Colombier char err[Maxstring];
1457dd7cddfSDavid du Colombier
1467dd7cddfSDavid du Colombier seek(cfd, 0, 0);
1477dd7cddfSDavid du Colombier n = snprint(msg, sizeof msg, "connect %s", dest);
1487dd7cddfSDavid du Colombier if(write(cfd, msg, n)< 0)
1497dd7cddfSDavid du Colombier return -1;
1507dd7cddfSDavid du Colombier
1517dd7cddfSDavid du Colombier rv = -1;
1527dd7cddfSDavid du Colombier for(i = 0; i < 3; i++){
1537dd7cddfSDavid du Colombier alarm(interval/3);
1547dd7cddfSDavid du Colombier if(write(dfd, "boo hoo ", 8) < 0)
1557dd7cddfSDavid du Colombier break;
1567dd7cddfSDavid du Colombier /*
1577dd7cddfSDavid du Colombier * a hangup due to an error looks like 3 eofs followed
1587dd7cddfSDavid du Colombier * by a real error. this is a qio.c qbread() strangeness
1597dd7cddfSDavid du Colombier * done for pipes.
1607dd7cddfSDavid du Colombier */
1617dd7cddfSDavid du Colombier do {
1627dd7cddfSDavid du Colombier n = read(dfd, msg, sizeof(msg)-1);
1637dd7cddfSDavid du Colombier } while(n == 0);
1647dd7cddfSDavid du Colombier alarm(0);
1657dd7cddfSDavid du Colombier if(n > 0){
1667dd7cddfSDavid du Colombier rv = 0;
1677dd7cddfSDavid du Colombier break;
1687dd7cddfSDavid du Colombier }
1699a747e4fSDavid du Colombier errstr(err, sizeof err);
1707dd7cddfSDavid du Colombier if(strstr(err, "alarm") == 0){
1717dd7cddfSDavid du Colombier werrstr(err);
1727dd7cddfSDavid du Colombier break;
1737dd7cddfSDavid du Colombier }
1747dd7cddfSDavid du Colombier werrstr(err);
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier alarm(0);
1777dd7cddfSDavid du Colombier return rv;
1787dd7cddfSDavid du Colombier }
1797dd7cddfSDavid du Colombier
1807dd7cddfSDavid du Colombier #define MSG "traceroute probe"
1817dd7cddfSDavid du Colombier #define MAGIC 0xdead
1827dd7cddfSDavid du Colombier
1835e1edbcaSDavid du Colombier /* ICMPv4 only */
1847dd7cddfSDavid du Colombier static int
icmpprobe(int cfd,int dfd,char * dest,int interval)1857dd7cddfSDavid du Colombier icmpprobe(int cfd, int dfd, char *dest, int interval)
1867dd7cddfSDavid du Colombier {
1877dd7cddfSDavid du Colombier int x, i, n, len, rv;
188*94aa1c4cSDavid du Colombier char buf[512], err[Maxstring], msg[Maxstring];
189*94aa1c4cSDavid du Colombier Icmphdr *ip;
1907dd7cddfSDavid du Colombier
1917dd7cddfSDavid du Colombier seek(cfd, 0, 0);
1927dd7cddfSDavid du Colombier n = snprint(msg, sizeof msg, "connect %s", dest);
1937dd7cddfSDavid du Colombier if(write(cfd, msg, n)< 0)
1947dd7cddfSDavid du Colombier return -1;
1957dd7cddfSDavid du Colombier
1967dd7cddfSDavid du Colombier rv = -1;
197*94aa1c4cSDavid du Colombier ip = (Icmphdr *)(buf + IPV4HDR_LEN);
1987dd7cddfSDavid du Colombier for(i = 0; i < 3; i++){
1997dd7cddfSDavid du Colombier alarm(interval/3);
2007dd7cddfSDavid du Colombier ip->type = EchoRequest;
2017dd7cddfSDavid du Colombier ip->code = 0;
2027dd7cddfSDavid du Colombier strcpy((char*)ip->data, MSG);
2037dd7cddfSDavid du Colombier ip->seq[0] = MAGIC;
2047dd7cddfSDavid du Colombier ip->seq[1] = MAGIC>>8;
2055e1edbcaSDavid du Colombier len = IPV4HDR_LEN + ICMP_HDRSIZE + sizeof(MSG);
2067dd7cddfSDavid du Colombier
2077dd7cddfSDavid du Colombier /* send a request */
2087dd7cddfSDavid du Colombier if(write(dfd, buf, len) < len)
2097dd7cddfSDavid du Colombier break;
2107dd7cddfSDavid du Colombier
2117dd7cddfSDavid du Colombier /* wait for reply */
2127dd7cddfSDavid du Colombier n = read(dfd, buf, sizeof(buf));
2137dd7cddfSDavid du Colombier alarm(0);
2147dd7cddfSDavid du Colombier if(n < 0){
2159a747e4fSDavid du Colombier errstr(err, sizeof err);
2167dd7cddfSDavid du Colombier if(strstr(err, "alarm") == 0){
2177dd7cddfSDavid du Colombier werrstr(err);
2187dd7cddfSDavid du Colombier break;
2197dd7cddfSDavid du Colombier }
2207dd7cddfSDavid du Colombier werrstr(err);
2217dd7cddfSDavid du Colombier continue;
2227dd7cddfSDavid du Colombier }
2237dd7cddfSDavid du Colombier x = (ip->seq[1]<<8) | ip->seq[0];
224*94aa1c4cSDavid du Colombier if(n >= len && ip->type == EchoReply && x == MAGIC &&
225*94aa1c4cSDavid du Colombier strcmp((char*)ip->data, MSG) == 0){
2267dd7cddfSDavid du Colombier rv = 0;
2277dd7cddfSDavid du Colombier break;
2287dd7cddfSDavid du Colombier }
2297dd7cddfSDavid du Colombier }
2307dd7cddfSDavid du Colombier alarm(0);
2317dd7cddfSDavid du Colombier return rv;
2327dd7cddfSDavid du Colombier }
2337dd7cddfSDavid du Colombier
2347dd7cddfSDavid du Colombier static void
catch(void * a,char * msg)2357dd7cddfSDavid du Colombier catch(void *a, char *msg)
2367dd7cddfSDavid du Colombier {
2377dd7cddfSDavid du Colombier USED(a);
2387dd7cddfSDavid du Colombier if(strstr(msg, "alarm"))
2397dd7cddfSDavid du Colombier noted(NCONT);
2407dd7cddfSDavid du Colombier else
2417dd7cddfSDavid du Colombier noted(NDFLT);
2427dd7cddfSDavid du Colombier }
2437dd7cddfSDavid du Colombier
2447dd7cddfSDavid du Colombier static int
call(DS * ds,char * clone,char * dest,int ttl,long * interval)2457dd7cddfSDavid du Colombier call(DS *ds, char *clone, char *dest, int ttl, long *interval)
2467dd7cddfSDavid du Colombier {
2477dd7cddfSDavid du Colombier int cfd, dfd, rv, n;
2487dd7cddfSDavid du Colombier char msg[Maxstring];
2497dd7cddfSDavid du Colombier char file[Maxstring];
2507dd7cddfSDavid du Colombier vlong start;
2517dd7cddfSDavid du Colombier
2527dd7cddfSDavid du Colombier notify(catch);
2537dd7cddfSDavid du Colombier
2547dd7cddfSDavid du Colombier /* start timing */
2557dd7cddfSDavid du Colombier start = nsec()/1000;
2567dd7cddfSDavid du Colombier rv = -1;
2577dd7cddfSDavid du Colombier
2587dd7cddfSDavid du Colombier cfd = open(clone, ORDWR);
2597dd7cddfSDavid du Colombier if(cfd < 0){
2607dd7cddfSDavid du Colombier werrstr("%s: %r", clone);
2617dd7cddfSDavid du Colombier return -1;
2627dd7cddfSDavid du Colombier }
2637dd7cddfSDavid du Colombier dfd = -1;
2647dd7cddfSDavid du Colombier
2657dd7cddfSDavid du Colombier /* get conversation number */
2667dd7cddfSDavid du Colombier n = read(cfd, msg, sizeof(msg)-1);
2677dd7cddfSDavid du Colombier if(n <= 0)
2687dd7cddfSDavid du Colombier goto out;
2697dd7cddfSDavid du Colombier msg[n] = 0;
2707dd7cddfSDavid du Colombier
2717dd7cddfSDavid du Colombier /* open data file */
2727dd7cddfSDavid du Colombier sprint(file, "%s/%s/%s/data", ds->netdir, ds->proto, msg);
2737dd7cddfSDavid du Colombier dfd = open(file, ORDWR);
2747dd7cddfSDavid du Colombier if(dfd < 0)
2757dd7cddfSDavid du Colombier goto out;
2767dd7cddfSDavid du Colombier
2777dd7cddfSDavid du Colombier /* set ttl */
2787dd7cddfSDavid du Colombier if(ttl)
2797dd7cddfSDavid du Colombier fprint(cfd, "ttl %d", ttl);
2807dd7cddfSDavid du Colombier
2817dd7cddfSDavid du Colombier /* probe */
2827dd7cddfSDavid du Colombier if(strcmp(ds->proto, "udp") == 0)
2837dd7cddfSDavid du Colombier rv = udpprobe(cfd, dfd, dest, 3000);
2847dd7cddfSDavid du Colombier else if(strcmp(ds->proto, "icmp") == 0)
2857dd7cddfSDavid du Colombier rv = icmpprobe(cfd, dfd, dest, 3000);
2867dd7cddfSDavid du Colombier else /* il and tcp */
2877dd7cddfSDavid du Colombier rv = tcpilprobe(cfd, dfd, dest, 3000);
2887dd7cddfSDavid du Colombier out:
2897dd7cddfSDavid du Colombier /* turn off alarms */
2907dd7cddfSDavid du Colombier alarm(0);
2917dd7cddfSDavid du Colombier *interval = nsec()/1000 - start;
2927dd7cddfSDavid du Colombier close(cfd);
2937dd7cddfSDavid du Colombier close(dfd);
2947dd7cddfSDavid du Colombier return rv;
2957dd7cddfSDavid du Colombier }
2967dd7cddfSDavid du Colombier
2977dd7cddfSDavid du Colombier /*
2987dd7cddfSDavid du Colombier * parse a dial string. default netdir is /net.
2997dd7cddfSDavid du Colombier * default proto is tcp.
3007dd7cddfSDavid du Colombier */
3017dd7cddfSDavid du Colombier static void
dial_string_parse(char * str,DS * ds)3027dd7cddfSDavid du Colombier dial_string_parse(char *str, DS *ds)
3037dd7cddfSDavid du Colombier {
3047dd7cddfSDavid du Colombier char *p, *p2;
3057dd7cddfSDavid du Colombier
3067dd7cddfSDavid du Colombier strncpy(ds->buf, str, Maxstring);
3077dd7cddfSDavid du Colombier ds->buf[Maxstring-3] = 0;
3087dd7cddfSDavid du Colombier
3097dd7cddfSDavid du Colombier p = strchr(ds->buf, '!');
3107dd7cddfSDavid du Colombier if(p == 0) {
3117dd7cddfSDavid du Colombier ds->netdir = 0;
3127dd7cddfSDavid du Colombier ds->proto = "tcp";
3137dd7cddfSDavid du Colombier ds->rem = ds->buf;
3147dd7cddfSDavid du Colombier } else {
3157dd7cddfSDavid du Colombier if(*ds->buf != '/'){
3167dd7cddfSDavid du Colombier ds->netdir = 0;
3177dd7cddfSDavid du Colombier ds->proto = ds->buf;
3187dd7cddfSDavid du Colombier } else {
3197dd7cddfSDavid du Colombier for(p2 = p; *p2 != '/'; p2--)
3207dd7cddfSDavid du Colombier ;
3217dd7cddfSDavid du Colombier *p2++ = 0;
3227dd7cddfSDavid du Colombier ds->netdir = ds->buf;
3237dd7cddfSDavid du Colombier ds->proto = p2;
3247dd7cddfSDavid du Colombier }
3257dd7cddfSDavid du Colombier *p = 0;
3267dd7cddfSDavid du Colombier ds->rem = p + 1;
3277dd7cddfSDavid du Colombier }
3287dd7cddfSDavid du Colombier if(strchr(ds->rem, '!') == 0)
3297dd7cddfSDavid du Colombier strcat(ds->rem, "!32767");
3307dd7cddfSDavid du Colombier }
3317dd7cddfSDavid du Colombier
3327dd7cddfSDavid du Colombier void
main(int argc,char ** argv)3337dd7cddfSDavid du Colombier main(int argc, char **argv)
3347dd7cddfSDavid du Colombier {
3355a354e27SDavid du Colombier int buckets, ttl, j, done, tries, notranslate;
3365a354e27SDavid du Colombier long lo, hi, sum, x;
3375a354e27SDavid du Colombier long *t;
3385a354e27SDavid du Colombier char *net, *p;
3397dd7cddfSDavid du Colombier char clone[Maxpath], dest[Maxstring], hop[Maxstring], dom[Maxstring];
3407dd7cddfSDavid du Colombier char err[Maxstring];
3415a354e27SDavid du Colombier DS ds;
3427dd7cddfSDavid du Colombier
3433ff48bf5SDavid du Colombier buckets = 0;
3447dd7cddfSDavid du Colombier tries = 3;
3457dd7cddfSDavid du Colombier notranslate = 0;
3467dd7cddfSDavid du Colombier net = "/net";
3473ff48bf5SDavid du Colombier ttl = 1;
3487dd7cddfSDavid du Colombier ARGBEGIN{
3495a354e27SDavid du Colombier case 'a':
3505a354e27SDavid du Colombier tries = atoi(EARGF(usage()));
3513ff48bf5SDavid du Colombier break;
3527dd7cddfSDavid du Colombier case 'd':
3537dd7cddfSDavid du Colombier debug++;
3547dd7cddfSDavid du Colombier break;
3555a354e27SDavid du Colombier case 'h':
3565a354e27SDavid du Colombier buckets = atoi(EARGF(usage()));
3575a354e27SDavid du Colombier break;
3587dd7cddfSDavid du Colombier case 'n':
3597dd7cddfSDavid du Colombier notranslate++;
3607dd7cddfSDavid du Colombier break;
3615a354e27SDavid du Colombier case 't':
3625a354e27SDavid du Colombier ttl = atoi(EARGF(usage()));
3637dd7cddfSDavid du Colombier break;
3647dd7cddfSDavid du Colombier case 'x':
3656c54378cSDavid du Colombier net = EARGF(usage());
3667dd7cddfSDavid du Colombier break;
3677dd7cddfSDavid du Colombier default:
3687dd7cddfSDavid du Colombier usage();
3697dd7cddfSDavid du Colombier }ARGEND;
3707dd7cddfSDavid du Colombier
3717dd7cddfSDavid du Colombier if(argc < 1)
3727dd7cddfSDavid du Colombier usage();
3737dd7cddfSDavid du Colombier
3743ff48bf5SDavid du Colombier t = malloc(tries*sizeof(ulong));
3753ff48bf5SDavid du Colombier
3767dd7cddfSDavid du Colombier dial_string_parse(argv[0], &ds);
3777dd7cddfSDavid du Colombier
3787dd7cddfSDavid du Colombier if(ds.netdir == 0)
3797dd7cddfSDavid du Colombier ds.netdir = net;
3807dd7cddfSDavid du Colombier if(csquery(&ds, clone, dest) < 0){
3817dd7cddfSDavid du Colombier fprint(2, "%s: %s: %r\n", argv0, argv[0]);
3827dd7cddfSDavid du Colombier exits(0);
3837dd7cddfSDavid du Colombier }
3847dd7cddfSDavid du Colombier print("trying %s/%s!%s\n\n", ds.netdir, ds.proto, dest);
3857dd7cddfSDavid du Colombier print(" round trip times in µs\n");
3867dd7cddfSDavid du Colombier print(" low avg high\n");
3877dd7cddfSDavid du Colombier print(" --------------------------\n");
3887dd7cddfSDavid du Colombier
3897dd7cddfSDavid du Colombier done = 0;
3903ff48bf5SDavid du Colombier for(; ttl < 32; ttl++){
3913ff48bf5SDavid du Colombier for(j = 0; j < tries; j++){
3923ff48bf5SDavid du Colombier if(call(&ds, clone, dest, ttl, &t[j]) >= 0){
3933ff48bf5SDavid du Colombier if(debug)
3943ff48bf5SDavid du Colombier print("%ld %s\n", t[j], dest);
3957dd7cddfSDavid du Colombier strcpy(hop, dest);
3967dd7cddfSDavid du Colombier done = 1;
3977dd7cddfSDavid du Colombier continue;
3987dd7cddfSDavid du Colombier }
3999a747e4fSDavid du Colombier errstr(err, sizeof err);
4007dd7cddfSDavid du Colombier if(strstr(err, "refused")){
4017dd7cddfSDavid du Colombier strcpy(hop, dest);
4027dd7cddfSDavid du Colombier p = strchr(hop, '!');
4037dd7cddfSDavid du Colombier if(p)
4047dd7cddfSDavid du Colombier *p = 0;
4057dd7cddfSDavid du Colombier done = 1;
4067dd7cddfSDavid du Colombier } else if(strstr(err, "unreachable")){
4073ff48bf5SDavid du Colombier snprint(hop, sizeof(hop), "%s", err);
4087dd7cddfSDavid du Colombier p = strchr(hop, '!');
4097dd7cddfSDavid du Colombier if(p)
4107dd7cddfSDavid du Colombier *p = 0;
4117dd7cddfSDavid du Colombier done = 1;
4125a354e27SDavid du Colombier } else if(strncmp(err, "ttl exceeded at ", 16) == 0)
4137dd7cddfSDavid du Colombier strcpy(hop, err+16);
4145a354e27SDavid du Colombier else {
4157dd7cddfSDavid du Colombier strcpy(hop, "*");
4167dd7cddfSDavid du Colombier break;
4177dd7cddfSDavid du Colombier }
4183ff48bf5SDavid du Colombier if(debug)
4193ff48bf5SDavid du Colombier print("%ld %s\n", t[j], hop);
4207dd7cddfSDavid du Colombier }
4217dd7cddfSDavid du Colombier if(strcmp(hop, "*") == 0){
4227dd7cddfSDavid du Colombier print("*\n");
4237dd7cddfSDavid du Colombier continue;
4247dd7cddfSDavid du Colombier }
4257dd7cddfSDavid du Colombier lo = 10000000;
4267dd7cddfSDavid du Colombier hi = 0;
4277dd7cddfSDavid du Colombier sum = 0;
4287dd7cddfSDavid du Colombier for(j = 0; j < tries; j++){
4297dd7cddfSDavid du Colombier x = t[j];
4307dd7cddfSDavid du Colombier sum += x;
4317dd7cddfSDavid du Colombier if(x < lo)
4327dd7cddfSDavid du Colombier lo = x;
4337dd7cddfSDavid du Colombier if(x > hi)
4347dd7cddfSDavid du Colombier hi = x;
4357dd7cddfSDavid du Colombier }
4367dd7cddfSDavid du Colombier if(notranslate == 1 || dodnsquery(&ds, hop, dom) < 0)
4377dd7cddfSDavid du Colombier dom[0] = 0;
438059f8267SDavid du Colombier /* don't truncate: ipv6 addresses can be quite long */
439059f8267SDavid du Colombier print("%-18s %8ld %8ld %8ld %s\n", hop, lo, sum/tries, hi, dom);
4403ff48bf5SDavid du Colombier if(buckets)
4413ff48bf5SDavid du Colombier histogram(t, tries, buckets, lo, hi);
4427dd7cddfSDavid du Colombier if(done)
4437dd7cddfSDavid du Colombier break;
4447dd7cddfSDavid du Colombier }
4457dd7cddfSDavid du Colombier exits(0);
4467dd7cddfSDavid du Colombier }
4473ff48bf5SDavid du Colombier
4483ff48bf5SDavid du Colombier char *order = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
4493ff48bf5SDavid du Colombier
4503ff48bf5SDavid du Colombier void
histogram(long * t,int n,int buckets,long lo,long hi)4513ff48bf5SDavid du Colombier histogram(long *t, int n, int buckets, long lo, long hi)
4523ff48bf5SDavid du Colombier {
4533ff48bf5SDavid du Colombier int i, j, empty;
4543ff48bf5SDavid du Colombier long span;
4553ff48bf5SDavid du Colombier static char *bar;
4563ff48bf5SDavid du Colombier char *p;
4573ff48bf5SDavid du Colombier char x[64];
4583ff48bf5SDavid du Colombier
4593ff48bf5SDavid du Colombier if(bar == nil)
4603ff48bf5SDavid du Colombier bar = malloc(n+1);
4613ff48bf5SDavid du Colombier
4623ff48bf5SDavid du Colombier print("+++++++++++++++++++++++\n");
4633ff48bf5SDavid du Colombier span = (hi-lo)/buckets;
4643ff48bf5SDavid du Colombier span++;
4653ff48bf5SDavid du Colombier empty = 0;
4663ff48bf5SDavid du Colombier for(i = 0; i < buckets; i++){
4673ff48bf5SDavid du Colombier p = bar;
4683ff48bf5SDavid du Colombier for(j = 0; j < n; j++)
4693ff48bf5SDavid du Colombier if(t[j] >= lo+i*span && t[j] <= lo+(i+1)*span)
4703ff48bf5SDavid du Colombier *p++ = order[j];
4713ff48bf5SDavid du Colombier *p = 0;
4723ff48bf5SDavid du Colombier if(p != bar){
4733ff48bf5SDavid du Colombier snprint(x, sizeof x, "[%ld-%ld]", lo+i*span, lo+(i+1)*span);
4743ff48bf5SDavid du Colombier print("%-16s %s\n", x, bar);
4753ff48bf5SDavid du Colombier empty = 0;
4763ff48bf5SDavid du Colombier } else if(!empty){
4773ff48bf5SDavid du Colombier print("...\n");
4783ff48bf5SDavid du Colombier empty = 1;
4793ff48bf5SDavid du Colombier }
4803ff48bf5SDavid du Colombier }
4813ff48bf5SDavid du Colombier print("+++++++++++++++++++++++\n");
4823ff48bf5SDavid du Colombier }
483