xref: /plan9/sys/src/cmd/unix/drawterm/kern/devip-posix.c (revision 58da3067adcdccaaa043d0bfde28ba83b7ced07d)
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <netinet/in.h>
4 #include <netinet/tcp.h>
5 #include <netdb.h>
6 #include <arpa/inet.h>
7 
8 #include "u.h"
9 #include "lib.h"
10 #include "dat.h"
11 #include "fns.h"
12 #include "error.h"
13 #include "ip.h"
14 
15 #include "devip.h"
16 
17 #undef listen
18 #undef accept
19 #undef bind
20 
21 static int
family(unsigned char * addr)22 family(unsigned char *addr)
23 {
24 	if(isv4(addr))
25 		return AF_INET;
26 	return AF_INET6;
27 }
28 
29 static int
addrlen(struct sockaddr_storage * ss)30 addrlen(struct sockaddr_storage *ss)
31 {
32 	switch(ss->ss_family){
33 	case AF_INET:
34 		return sizeof(struct sockaddr_in);
35 	case AF_INET6:
36 		return sizeof(struct sockaddr_in6);
37 	}
38 	return 0;
39 }
40 
41 void
osipinit(void)42 osipinit(void)
43 {
44 	char buf[1024];
45 	gethostname(buf, sizeof(buf));
46 	kstrdup(&sysname, buf);
47 
48 }
49 
50 int
so_socket(int type,unsigned char * addr)51 so_socket(int type, unsigned char *addr)
52 {
53 	int fd, one;
54 
55 	switch(type) {
56 	default:
57 		error("bad protocol type");
58 	case S_TCP:
59 		type = SOCK_STREAM;
60 		break;
61 	case S_UDP:
62 		type = SOCK_DGRAM;
63 		break;
64 	}
65 
66 	fd = socket(family(addr), type, 0);
67 	if(fd < 0)
68 		oserror();
69 
70 	one = 1;
71 	if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0){
72 		oserrstr();
73 		print("setsockopt: %r");
74 	}
75 
76 	return fd;
77 }
78 
79 void
so_connect(int fd,unsigned char * raddr,unsigned short rport)80 so_connect(int fd, unsigned char *raddr, unsigned short rport)
81 {
82 	struct sockaddr_storage ss;
83 
84 	memset(&ss, 0, sizeof(ss));
85 
86 	ss.ss_family = family(raddr);
87 
88 	switch(ss.ss_family){
89 	case AF_INET:
90 		hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport);
91 		v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr);
92 		break;
93 	case AF_INET6:
94 		hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport);
95 		memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr));
96 		break;
97 	}
98 
99 	if(connect(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0)
100 		oserror();
101 }
102 
103 void
so_getsockname(int fd,unsigned char * laddr,unsigned short * lport)104 so_getsockname(int fd, unsigned char *laddr, unsigned short *lport)
105 {
106 	socklen_t len;
107 	struct sockaddr_storage ss;
108 
109 	len = sizeof(ss);
110 	if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0)
111 		oserror();
112 
113 	switch(ss.ss_family){
114 	case AF_INET:
115 		v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
116 		*lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
117 		break;
118 	case AF_INET6:
119 		memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
120 		*lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
121 		break;
122 	default:
123 		error("not AF_INET or AF_INET6");
124 	}
125 }
126 
127 void
so_listen(int fd)128 so_listen(int fd)
129 {
130 	if(listen(fd, 5) < 0)
131 		oserror();
132 }
133 
134 int
so_accept(int fd,unsigned char * raddr,unsigned short * rport)135 so_accept(int fd, unsigned char *raddr, unsigned short *rport)
136 {
137 	int nfd;
138 	socklen_t len;
139 	struct sockaddr_storage ss;
140 
141 	len = sizeof(ss);
142 	nfd = accept(fd, (struct sockaddr*)&ss, &len);
143 	if(nfd < 0)
144 		oserror();
145 
146 	switch(ss.ss_family){
147 	case AF_INET:
148 		v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
149 		*rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
150 		break;
151 	case AF_INET6:
152 		memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
153 		*rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
154 		break;
155 	default:
156 		error("not AF_INET or AF_INET6");
157 	}
158 	return nfd;
159 }
160 
161 void
so_bind(int fd,int su,unsigned short port,unsigned char * addr)162 so_bind(int fd, int su, unsigned short port, unsigned char *addr)
163 {
164 	int i, one;
165 	struct sockaddr_storage ss;
166 
167 	one = 1;
168 	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){
169 		oserrstr();
170 		print("setsockopt: %r");
171 	}
172 
173 	if(su) {
174 		for(i = 600; i < 1024; i++) {
175 			memset(&ss, 0, sizeof(ss));
176 			ss.ss_family = family(addr);
177 
178 			switch(ss.ss_family){
179 			case AF_INET:
180 				((struct sockaddr_in*)&ss)->sin_port = i;
181 				break;
182 			case AF_INET6:
183 				((struct sockaddr_in6*)&ss)->sin6_port = i;
184 				break;
185 			}
186 
187 			if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) >= 0)
188 				return;
189 		}
190 		oserror();
191 	}
192 
193 	memset(&ss, 0, sizeof(ss));
194 	ss.ss_family = family(addr);
195 
196 	switch(ss.ss_family){
197 	case AF_INET:
198 		hnputs(&((struct sockaddr_in*)&ss)->sin_port, port);
199 		break;
200 	case AF_INET6:
201 		hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port);
202 		break;
203 	}
204 
205 	if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0)
206 		oserror();
207 }
208 
209 int
so_gethostbyname(char * host,char ** hostv,int n)210 so_gethostbyname(char *host, char**hostv, int n)
211 {
212 	int i;
213 	char buf[32];
214 	unsigned char *p;
215 	struct hostent *hp;
216 
217 	hp = gethostbyname(host);
218 	if(hp == 0)
219 		return 0;
220 
221 	for(i = 0; hp->h_addr_list[i] && i < n; i++) {
222 		p = (unsigned char*)hp->h_addr_list[i];
223 		sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
224 		hostv[i] = strdup(buf);
225 		if(hostv[i] == 0)
226 			break;
227 	}
228 	return i;
229 }
230 
231 char*
hostlookup(char * host)232 hostlookup(char *host)
233 {
234 	char buf[INET6_ADDRSTRLEN];
235 	uchar *p;
236 	struct hostent *he;
237 	struct addrinfo *result;
238 
239 	he = gethostbyname(host);
240 	if(he != 0 && he->h_addr_list[0]) {
241 		p = (uchar*)he->h_addr_list[0];
242 		sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
243 	} else if(getaddrinfo(host, NULL, NULL, &result) == 0) {
244 		switch (result->ai_family) {
245 		case AF_INET:
246 			inet_ntop(AF_INET, &((struct sockaddr_in*)result->ai_addr)->sin_addr, buf, sizeof(buf));
247 			break;
248 		case AF_INET6:
249 			inet_ntop(AF_INET6, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, buf, sizeof(buf));
250 			break;
251 		default:
252 			return nil;
253 		}
254 	} else
255 		return nil;
256 
257 	return strdup(buf);
258 }
259 
260 int
so_getservbyname(char * service,char * net,char * port)261 so_getservbyname(char *service, char *net, char *port)
262 {
263 	struct servent *s;
264 
265 	s = getservbyname(service, net);
266 	if(s == 0)
267 		return -1;
268 
269 	sprint(port, "%d", nhgets(&s->s_port));
270 	return 0;
271 }
272 
273 int
so_send(int fd,void * d,int n,int f)274 so_send(int fd, void *d, int n, int f)
275 {
276 	return send(fd, d, n, f);
277 }
278 
279 int
so_recv(int fd,void * d,int n,int f)280 so_recv(int fd, void *d, int n, int f)
281 {
282 	return recv(fd, d, n, f);
283 }
284