1. do the lookup, and then use the numeric address (arswa on 9fans). great catch. 2. the man page says -6 forces icmp6, make ping follow the man page and add matching -4. Reference: /n/atom/patch/applied/ping6fix Date: Sat Jan 2 02:22:05 CET 2016 Signed-off-by: quanstro@quanstro.net --- /sys/src/cmd/ip/ping.c Sat Jan 2 02:19:57 2016 +++ /sys/src/cmd/ip/ping.c Sat Jan 2 02:19:58 2016 @@ -391,115 +391,71 @@ return colon; } -/* from /sys/src/libc/9sys/dial.c */ - -enum -{ - Maxstring = 128, - Maxpath = 256, -}; - -typedef struct DS DS; -struct DS { - /* dist string */ - char buf[Maxstring]; - char *netdir; - char *proto; - char *rem; - - /* other args */ - char *local; - char *dir; - int *cfdp; -}; - -/* - * parse a dial string - */ -static void -_dial_string_parse(char *str, DS *ds) +char* +nametoip(char *cs, char *name, int *ipver) { - char *p, *p2; + int n,fd; + char buf[128], ip6[128], ip4[128], *p, *addr, *ip; - strncpy(ds->buf, str, Maxstring); - ds->buf[Maxstring-1] = 0; - - p = strchr(ds->buf, '!'); - if(p == 0) { - ds->netdir = 0; - ds->proto = "net"; - ds->rem = ds->buf; - } else { - if(*ds->buf != '/' && *ds->buf != '#'){ - ds->netdir = 0; - ds->proto = ds->buf; - } else { - for(p2 = p; *p2 != '/'; p2--) - ; - *p2++ = 0; - ds->netdir = ds->buf; - ds->proto = p2; - } - *p = 0; - ds->rem = p + 1; + 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; } -} - -/* end excerpt from /sys/src/libc/9sys/dial.c */ -/* side effect: sets network & target */ -static int -isv4name(char *name) -{ - int r = 1; - char *root, *ip, *pr; - DS ds; - - _dial_string_parse(name, &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); + if(cs == nil) + cs = "/net/cs"; + fd = open(cs, ORDWR); + if(fd < 0) + sysfatal("cannot open %s: %r", 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); + +match: + if((*ipver == 4 || *ipver == -1) && ip4[0] != 0){ + *ipver = 4; + return strdup(ip4); + }else if((*ipver == 6 || *ipver == -1) && ip6[0] != 0){ + *ipver = 6; + return strdup(ip6); + }else if(*ipver == 6 && ip4[0] != 0) + return strdup(ip4); + else if(ip4[0] != 0 || ip6[0] != 0) + werrstr("address %s does not match proto %d", ip4[0]? ip4: ip6, *ipver); - /* 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; - - /* 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; + *ipver = -1; + return nil; } void main(int argc, char **argv) { - int fd, msglen, interval, nmsg; + int fd, msglen, interval, nmsg, ipver; char *ds; nsecfd = bintime(-1, nil, nil, nil); @@ -509,9 +465,11 @@ msglen = interval = 0; nmsg = MAXMSG; + ipver = -1; ARGBEGIN { + case '4': case '6': - proto = &v6pr; + ipver = ARGC() - '0'; break; case 'a': addresses = 1; @@ -568,9 +526,12 @@ notify(catch); - if (!isv4name(argv[0])) - proto = &v6pr; - ds = netmkaddr(argv[0], proto->net, "1"); + target = nametoip(nil, argv[0], &ipver); + if(target == nil) + sysfatal("%s: nametoip: %r", argv0); + proto = ipver==4? &v4pr: &v6pr; + + ds = netmkaddr(target, proto->net, "1"); fd = dial(ds, 0, 0, 0); if(fd < 0){ fprint(2, "%s: couldn't dial %s: %r\n", argv0, ds); @@ -583,8 +544,7 @@ 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); --- /sys/man/8/ping Sat Jan 2 02:20:00 2016 +++ /sys/man/8/ping Sat Jan 2 02:20:01 2016 @@ -4,7 +4,7 @@ .SH SYNOPSIS .B ip/ping [ -.B -6aflqr +.B -46aflqr ] [ .B -i .I interval @@ -72,8 +72,12 @@ .PP The options are: .TP +.B 5 +force the use of IPv4's ICMP, and native IP4 addresses. .B 6 -force the use of IPv6's ICMP, +force the use of IPv6's ICMP and +.I prefer +native IP6 addresses, .BR icmpv6 , instead of IPv4's ICMP. .I Ping