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);

Reply via email to