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