xref: /plan9/sys/src/cmd/unix/drawterm/kern/devip-posix.c (revision 58da3067adcdccaaa043d0bfde28ba83b7ced07d)
18ccd4a63SDavid du Colombier #include <sys/types.h>
28ccd4a63SDavid du Colombier #include <sys/socket.h>
38ccd4a63SDavid du Colombier #include <netinet/in.h>
48ccd4a63SDavid du Colombier #include <netinet/tcp.h>
58ccd4a63SDavid du Colombier #include <netdb.h>
6*58da3067SDavid du Colombier #include <arpa/inet.h>
78ccd4a63SDavid du Colombier 
88ccd4a63SDavid du Colombier #include "u.h"
98ccd4a63SDavid du Colombier #include "lib.h"
108ccd4a63SDavid du Colombier #include "dat.h"
118ccd4a63SDavid du Colombier #include "fns.h"
128ccd4a63SDavid du Colombier #include "error.h"
13*58da3067SDavid du Colombier #include "ip.h"
148ccd4a63SDavid du Colombier 
158ccd4a63SDavid du Colombier #include "devip.h"
168ccd4a63SDavid du Colombier 
178ccd4a63SDavid du Colombier #undef listen
188ccd4a63SDavid du Colombier #undef accept
198ccd4a63SDavid du Colombier #undef bind
208ccd4a63SDavid du Colombier 
21*58da3067SDavid du Colombier static int
family(unsigned char * addr)22*58da3067SDavid du Colombier family(unsigned char *addr)
23*58da3067SDavid du Colombier {
24*58da3067SDavid du Colombier 	if(isv4(addr))
25*58da3067SDavid du Colombier 		return AF_INET;
26*58da3067SDavid du Colombier 	return AF_INET6;
27*58da3067SDavid du Colombier }
28*58da3067SDavid du Colombier 
29*58da3067SDavid du Colombier static int
addrlen(struct sockaddr_storage * ss)30*58da3067SDavid du Colombier addrlen(struct sockaddr_storage *ss)
31*58da3067SDavid du Colombier {
32*58da3067SDavid du Colombier 	switch(ss->ss_family){
33*58da3067SDavid du Colombier 	case AF_INET:
34*58da3067SDavid du Colombier 		return sizeof(struct sockaddr_in);
35*58da3067SDavid du Colombier 	case AF_INET6:
36*58da3067SDavid du Colombier 		return sizeof(struct sockaddr_in6);
37*58da3067SDavid du Colombier 	}
38*58da3067SDavid du Colombier 	return 0;
39*58da3067SDavid du Colombier }
40*58da3067SDavid du Colombier 
418ccd4a63SDavid du Colombier void
osipinit(void)428ccd4a63SDavid du Colombier osipinit(void)
438ccd4a63SDavid du Colombier {
448ccd4a63SDavid du Colombier 	char buf[1024];
458ccd4a63SDavid du Colombier 	gethostname(buf, sizeof(buf));
468ccd4a63SDavid du Colombier 	kstrdup(&sysname, buf);
478ccd4a63SDavid du Colombier 
488ccd4a63SDavid du Colombier }
498ccd4a63SDavid du Colombier 
508ccd4a63SDavid du Colombier int
so_socket(int type,unsigned char * addr)51*58da3067SDavid du Colombier so_socket(int type, unsigned char *addr)
528ccd4a63SDavid du Colombier {
538ccd4a63SDavid du Colombier 	int fd, one;
548ccd4a63SDavid du Colombier 
558ccd4a63SDavid du Colombier 	switch(type) {
568ccd4a63SDavid du Colombier 	default:
578ccd4a63SDavid du Colombier 		error("bad protocol type");
588ccd4a63SDavid du Colombier 	case S_TCP:
598ccd4a63SDavid du Colombier 		type = SOCK_STREAM;
608ccd4a63SDavid du Colombier 		break;
618ccd4a63SDavid du Colombier 	case S_UDP:
628ccd4a63SDavid du Colombier 		type = SOCK_DGRAM;
638ccd4a63SDavid du Colombier 		break;
648ccd4a63SDavid du Colombier 	}
658ccd4a63SDavid du Colombier 
66*58da3067SDavid du Colombier 	fd = socket(family(addr), type, 0);
678ccd4a63SDavid du Colombier 	if(fd < 0)
688ccd4a63SDavid du Colombier 		oserror();
698ccd4a63SDavid du Colombier 
708ccd4a63SDavid du Colombier 	one = 1;
718ccd4a63SDavid du Colombier 	if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0){
728ccd4a63SDavid du Colombier 		oserrstr();
738ccd4a63SDavid du Colombier 		print("setsockopt: %r");
748ccd4a63SDavid du Colombier 	}
758ccd4a63SDavid du Colombier 
768ccd4a63SDavid du Colombier 	return fd;
778ccd4a63SDavid du Colombier }
788ccd4a63SDavid du Colombier 
798ccd4a63SDavid du Colombier void
so_connect(int fd,unsigned char * raddr,unsigned short rport)80*58da3067SDavid du Colombier so_connect(int fd, unsigned char *raddr, unsigned short rport)
818ccd4a63SDavid du Colombier {
82*58da3067SDavid du Colombier 	struct sockaddr_storage ss;
838ccd4a63SDavid du Colombier 
84*58da3067SDavid du Colombier 	memset(&ss, 0, sizeof(ss));
858ccd4a63SDavid du Colombier 
86*58da3067SDavid du Colombier 	ss.ss_family = family(raddr);
87*58da3067SDavid du Colombier 
88*58da3067SDavid du Colombier 	switch(ss.ss_family){
89*58da3067SDavid du Colombier 	case AF_INET:
90*58da3067SDavid du Colombier 		hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport);
91*58da3067SDavid du Colombier 		v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr);
92*58da3067SDavid du Colombier 		break;
93*58da3067SDavid du Colombier 	case AF_INET6:
94*58da3067SDavid du Colombier 		hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport);
95*58da3067SDavid du Colombier 		memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr));
96*58da3067SDavid du Colombier 		break;
97*58da3067SDavid du Colombier 	}
98*58da3067SDavid du Colombier 
99*58da3067SDavid du Colombier 	if(connect(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0)
1008ccd4a63SDavid du Colombier 		oserror();
1018ccd4a63SDavid du Colombier }
1028ccd4a63SDavid du Colombier 
1038ccd4a63SDavid du Colombier void
so_getsockname(int fd,unsigned char * laddr,unsigned short * lport)104*58da3067SDavid du Colombier so_getsockname(int fd, unsigned char *laddr, unsigned short *lport)
1058ccd4a63SDavid du Colombier {
1068ccd4a63SDavid du Colombier 	socklen_t len;
107*58da3067SDavid du Colombier 	struct sockaddr_storage ss;
1088ccd4a63SDavid du Colombier 
109*58da3067SDavid du Colombier 	len = sizeof(ss);
110*58da3067SDavid du Colombier 	if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0)
1118ccd4a63SDavid du Colombier 		oserror();
1128ccd4a63SDavid du Colombier 
113*58da3067SDavid du Colombier 	switch(ss.ss_family){
114*58da3067SDavid du Colombier 	case AF_INET:
115*58da3067SDavid du Colombier 		v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
116*58da3067SDavid du Colombier 		*lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
117*58da3067SDavid du Colombier 		break;
118*58da3067SDavid du Colombier 	case AF_INET6:
119*58da3067SDavid du Colombier 		memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
120*58da3067SDavid du Colombier 		*lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
121*58da3067SDavid du Colombier 		break;
122*58da3067SDavid du Colombier 	default:
123*58da3067SDavid du Colombier 		error("not AF_INET or AF_INET6");
124*58da3067SDavid du Colombier 	}
1258ccd4a63SDavid du Colombier }
1268ccd4a63SDavid du Colombier 
1278ccd4a63SDavid du Colombier void
so_listen(int fd)1288ccd4a63SDavid du Colombier so_listen(int fd)
1298ccd4a63SDavid du Colombier {
1308ccd4a63SDavid du Colombier 	if(listen(fd, 5) < 0)
1318ccd4a63SDavid du Colombier 		oserror();
1328ccd4a63SDavid du Colombier }
1338ccd4a63SDavid du Colombier 
1348ccd4a63SDavid du Colombier int
so_accept(int fd,unsigned char * raddr,unsigned short * rport)135*58da3067SDavid du Colombier so_accept(int fd, unsigned char *raddr, unsigned short *rport)
1368ccd4a63SDavid du Colombier {
1378ccd4a63SDavid du Colombier 	int nfd;
1388ccd4a63SDavid du Colombier 	socklen_t len;
139*58da3067SDavid du Colombier 	struct sockaddr_storage ss;
1408ccd4a63SDavid du Colombier 
141*58da3067SDavid du Colombier 	len = sizeof(ss);
142*58da3067SDavid du Colombier 	nfd = accept(fd, (struct sockaddr*)&ss, &len);
1438ccd4a63SDavid du Colombier 	if(nfd < 0)
1448ccd4a63SDavid du Colombier 		oserror();
1458ccd4a63SDavid du Colombier 
146*58da3067SDavid du Colombier 	switch(ss.ss_family){
147*58da3067SDavid du Colombier 	case AF_INET:
148*58da3067SDavid du Colombier 		v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
149*58da3067SDavid du Colombier 		*rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
150*58da3067SDavid du Colombier 		break;
151*58da3067SDavid du Colombier 	case AF_INET6:
152*58da3067SDavid du Colombier 		memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
153*58da3067SDavid du Colombier 		*rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
154*58da3067SDavid du Colombier 		break;
155*58da3067SDavid du Colombier 	default:
156*58da3067SDavid du Colombier 		error("not AF_INET or AF_INET6");
157*58da3067SDavid du Colombier 	}
1588ccd4a63SDavid du Colombier 	return nfd;
1598ccd4a63SDavid du Colombier }
1608ccd4a63SDavid du Colombier 
1618ccd4a63SDavid du Colombier void
so_bind(int fd,int su,unsigned short port,unsigned char * addr)162*58da3067SDavid du Colombier so_bind(int fd, int su, unsigned short port, unsigned char *addr)
1638ccd4a63SDavid du Colombier {
1648ccd4a63SDavid du Colombier 	int i, one;
165*58da3067SDavid du Colombier 	struct sockaddr_storage ss;
1668ccd4a63SDavid du Colombier 
1678ccd4a63SDavid du Colombier 	one = 1;
1688ccd4a63SDavid du Colombier 	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){
1698ccd4a63SDavid du Colombier 		oserrstr();
1708ccd4a63SDavid du Colombier 		print("setsockopt: %r");
1718ccd4a63SDavid du Colombier 	}
1728ccd4a63SDavid du Colombier 
1738ccd4a63SDavid du Colombier 	if(su) {
1748ccd4a63SDavid du Colombier 		for(i = 600; i < 1024; i++) {
175*58da3067SDavid du Colombier 			memset(&ss, 0, sizeof(ss));
176*58da3067SDavid du Colombier 			ss.ss_family = family(addr);
1778ccd4a63SDavid du Colombier 
178*58da3067SDavid du Colombier 			switch(ss.ss_family){
179*58da3067SDavid du Colombier 			case AF_INET:
180*58da3067SDavid du Colombier 				((struct sockaddr_in*)&ss)->sin_port = i;
181*58da3067SDavid du Colombier 				break;
182*58da3067SDavid du Colombier 			case AF_INET6:
183*58da3067SDavid du Colombier 				((struct sockaddr_in6*)&ss)->sin6_port = i;
184*58da3067SDavid du Colombier 				break;
185*58da3067SDavid du Colombier 			}
186*58da3067SDavid du Colombier 
187*58da3067SDavid du Colombier 			if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) >= 0)
1888ccd4a63SDavid du Colombier 				return;
1898ccd4a63SDavid du Colombier 		}
1908ccd4a63SDavid du Colombier 		oserror();
1918ccd4a63SDavid du Colombier 	}
1928ccd4a63SDavid du Colombier 
193*58da3067SDavid du Colombier 	memset(&ss, 0, sizeof(ss));
194*58da3067SDavid du Colombier 	ss.ss_family = family(addr);
1958ccd4a63SDavid du Colombier 
196*58da3067SDavid du Colombier 	switch(ss.ss_family){
197*58da3067SDavid du Colombier 	case AF_INET:
198*58da3067SDavid du Colombier 		hnputs(&((struct sockaddr_in*)&ss)->sin_port, port);
199*58da3067SDavid du Colombier 		break;
200*58da3067SDavid du Colombier 	case AF_INET6:
201*58da3067SDavid du Colombier 		hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port);
202*58da3067SDavid du Colombier 		break;
203*58da3067SDavid du Colombier 	}
204*58da3067SDavid du Colombier 
205*58da3067SDavid du Colombier 	if(bind(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0)
2068ccd4a63SDavid du Colombier 		oserror();
2078ccd4a63SDavid du Colombier }
2088ccd4a63SDavid du Colombier 
2098ccd4a63SDavid du Colombier int
so_gethostbyname(char * host,char ** hostv,int n)2108ccd4a63SDavid du Colombier so_gethostbyname(char *host, char**hostv, int n)
2118ccd4a63SDavid du Colombier {
2128ccd4a63SDavid du Colombier 	int i;
2138ccd4a63SDavid du Colombier 	char buf[32];
2148ccd4a63SDavid du Colombier 	unsigned char *p;
2158ccd4a63SDavid du Colombier 	struct hostent *hp;
2168ccd4a63SDavid du Colombier 
2178ccd4a63SDavid du Colombier 	hp = gethostbyname(host);
2188ccd4a63SDavid du Colombier 	if(hp == 0)
2198ccd4a63SDavid du Colombier 		return 0;
2208ccd4a63SDavid du Colombier 
2218ccd4a63SDavid du Colombier 	for(i = 0; hp->h_addr_list[i] && i < n; i++) {
2228ccd4a63SDavid du Colombier 		p = (unsigned char*)hp->h_addr_list[i];
2238ccd4a63SDavid du Colombier 		sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
2248ccd4a63SDavid du Colombier 		hostv[i] = strdup(buf);
2258ccd4a63SDavid du Colombier 		if(hostv[i] == 0)
2268ccd4a63SDavid du Colombier 			break;
2278ccd4a63SDavid du Colombier 	}
2288ccd4a63SDavid du Colombier 	return i;
2298ccd4a63SDavid du Colombier }
2308ccd4a63SDavid du Colombier 
2318ccd4a63SDavid du Colombier char*
hostlookup(char * host)2328ccd4a63SDavid du Colombier hostlookup(char *host)
2338ccd4a63SDavid du Colombier {
234*58da3067SDavid du Colombier 	char buf[INET6_ADDRSTRLEN];
2358ccd4a63SDavid du Colombier 	uchar *p;
2368ccd4a63SDavid du Colombier 	struct hostent *he;
237*58da3067SDavid du Colombier 	struct addrinfo *result;
2388ccd4a63SDavid du Colombier 
2398ccd4a63SDavid du Colombier 	he = gethostbyname(host);
2408ccd4a63SDavid du Colombier 	if(he != 0 && he->h_addr_list[0]) {
2418ccd4a63SDavid du Colombier 		p = (uchar*)he->h_addr_list[0];
2428ccd4a63SDavid du Colombier 		sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
243*58da3067SDavid du Colombier 	} else if(getaddrinfo(host, NULL, NULL, &result) == 0) {
244*58da3067SDavid du Colombier 		switch (result->ai_family) {
245*58da3067SDavid du Colombier 		case AF_INET:
246*58da3067SDavid du Colombier 			inet_ntop(AF_INET, &((struct sockaddr_in*)result->ai_addr)->sin_addr, buf, sizeof(buf));
247*58da3067SDavid du Colombier 			break;
248*58da3067SDavid du Colombier 		case AF_INET6:
249*58da3067SDavid du Colombier 			inet_ntop(AF_INET6, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, buf, sizeof(buf));
250*58da3067SDavid du Colombier 			break;
251*58da3067SDavid du Colombier 		default:
252*58da3067SDavid du Colombier 			return nil;
253*58da3067SDavid du Colombier 		}
2548ccd4a63SDavid du Colombier 	} else
255*58da3067SDavid du Colombier 		return nil;
2568ccd4a63SDavid du Colombier 
2578ccd4a63SDavid du Colombier 	return strdup(buf);
2588ccd4a63SDavid du Colombier }
2598ccd4a63SDavid du Colombier 
2608ccd4a63SDavid du Colombier int
so_getservbyname(char * service,char * net,char * port)2618ccd4a63SDavid du Colombier so_getservbyname(char *service, char *net, char *port)
2628ccd4a63SDavid du Colombier {
2638ccd4a63SDavid du Colombier 	struct servent *s;
2648ccd4a63SDavid du Colombier 
2658ccd4a63SDavid du Colombier 	s = getservbyname(service, net);
2668ccd4a63SDavid du Colombier 	if(s == 0)
2678ccd4a63SDavid du Colombier 		return -1;
2688ccd4a63SDavid du Colombier 
2698ccd4a63SDavid du Colombier 	sprint(port, "%d", nhgets(&s->s_port));
2708ccd4a63SDavid du Colombier 	return 0;
2718ccd4a63SDavid du Colombier }
2728ccd4a63SDavid du Colombier 
2738ccd4a63SDavid du Colombier int
so_send(int fd,void * d,int n,int f)2748ccd4a63SDavid du Colombier so_send(int fd, void *d, int n, int f)
2758ccd4a63SDavid du Colombier {
2768ccd4a63SDavid du Colombier 	return send(fd, d, n, f);
2778ccd4a63SDavid du Colombier }
2788ccd4a63SDavid du Colombier 
2798ccd4a63SDavid du Colombier int
so_recv(int fd,void * d,int n,int f)2808ccd4a63SDavid du Colombier so_recv(int fd, void *d, int n, int f)
2818ccd4a63SDavid du Colombier {
2828ccd4a63SDavid du Colombier 	return recv(fd, d, n, f);
2838ccd4a63SDavid du Colombier }
284