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