_p9dialparse.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       _p9dialparse.c (3441B)
       ---
            1 #include <u.h>
            2 #define NOPLAN9DEFINES
            3 #include <libc.h>
            4 
            5 #include <sys/types.h>
            6 #include <netdb.h>
            7 #include <sys/un.h>
            8 #include <netinet/in.h>
            9 
           10 static char *nets[] = { "tcp", "udp", nil };
           11 #define CLASS(p) ((*(uchar*)(p))>>6)
           12 
           13 static struct {
           14         char *net;
           15         char *service;
           16         int port;
           17 } porttbl[] = {
           18         "tcp",        "9fs",        564,
           19         "tcp",        "whoami",        565,
           20         "tcp",        "guard",        566,
           21         "tcp",        "ticket",        567,
           22         "tcp",        "exportfs",        17007,
           23         "tcp",        "rexexec",        17009,
           24         "tcp",        "ncpu",        17010,
           25         "tcp",        "cpu",        17013,
           26         "tcp",        "venti",        17034,
           27         "tcp",        "wiki",        17035,
           28         "tcp",        "secstore",        5356,
           29         "udp",        "dns",        53,
           30         "tcp",        "dns",        53,
           31 };
           32 
           33 static int
           34 parseip(char *host, u32int *pip)
           35 {
           36         uchar addr[4];
           37         int x, i;
           38         char *p;
           39 
           40         p = host;
           41         for(i=0; i<4 && *p; i++){
           42                 x = strtoul(p, &p, 0);
           43                 if(x < 0 || x >= 256)
           44                         return -1;
           45                 if(*p != '.' && *p != 0)
           46                         return -1;
           47                 if(*p == '.')
           48                         p++;
           49                 addr[i] = x;
           50         }
           51 
           52         switch(CLASS(addr)){
           53         case 0:
           54         case 1:
           55                 if(i == 3){
           56                         addr[3] = addr[2];
           57                         addr[2] = addr[1];
           58                         addr[1] = 0;
           59                 }else if(i == 2){
           60                         addr[3] = addr[1];
           61                         addr[2] = 0;
           62                         addr[1] = 0;
           63                 }else if(i != 4)
           64                         return -1;
           65                 break;
           66         case 2:
           67                 if(i == 3){
           68                         addr[3] = addr[2];
           69                         addr[2] = 0;
           70                 }else if(i != 4)
           71                         return -1;
           72                 break;
           73         }
           74         memmove(pip, addr, 4);
           75         return 0;
           76 }
           77 
           78 int
           79 p9dialparse(char *addr, char **pnet, char **punix, u32int *phost, int *pport)
           80 {
           81         char *net, *host, *port, *e;
           82         int i;
           83         struct servent *se;
           84         struct hostent *he;
           85         struct sockaddr_un *sockun;
           86 
           87         *punix = nil;
           88         net = addr;
           89         if((host = strchr(net, '!')) == nil){
           90                 werrstr("malformed address");
           91                 return -1;
           92         }
           93         *host++ = 0;
           94         if((port = strchr(host, '!')) == nil){
           95                 if(strcmp(net, "unix")==0 || strcmp(net, "net")==0){
           96                 Unix:
           97                         if(strlen(host)+1 > sizeof sockun->sun_path){
           98                                 werrstr("unix socket name too long");
           99                                 return -1;
          100                         }
          101                         *punix = host;
          102                         *pnet = "unix";
          103                         *phost = 0;
          104                         *pport = 0;
          105                         return 0;
          106                 }
          107                 werrstr("malformed address");
          108                 return -1;
          109         }
          110         *port++ = 0;
          111 
          112         if(*host == 0){
          113                 werrstr("malformed address (empty host)");
          114                 return -1;
          115         }
          116         if(*port == 0){
          117                 werrstr("malformed address (empty port)");
          118                 return -1;
          119         }
          120 
          121         if(strcmp(net, "unix") == 0)
          122                 goto Unix;
          123 
          124         if(strcmp(net, "tcp")!=0 && strcmp(net, "udp")!=0 && strcmp(net, "net") != 0){
          125                 werrstr("bad network %s!%s!%s", net, host, port);
          126                 return -1;
          127         }
          128 
          129         /* translate host */
          130         if(strcmp(host, "*") == 0)
          131                 *phost = 0;
          132         else if(parseip(host, phost) == 0)
          133                 {}
          134         else if((he = gethostbyname(host)) != nil)
          135                 *phost = *(u32int*)(he->h_addr);
          136         else{
          137                 werrstr("unknown host %s", host);
          138                 return -1;
          139         }
          140 
          141         /* translate network and port; should return list rather than first */
          142         if(strcmp(net, "net") == 0){
          143                 for(i=0; nets[i]; i++){
          144                         if((se = getservbyname(port, nets[i])) != nil){
          145                                 *pnet = nets[i];
          146                                 *pport = ntohs(se->s_port);
          147                                 return 0;
          148                         }
          149                 }
          150         }
          151 
          152         for(i=0; i<nelem(porttbl); i++){
          153                 if(strcmp(net, "net") == 0 || strcmp(porttbl[i].net, net) == 0)
          154                 if(strcmp(porttbl[i].service, port) == 0){
          155                         *pnet = porttbl[i].net;
          156                         *pport = porttbl[i].port;
          157                         return 0;
          158                 }
          159         }
          160 
          161         if(strcmp(net, "net") == 0){
          162                 werrstr("unknown service net!*!%s", port);
          163                 return -1;
          164         }
          165 
          166         if(strcmp(net, "tcp") != 0 && strcmp(net, "udp") != 0){
          167                 werrstr("unknown network %s", net);
          168                 return -1;
          169         }
          170 
          171         *pnet = net;
          172         i = strtol(port, &e, 0);
          173         if(*e == 0){
          174                 *pport = i;
          175                 return 0;
          176         }
          177 
          178         if((se = getservbyname(port, net)) != nil){
          179                 *pport = ntohs(se->s_port);
          180                 return 0;
          181         }
          182         werrstr("unknown service %s!*!%s", net, port);
          183         return -1;
          184 }