Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
22
family(unsigned char *addr)
23
{
24
	if(isv4(addr))
25
		return AF_INET;
26
	return AF_INET6;
27
}
28
 
29
static int
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
42
osipinit(void)
43
{
44
	char buf[1024];
45
	gethostname(buf, sizeof(buf));
46
	kstrdup(&sysname, buf);
47
 
48
}
49
 
50
int
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
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
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
128
so_listen(int fd)
129
{
130
	if(listen(fd, 5) < 0)
131
		oserror();
132
}
133
 
134
int
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
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
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*
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
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
274
so_send(int fd, void *d, int n, int f)
275
{
276
	return send(fd, d, n, f);
277
}
278
 
279
int
280
so_recv(int fd, void *d, int n, int f)
281
{
282
	return recv(fd, d, n, f);
283
}