_p9dialparse.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
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 *p… | |
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,… | |
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 fi… | |
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… | |
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 } |