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