_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 }