12
#include <sys/socket.h>
19
#include <mem/misc/pool.h>
21
#include <net/inetdevice.h>
22
#include <net/l3/route.h>
23
#include <net/l3/ipv6.h>
26
#include <net/socket/inet6_sock.h>
28
#include <framework/mod/options.h>
30
#define MODOPS_AMOUNT_INET_SOCK OPTION_GET(NUMBER, amount_inet6_sock)
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;
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 }
42
EMBOX_NET_FAMILY(AF_INET6, inet6_types, ip6_out_ops);
44
static int inet6_init(struct sock *sk) {
45
struct inet6_sock *in6_sk;
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;
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);
61
static int inet6_close(struct sock *sk) {
64
assert(sk->p_ops != NULL);
65
if (sk->p_ops->close == NULL) {
70
return sk->p_ops->close(sk);
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);
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;
85
assert(lhs_sa != NULL);
86
assert(rhs_sa != NULL);
88
lhs_in6 = (const struct sockaddr_in6 *)lhs_sa;
89
rhs_in6 = (const struct sockaddr_in6 *)rhs_sa;
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);
102
static int inet6_bind(struct sock *sk, const struct sockaddr *addr,
104
const struct sockaddr_in6 *addr_in6;
109
if (addrlen != sizeof *addr_in6) {
113
addr_in6 = (const struct sockaddr_in6 *)addr;
114
if (addr_in6->sin6_family != AF_INET6) {
115
return -EAFNOSUPPORT;
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))) {
122
return -EADDRNOTAVAIL;
124
else if (sock_addr_is_busy(sk->p_ops, inet6_addr_tester, addr,
129
__inet6_bind(to_inet6_sock(sk), addr_in6);
134
static int inet6_bind_local(struct sock *sk) {
135
struct sockaddr_in6 addr_in6;
139
addr_in6.sin6_family = AF_INET6;
140
memcpy(&addr_in6.sin6_addr, &in6addr_loopback,
141
sizeof addr_in6.sin6_addr);
143
if (!sock_addr_alloc_port(sk->p_ops, &addr_in6.sin6_port,
144
inet6_addr_tester, (const struct sockaddr *)&addr_in6,
149
__inet6_bind(to_inet6_sock(sk), &addr_in6);
154
static int __inet6_connect(struct inet6_sock *in6_sk,
155
const struct sockaddr_in6 *addr_in6) {
159
assert(in6_sk != NULL);
160
assert(addr_in6 != NULL);
161
assert(addr_in6->sin6_family == AF_INET6);
165
ret = rt_fib_source_ip(addr_in6->sin6_addr.s_addr, &src_ip);
170
if ((in6_sk->src_in6.sin6_addr.s_addr != htonl(INADDR_ANY))
171
&& (in6_sk->src_in6.sin6_addr.s_addr != src_ip)) {
175
in6_sk->src_in6.sin6_addr.s_addr = src_ip;
178
memcpy(&in6_sk->dst_in6, addr_in6, sizeof *addr_in6);
183
static int inet6_stream_connect(struct sock *sk,
184
const struct sockaddr *addr, socklen_t addrlen,
187
const struct sockaddr_in6 *addr_in6;
192
if (addrlen != sizeof *addr_in6) {
196
addr_in6 = (const struct sockaddr_in6 *)addr;
197
if (addr_in6->sin6_family != AF_INET6) {
201
ret = __inet6_connect(to_inet6_sock(sk), addr_in6);
206
assert(sk->p_ops != NULL);
207
if (sk->p_ops->connect == NULL) {
211
return sk->p_ops->connect(sk, addr, addrlen, flags);
214
static int inet6_nonstream_connect(struct sock *sk,
215
const struct sockaddr *addr, socklen_t addrlen,
218
const struct sockaddr_in6 *addr_in6;
223
if (addrlen != sizeof *addr_in6) {
227
addr_in6 = (const struct sockaddr_in6 *)addr;
228
if (addr_in6->sin6_family != AF_INET6) {
232
ret = __inet6_connect(to_inet6_sock(sk), addr_in6);
237
assert(sk->p_ops != NULL);
238
if (sk->p_ops->connect == NULL) {
242
return sk->p_ops->connect(sk, addr, addrlen, flags);
245
static int inet6_listen(struct sock *sk, int backlog) {
247
assert(backlog >= 0);
249
assert(sk->p_ops != NULL);
250
if (sk->p_ops->listen == NULL) {
254
return sk->p_ops->listen(sk, backlog);
257
static int inet6_accept(struct sock *sk, struct sockaddr *addr,
258
socklen_t *addrlen, int flags, struct sock **out_sk) {
260
struct sockaddr_in6 *addr_in6;
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))) {
272
assert(sk->p_ops != NULL);
273
if (sk->p_ops->accept == NULL) {
277
ret = sk->p_ops->accept(sk, addr, addrlen, flags, out_sk);
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;
291
static int inet6_sendmsg(struct sock *sk, struct msghdr *msg,
293
const struct sockaddr_in6 *addr_in6;
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))) {
305
assert(sk->p_ops != NULL);
306
if (sk->p_ops->sendmsg == NULL) {
310
return sk->p_ops->sendmsg(sk, msg, flags);
313
static int inet6_recvmsg(struct sock *sk, struct msghdr *msg,
316
struct sockaddr_in6 *addr_in6;
321
assert(sk->p_ops != NULL);
322
if (sk->p_ops->recvmsg == NULL) {
326
ret = sk->p_ops->recvmsg(sk, msg, flags);
331
if (msg->msg_name != NULL) {
332
if (msg->msg_namelen < sizeof *addr_in6) {
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;
344
static int inet6_getsockname(struct sock *sk,
345
struct sockaddr *addr, socklen_t *addrlen) {
346
struct sockaddr_in6 *addr_in6;
352
if (*addrlen < sizeof *addr_in6) {
356
addr_in6 = (struct sockaddr_in6 *)addr;
357
memcpy(addr_in6, &to_inet6_sock(sk)->src_in6, sizeof *addr_in6);
359
assert((addr_in6->sin6_family == AF_UNSPEC)
360
|| (addr_in6->sin6_family == AF_INET6));
362
addr_in6->sin6_family = AF_INET6;
364
*addrlen = sizeof *addr_in6;
369
static int inet6_getpeername(struct sock *sk,
370
struct sockaddr *addr, socklen_t *addrlen) {
371
struct sockaddr_in6 *addr_in6;
377
if (*addrlen < sizeof *addr_in6) {
381
addr_in6 = (struct sockaddr_in6 *)addr;
382
memcpy(addr_in6, &to_inet6_sock(sk)->dst_in6, sizeof *addr_in6);
384
assert((addr_in6->sin6_family == AF_UNSPEC)
385
|| (addr_in6->sin6_family == AF_INET6));
387
addr_in6->sin6_family = AF_INET6;
389
*addrlen = sizeof *addr_in6;
394
static int inet6_getsockopt(struct sock *sk, int level,
395
int optname, void *optval, socklen_t *optlen) {
399
assert(*optlen >= 0);
401
if (level != IPPROTO_IPV6) {
402
assert(sk->p_ops != NULL);
403
if (sk->p_ops->getsockopt == NULL) {
406
return sk->p_ops->getsockopt(sk, level, optname, optval,
418
static int inet6_setsockopt(struct sock *sk, int level,
419
int optname, const void *optval, socklen_t optlen) {
424
if (level != IPPROTO_IPV6) {
425
assert(sk->p_ops != NULL);
426
if (sk->p_ops->setsockopt == NULL) {
429
return sk->p_ops->setsockopt(sk, level, optname, optval,
441
static int inet6_shutdown(struct sock *sk, int how) {
444
assert(sk->p_ops != NULL);
445
if (sk->p_ops->shutdown == NULL) {
449
return sk->p_ops->shutdown(sk, how);
452
POOL_DEF(inet6_sock_pool, struct inet6_sock, MODOPS_AMOUNT_INET_SOCK);
454
static const struct sock_family_ops inet6_stream_ops = {
456
.close = inet6_close,
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
472
static const struct sock_family_ops inet6_dgram_ops = {
474
.close = inet6_close,
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
490
static const struct sock_family_ops inet6_raw_ops = {
492
.close = inet6_close,
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