From mboxrd@z Thu Jan 1 00:00:00 1970 From: erik quanstrom Date: Sun, 3 Jan 2016 17:31:41 -0800 To: arisawa@ar.aichi-u.ac.jp, 9fans@9fans.net Message-ID: <703dcf90537aeb1ea61012d823f833e5@mule> In-Reply-To: <2F96B09F-7524-473A-B883-9A7B7DD09978@ar.aichi-u.ac.jp> References: <4AE7714E-C18F-4897-ACC1-4F8D35C858AE@ar.aichi-u.ac.jp> <2F96B09F-7524-473A-B883-9A7B7DD09978@ar.aichi-u.ac.jp> MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit Subject: Re: [9fans] bug or feature ? --- ip/ping -6 Topicbox-Message-UUID: 7e047954-ead9-11e9-9d60-3106f5b1d025 unfortunately, the simlification removes the code that solves an important use case. it's important to be able to specify the protocol or network stack, such as in ip/ping /net.alt/icmp!someaddress the diff is here and i'll be working on a patch. the basic idea is to translate only the dns names to ip addresses, and then reassemble the string. this way we can keep any decorations such as /net.alt/icmpv6!... - erik --- lilly; diff -c `{yesterday -n20 /sys/src/cmd/ip/ping.c} /sys/src/cmd/ip/ping.c /n/dump/2015/1214/sys/src/cmd/ip/ping.c:28,34 - /sys/src/cmd/ip/ping.c:28,34 typedef struct { int version; - char *net; + char *protoname; int echocmd; int echoreply; unsigned iphdrsz; /n/dump/2015/1214/sys/src/cmd/ip/ping.c:393,398 - /sys/src/cmd/ip/ping.c:393,401 /* from /sys/src/libc/9sys/dial.c */ + static char defnet[] = "/net"; + static char defproto[] = "icmp"; + enum { Maxstring = 128, /n/dump/2015/1214/sys/src/cmd/ip/ping.c:406,416 - /sys/src/cmd/ip/ping.c:409,414 char *netdir; char *proto; char *rem; - - /* other args */ - char *local; - char *dir; - int *cfdp; }; /* /n/dump/2015/1214/sys/src/cmd/ip/ping.c:417,423 - /sys/src/cmd/ip/ping.c:415,421 * parse a dial string */ static void - _dial_string_parse(char *str, DS *ds) + dsparse(char *str, char *defproto, DS *ds) { char *p, *p2; /n/dump/2015/1214/sys/src/cmd/ip/ping.c:425,437 - /sys/src/cmd/ip/ping.c:423,435 ds->buf[Maxstring-1] = 0; p = strchr(ds->buf, '!'); - if(p == 0) { - ds->netdir = 0; - ds->proto = "net"; + if(p == nil) { + ds->netdir = nil; + ds->proto = defproto; ds->rem = ds->buf; } else { if(*ds->buf != '/' && *ds->buf != '#'){ - ds->netdir = 0; + ds->netdir = nil; ds->proto = ds->buf; } else { for(p2 = p; *p2 != '/'; p2--) /n/dump/2015/1214/sys/src/cmd/ip/ping.c:443,506 - /sys/src/cmd/ip/ping.c:441,560 *p = 0; ds->rem = p + 1; } + if(ds->netdir == nil || ds->netdir[0] == 0) + ds->netdir = defnet; } /* end excerpt from /sys/src/libc/9sys/dial.c */ - /* side effect: sets network & target */ - static int - isv4name(char *name) + char* + dstopretty(DS *ds, char *name) { - int r = 1; - char *root, *ip, *pr; + char *port; + + port = strchr(ds->rem, '!'); + if(port == nil) + port = ""; + + if(ds->netdir == defnet) + return smprint("%s!%s%s", ds->proto, name, port); + else + return smprint("%s/%s!%s%s", ds->netdir, ds->proto, name, port); + } + + char* + nametoip(char *name0, int *ipver, char **target, char **pretty) + { + int n,fd; + char buf[128], ip6[128], ip4[128], *cs, *s, *p, *name, *addr, *ip; DS ds; - _dial_string_parse(name, &ds); + *target = nil; + dsparse(name0, defproto, &ds); - /* cope with leading /net.alt/icmp! and the like */ - root = nil; - if (ds.netdir != nil) { - pr = strrchr(ds.netdir, '/'); - if (pr == nil) - pr = ds.netdir; - else { - *pr++ = '\0'; - root = ds.netdir; - network = strdup(root); + /* do not override protocol specified */ + if(*ipver == -1 && ds.proto != defproto){ + if(strcmp(ds.proto, v4pr.protoname) == 0) + *ipver = 4; + else if (strcmp(ds.proto, v6pr.protoname) == 0) + *ipver = 6; + } + + name = ds.rem; + ip6[0] = 0; + ip4[0] = 0; + if(isdottedquad(name)){ + snprint(ip4, sizeof ip4, "%s", name); + goto match; + } + if(isv6lit(name)){ + snprint(ip6, sizeof ip6, "%s", name); + goto match; + } + + + cs = smprint("%s/cs", ds.netdir); + fd = open(cs, ORDWR); + if(fd < 0) + sysfatal("cannot open %s: %r", cs); + free(cs); + + addr = smprint("tcp!%s!1", name); + if(write(fd, addr, strlen(addr)) != strlen(addr)){ + close(fd); + sysfatal("cannot write %s to %s: %r", addr, cs); + } + free(addr); + seek(fd, 0, 0); + while((n = read(fd, buf, sizeof(buf)-1)) > 0){ + buf[n] = 0; + ip = strchr(buf,' '); + ip++; + p = strchr(ip,'!'); + *p = 0; + if(isdottedquad(ip)){ + if(ip4[0] == 0) + snprint(ip4, sizeof ip4, "%s", ip); + }else if(isv6lit(ip)){ + if(ip6[0] == 0) + snprint(ip6, sizeof ip6, "%s", ip); } - if (strcmp(pr, v4pr.net) == 0) - return 1; - if (strcmp(pr, v6pr.net) == 0) - return 0; } + close(fd); - /* if it's a literal, it's obvious from syntax which proto it is */ - free(target); - target = strdup(ds.rem); - if (isdottedquad(ds.rem)) - return 1; - else if (isv6lit(ds.rem)) - return 0; + match: + s = nil; + if((*ipver == 4 || *ipver == -1) && ip4[0] != 0){ + *ipver = 4; + s = ip4; + }else if((*ipver == 6 || *ipver == -1) && ip6[0] != 0){ + *ipver = 6; + s = ip6; + }else if(*ipver == 6 && ip4[0] != 0) + s = ip4; + else if(ip4[0] != 0 || ip6[0] != 0) + werrstr("address %s does not match proto %d", ip4[0]? ip4: ip6, *ipver); - /* map name to ip and look at its syntax */ - ip = csgetvalue(root, "sys", ds.rem, "ip", nil); - if (ip == nil) - ip = csgetvalue(root, "dom", ds.rem, "ip", nil); - if (ip == nil) - ip = csgetvalue(root, "sys", ds.rem, "ipv6", nil); - if (ip == nil) - ip = csgetvalue(root, "dom", ds.rem, "ipv6", nil); - if (ip != nil) - r = isv4name(ip); - free(ip); - return r; + if(s == nil || *ipver == -1){ + *ipver = -1; + return nil; + } + + /* fixup protocol if never specified */ + if(*ipver == 6 && ds.proto == defproto) + ds.proto = v6pr.protoname; + + *pretty = dstopretty(&ds, s); + + *target = smprint("%s/%s!%s", ds.netdir, ds.proto, s); + return netmkaddr(*target, ds.netdir, "1"); } void main(int argc, char **argv) { - int fd, msglen, interval, nmsg; - char *ds; + int fd, msglen, interval, nmsg, ipver; + char *ds, *pretty; nsecfd = bintime(-1, nil, nil, nil); /n/dump/2015/1214/sys/src/cmd/ip/ping.c:509,517 - /sys/src/cmd/ip/ping.c:563,573 msglen = interval = 0; nmsg = MAXMSG; + ipver = -1; ARGBEGIN { + case '4': case '6': - proto = &v6pr; + ipver = ARGC() - '0'; break; case 'a': addresses = 1; /n/dump/2015/1214/sys/src/cmd/ip/ping.c:568,576 - /sys/src/cmd/ip/ping.c:624,636 notify(catch); - if (!isv4name(argv[0])) - proto = &v6pr; - ds = netmkaddr(argv[0], proto->net, "1"); + ds = nametoip(argv[0], &ipver, &target, &pretty); + if(ds == nil) + sysfatal("%s: nametoip: %r", argv0); + proto = ipver==4? &v4pr: &v6pr; + + if(0)fprint(2, "ds %s\n", ds); + fd = dial(ds, 0, 0, 0); if(fd < 0){ fprint(2, "%s: couldn't dial %s: %r\n", argv0, ds); /n/dump/2015/1214/sys/src/cmd/ip/ping.c:579,590 - /sys/src/cmd/ip/ping.c:639,650 if (!quiet) print("sending %d %d byte messages %d ms apart to %s\n", - nmsg, msglen, interval, ds); + nmsg, msglen, interval, pretty); + free(pretty); switch(rfork(RFPROC|RFMEM|RFFDG)){ case -1: - fprint(2, "%s: can't fork: %r\n", argv0); - /* fallthrough */ + sysfatal("%s: can't fork: %r\n", argv0); case 0: rcvr(fd, msglen, interval, nmsg); exits(0);