embox

Форк
0
/
af_inet6.c 
506 строк · 11.2 Кб
1
/**
2
 * @file
3
 * @brief
4
 *
5
 * @date 28.10.13
6
 * @author Ilia Vaprol
7
 */
8

9
#include <errno.h>
10
#include <stddef.h>
11
#include <arpa/inet.h>
12
#include <sys/socket.h>
13
#include <string.h>
14

15

16
#include "family.h"
17
#include "net_sock.h"
18

19
#include <mem/misc/pool.h>
20

21
#include <net/inetdevice.h>
22
#include <net/l3/route.h>
23
#include <net/l3/ipv6.h>
24
#include <net/sock.h>
25

26
#include <net/socket/inet6_sock.h>
27

28
#include <framework/mod/options.h>
29

30
#define MODOPS_AMOUNT_INET_SOCK OPTION_GET(NUMBER, amount_inet6_sock)
31

32
static const struct sock_family_ops inet6_stream_ops;
33
static const struct sock_family_ops inet6_dgram_ops;
34
static const struct sock_family_ops inet6_raw_ops;
35

36
static const struct net_family_type inet6_types[] = {
37
	{ SOCK_STREAM, &inet6_stream_ops },
38
	{ SOCK_DGRAM, &inet6_dgram_ops },
39
	{ SOCK_RAW, &inet6_raw_ops }
40
};
41

42
EMBOX_NET_FAMILY(AF_INET6, inet6_types, ip6_out_ops);
43

44
static int inet6_init(struct sock *sk) {
45
	struct inet6_sock *in6_sk;
46

47
	assert(sk);
48

49
	in6_sk = to_inet6_sock(sk);
50
	memset(&in6_sk->src_in6, 0, sizeof in6_sk->src_in6);
51
	memset(&in6_sk->dst_in6, 0, sizeof in6_sk->dst_in6);
52
	in6_sk->src_in6.sin6_family = in6_sk->dst_in6.sin6_family = AF_UNSPEC;
53

54
	in6_sk->sk.src_addr = (const struct sockaddr *)&in6_sk->src_in6;
55
	in6_sk->sk.dst_addr = (const struct sockaddr *)&in6_sk->dst_in6;
56
	in6_sk->sk.addr_len = sizeof(struct sockaddr_in6);
57

58
	return 0;
59
}
60

61
static int inet6_close(struct sock *sk) {
62
	assert(sk);
63

64
	assert(sk->p_ops != NULL);
65
	if (sk->p_ops->close == NULL) {
66
		sock_release(sk);
67
		return 0;
68
	}
69

70
	return sk->p_ops->close(sk);
71
}
72

73
static void __inet6_bind(struct inet6_sock *in6_sk,
74
		const struct sockaddr_in6 *addr_in6) {
75
	assert(in6_sk != NULL);
76
	assert(addr_in6 != NULL);
77
	assert(addr_in6->sin6_family == AF_INET6);
78
	memcpy(&in6_sk->src_in6, addr_in6, sizeof *addr_in6);
79
}
80

81
static int inet6_addr_tester(const struct sockaddr *lhs_sa,
82
		const struct sockaddr *rhs_sa) {
83
	const struct sockaddr_in6 *lhs_in6, *rhs_in6;
84

85
	assert(lhs_sa != NULL);
86
	assert(rhs_sa != NULL);
87

88
	lhs_in6 = (const struct sockaddr_in6 *)lhs_sa;
89
	rhs_in6 = (const struct sockaddr_in6 *)rhs_sa;
90

91
	assert(lhs_in6->sin6_family == AF_INET6);
92
	return (lhs_in6->sin6_family == rhs_in6->sin6_family)
93
			&& ((0 == memcmp(&lhs_in6->sin6_addr, &rhs_in6->sin6_addr,
94
							sizeof lhs_in6->sin6_addr))
95
					|| (0 == memcmp(&lhs_in6->sin6_addr, &in6addr_any,
96
							sizeof lhs_in6->sin6_addr))
97
					|| (0 == memcmp(&rhs_in6->sin6_addr, &in6addr_any,
98
							sizeof rhs_in6->sin6_addr)))
99
			&& (lhs_in6->sin6_port == rhs_in6->sin6_port);
100
}
101

102
static int inet6_bind(struct sock *sk, const struct sockaddr *addr,
103
		socklen_t addrlen) {
104
	const struct sockaddr_in6 *addr_in6;
105

106
	assert(sk);
107
	assert(addr);
108

109
	if (addrlen != sizeof *addr_in6) {
110
		return -EINVAL;
111
	}
112

113
	addr_in6 = (const struct sockaddr_in6 *)addr;
114
	if (addr_in6->sin6_family != AF_INET6) {
115
		return -EAFNOSUPPORT;
116
	}
117
	else if ((0 != memcmp(&addr_in6->sin6_addr, &in6addr_any,
118
				sizeof addr_in6->sin6_addr))
119
			&& (0 != memcmp(&addr_in6->sin6_addr,
120
				&in6addr_loopback, sizeof addr_in6->sin6_addr))) {
121
		/* FIXME */
122
		return -EADDRNOTAVAIL;
123
	}
124
	else if (sock_addr_is_busy(sk->p_ops, inet6_addr_tester, addr,
125
				addrlen)) {
126
		return -EADDRINUSE;
127
	}
128

129
	__inet6_bind(to_inet6_sock(sk), addr_in6);
130

131
	return 0;
132
}
133

134
static int inet6_bind_local(struct sock *sk) {
135
	struct sockaddr_in6 addr_in6;
136

137
	assert(sk);
138

139
	addr_in6.sin6_family = AF_INET6;
140
	memcpy(&addr_in6.sin6_addr, &in6addr_loopback,
141
			sizeof addr_in6.sin6_addr);
142

143
	if (!sock_addr_alloc_port(sk->p_ops, &addr_in6.sin6_port,
144
				inet6_addr_tester, (const struct sockaddr *)&addr_in6,
145
				sizeof addr_in6)) {
146
		return -ENOMEM;
147
	}
148

149
	__inet6_bind(to_inet6_sock(sk), &addr_in6);
150

151
	return 0;
152
}
153

154
static int __inet6_connect(struct inet6_sock *in6_sk,
155
		const struct sockaddr_in6 *addr_in6) {
156
//	int ret;
157
//	in_addr_t src_ip;
158

159
	assert(in6_sk != NULL);
160
	assert(addr_in6 != NULL);
161
	assert(addr_in6->sin6_family == AF_INET6);
162

163
#if 0
164
	/* FIXME */
165
	ret = rt_fib_source_ip(addr_in6->sin6_addr.s_addr, &src_ip);
166
	if (ret != 0) {
167
		return ret;
168
	}
169

170
	if ((in6_sk->src_in6.sin6_addr.s_addr != htonl(INADDR_ANY))
171
			&& (in6_sk->src_in6.sin6_addr.s_addr != src_ip)) {
172
		return -EINVAL;
173
	}
174

175
	in6_sk->src_in6.sin6_addr.s_addr = src_ip;
176
#endif
177

178
	memcpy(&in6_sk->dst_in6, addr_in6, sizeof *addr_in6);
179

180
	return 0;
181
}
182

183
static int inet6_stream_connect(struct sock *sk,
184
		const struct sockaddr *addr, socklen_t addrlen,
185
		int flags) {
186
	int ret;
187
	const struct sockaddr_in6 *addr_in6;
188

189
	assert(sk);
190
	assert(addr);
191

192
	if (addrlen != sizeof *addr_in6) {
193
		return -EINVAL;
194
	}
195

196
	addr_in6 = (const struct sockaddr_in6 *)addr;
197
	if (addr_in6->sin6_family != AF_INET6) {
198
		return -EINVAL;
199
	}
200

201
	ret = __inet6_connect(to_inet6_sock(sk), addr_in6);
202
	if (ret != 0) {
203
		return ret;
204
	}
205

206
	assert(sk->p_ops != NULL);
207
	if (sk->p_ops->connect == NULL) {
208
		return -EOPNOTSUPP;
209
	}
210

211
	return sk->p_ops->connect(sk, addr, addrlen, flags);
212
}
213

214
static int inet6_nonstream_connect(struct sock *sk,
215
		const struct sockaddr *addr, socklen_t addrlen,
216
		int flags) {
217
	int ret;
218
	const struct sockaddr_in6 *addr_in6;
219

220
	assert(sk);
221
	assert(addr);
222

223
	if (addrlen != sizeof *addr_in6) {
224
		return -EINVAL;
225
	}
226

227
	addr_in6 = (const struct sockaddr_in6 *)addr;
228
	if (addr_in6->sin6_family != AF_INET6) {
229
		return -EINVAL;
230
	}
231

232
	ret = __inet6_connect(to_inet6_sock(sk), addr_in6);
233
	if (ret != 0) {
234
		return ret;
235
	}
236

237
	assert(sk->p_ops != NULL);
238
	if (sk->p_ops->connect == NULL) {
239
		return 0;
240
	}
241

242
	return sk->p_ops->connect(sk, addr, addrlen, flags);
243
}
244

245
static int inet6_listen(struct sock *sk, int backlog) {
246
	assert(sk);
247
	assert(backlog >= 0);
248

249
	assert(sk->p_ops != NULL);
250
	if (sk->p_ops->listen == NULL) {
251
		return -EOPNOTSUPP;
252
	}
253

254
	return sk->p_ops->listen(sk, backlog);
255
}
256

257
static int inet6_accept(struct sock *sk, struct sockaddr *addr,
258
		socklen_t *addrlen, int flags, struct sock **out_sk) {
259
	int ret;
260
	struct sockaddr_in6 *addr_in6;
261

262
	assert(sk);
263
	assert(out_sk);
264

265
	addr_in6 = (struct sockaddr_in6 *)addr;
266
	if (((addr_in6 == NULL) && (addrlen != NULL))
267
			|| ((addr_in6 != NULL) && (addrlen == NULL))
268
			|| ((addrlen != NULL) && (*addrlen < sizeof *addr_in6))) {
269
		return -EINVAL;
270
	}
271

272
	assert(sk->p_ops != NULL);
273
	if (sk->p_ops->accept == NULL) {
274
		return -EOPNOTSUPP;
275
	}
276

277
	ret = sk->p_ops->accept(sk, addr, addrlen, flags, out_sk);
278
	if (ret != 0) {
279
		return ret;
280
	}
281

282
	if (addr_in6 != NULL) {
283
		memcpy(addr_in6, &to_inet6_sock(*out_sk)->dst_in6, sizeof *addr_in6);
284
		assert(addr_in6->sin6_family == AF_INET6);
285
		*addrlen = sizeof *addr_in6;
286
	}
287

288
	return 0;
289
}
290

291
static int inet6_sendmsg(struct sock *sk, struct msghdr *msg,
292
		int flags) {
293
	const struct sockaddr_in6 *addr_in6;
294

295
	assert(sk);
296
	assert(msg);
297

298
	addr_in6 = (const struct sockaddr_in6 *)msg->msg_name;
299
	if ((addr_in6 != NULL) &&
300
			((msg->msg_namelen != sizeof *addr_in6)
301
				|| (addr_in6->sin6_family != AF_INET6))) {
302
		return -EINVAL;
303
	}
304

305
	assert(sk->p_ops != NULL);
306
	if (sk->p_ops->sendmsg == NULL) {
307
		return -EOPNOTSUPP;
308
	}
309

310
	return sk->p_ops->sendmsg(sk, msg, flags);
311
}
312

313
static int inet6_recvmsg(struct sock *sk, struct msghdr *msg,
314
		int flags) {
315
	int ret;
316
	struct sockaddr_in6 *addr_in6;
317

318
	assert(sk);
319
	assert(msg);
320

321
	assert(sk->p_ops != NULL);
322
	if (sk->p_ops->recvmsg == NULL) {
323
		return -EOPNOTSUPP;
324
	}
325

326
	ret = sk->p_ops->recvmsg(sk, msg, flags);
327
	if (ret != 0) {
328
		return ret;
329
	}
330

331
	if (msg->msg_name != NULL) {
332
		if (msg->msg_namelen < sizeof *addr_in6) {
333
			return -EINVAL;
334
		}
335
		addr_in6 = (struct sockaddr_in6 *)msg->msg_name;
336
		memcpy(addr_in6, &to_inet6_sock(sk)->dst_in6, sizeof *addr_in6);
337
		assert(addr_in6->sin6_family == AF_INET6);
338
		msg->msg_namelen = sizeof *addr_in6;
339
	}
340

341
	return 0;
342
}
343

344
static int inet6_getsockname(struct sock *sk,
345
		struct sockaddr *addr, socklen_t *addrlen) {
346
	struct sockaddr_in6 *addr_in6;
347

348
	assert(sk);
349
	assert(addr);
350
	assert(addrlen);
351

352
	if (*addrlen < sizeof *addr_in6) {
353
		return -EINVAL;
354
	}
355

356
	addr_in6 = (struct sockaddr_in6 *)addr;
357
	memcpy(addr_in6, &to_inet6_sock(sk)->src_in6, sizeof *addr_in6);
358
#if 0
359
	assert((addr_in6->sin6_family == AF_UNSPEC)
360
			|| (addr_in6->sin6_family == AF_INET6));
361
#else
362
	addr_in6->sin6_family = AF_INET6;
363
#endif
364
	*addrlen = sizeof *addr_in6;
365

366
	return 0;
367
}
368

369
static int inet6_getpeername(struct sock *sk,
370
		struct sockaddr *addr, socklen_t *addrlen) {
371
	struct sockaddr_in6 *addr_in6;
372

373
	assert(sk);
374
	assert(addr);
375
	assert(addrlen);
376

377
	if (*addrlen < sizeof *addr_in6) {
378
		return -EINVAL;
379
	}
380

381
	addr_in6 = (struct sockaddr_in6 *)addr;
382
	memcpy(addr_in6, &to_inet6_sock(sk)->dst_in6, sizeof *addr_in6);
383
#if 0
384
	assert((addr_in6->sin6_family == AF_UNSPEC)
385
			|| (addr_in6->sin6_family == AF_INET6));
386
#else
387
	addr_in6->sin6_family = AF_INET6;
388
#endif
389
	*addrlen = sizeof *addr_in6;
390

391
	return 0;
392
}
393

394
static int inet6_getsockopt(struct sock *sk, int level,
395
		int optname, void *optval, socklen_t *optlen) {
396
	assert(sk);
397
	assert(optval);
398
	assert(optlen);
399
	assert(*optlen >= 0);
400

401
	if (level != IPPROTO_IPV6) {
402
		assert(sk->p_ops != NULL);
403
		if (sk->p_ops->getsockopt == NULL) {
404
			return -EOPNOTSUPP;
405
		}
406
		return sk->p_ops->getsockopt(sk, level, optname, optval,
407
				optlen);
408
	}
409

410
	switch (optname) {
411
	default:
412
		return -ENOPROTOOPT;
413
	}
414

415
	return 0;
416
}
417

418
static int inet6_setsockopt(struct sock *sk, int level,
419
		int optname, const void *optval, socklen_t optlen) {
420
	assert(sk);
421
	assert(optval);
422
	assert(optlen >= 0);
423

424
	if (level != IPPROTO_IPV6) {
425
		assert(sk->p_ops != NULL);
426
		if (sk->p_ops->setsockopt == NULL) {
427
			return -EOPNOTSUPP;
428
		}
429
		return sk->p_ops->setsockopt(sk, level, optname, optval,
430
				optlen);
431
	}
432

433
	switch (optname) {
434
	default:
435
		return -ENOPROTOOPT;
436
	}
437

438
	return 0;
439
}
440

441
static int inet6_shutdown(struct sock *sk, int how) {
442
	assert(sk);
443

444
	assert(sk->p_ops != NULL);
445
	if (sk->p_ops->shutdown == NULL) {
446
		return -EOPNOTSUPP;
447
	}
448

449
	return sk->p_ops->shutdown(sk, how);
450
}
451

452
POOL_DEF(inet6_sock_pool, struct inet6_sock, MODOPS_AMOUNT_INET_SOCK);
453

454
static const struct sock_family_ops inet6_stream_ops = {
455
	.init        = inet6_init,
456
	.close       = inet6_close,
457
	.bind        = inet6_bind,
458
	.bind_local  = inet6_bind_local,
459
	.connect     = inet6_stream_connect,
460
	.listen      = inet6_listen,
461
	.accept      = inet6_accept,
462
	.sendmsg     = inet6_sendmsg,
463
	.recvmsg     = inet6_recvmsg,
464
	.getsockname = inet6_getsockname,
465
	.getpeername = inet6_getpeername,
466
	.getsockopt  = inet6_getsockopt,
467
	.setsockopt  = inet6_setsockopt,
468
	.shutdown    = inet6_shutdown,
469
	.sock_pool   = &inet6_sock_pool
470
};
471

472
static const struct sock_family_ops inet6_dgram_ops = {
473
	.init        = inet6_init,
474
	.close       = inet6_close,
475
	.bind        = inet6_bind,
476
	.bind_local  = inet6_bind_local,
477
	.connect     = inet6_nonstream_connect,
478
	.listen      = inet6_listen,
479
	.accept      = inet6_accept,
480
	.sendmsg     = inet6_sendmsg,
481
	.recvmsg     = inet6_recvmsg,
482
	.getsockname = inet6_getsockname,
483
	.getpeername = inet6_getpeername,
484
	.getsockopt  = inet6_getsockopt,
485
	.setsockopt  = inet6_setsockopt,
486
	.shutdown    = inet6_shutdown,
487
	.sock_pool   = &inet6_sock_pool
488
};
489

490
static const struct sock_family_ops inet6_raw_ops = {
491
	.init        = inet6_init,
492
	.close       = inet6_close,
493
	.bind        = inet6_bind,
494
	.bind_local  = inet6_bind_local,
495
	.connect     = inet6_nonstream_connect,
496
	.listen      = inet6_listen,
497
	.accept      = inet6_accept,
498
	.sendmsg     = inet6_sendmsg,
499
	.recvmsg     = inet6_recvmsg,
500
	.getsockname = inet6_getsockname,
501
	.getpeername = inet6_getpeername,
502
	.getsockopt  = inet6_getsockopt,
503
	.setsockopt  = inet6_setsockopt,
504
	.shutdown    = inet6_shutdown,
505
	.sock_pool   = &inet6_sock_pool
506
};
507

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.