embox

Форк
0
/
af_inet.c 
581 строка · 13.0 Кб
1
/**
2
 * @file
3
 * @brief PF_INET protocol family socket handler.
4
 *
5
 * @date 01.12.09
6
 * @author Nikolay Korotky
7
 * @author Ilia Vaprol
8
 */
9

10
#include <errno.h>
11

12
#include <stddef.h>
13
#include <arpa/inet.h>
14
#include <sys/socket.h>
15
#include <string.h>
16
#include <netinet/in.h>
17

18
#include <net/sock.h>
19
#include <net/inetdevice.h>
20

21
#include "family.h"
22
#include "net_sock.h"
23

24
#include <mem/misc/pool.h>
25

26
#include <net/l3/route.h>
27
#include <net/l3/ipv4/ip.h>
28

29
#include <net/socket/inet_sock.h>
30
#include <framework/mod/options.h>
31

32
#define MODOPS_AMOUNT_INET_SOCK OPTION_GET(NUMBER, amount_inet_sock)
33

34
static const struct sock_family_ops inet_stream_ops;
35
static const struct sock_family_ops inet_dgram_ops;
36
static const struct sock_family_ops inet_raw_ops;
37

38
static const struct net_family_type inet_types[] = {
39
	{ SOCK_STREAM, &inet_stream_ops },
40
	{ SOCK_DGRAM, &inet_dgram_ops },
41
	{ SOCK_RAW, &inet_raw_ops }
42
};
43

44
EMBOX_NET_FAMILY(AF_INET, inet_types, ip_out_ops);
45

46
static int inet_init(struct sock *sk) {
47
	struct inet_sock *in_sk;
48

49
	assert(sk);
50

51
	in_sk = to_inet_sock(sk);
52
	in_sk->id = 0;
53
	in_sk->uc_ttl = -1;
54
	memset(&in_sk->src_in, 0, sizeof in_sk->src_in);
55
	memset(&in_sk->dst_in, 0, sizeof in_sk->dst_in);
56
	in_sk->src_in.sin_family = in_sk->dst_in.sin_family = AF_INET;
57

58
	in_sk->sk.src_addr = (const struct sockaddr *)&in_sk->src_in;
59
	in_sk->sk.dst_addr = (const struct sockaddr *)&in_sk->dst_in;
60
	in_sk->sk.addr_len = sizeof(struct sockaddr_in);
61
	memset(&in_sk->opt, 0, sizeof in_sk->opt);
62

63
	return 0;
64
}
65

66
static int inet_close(struct sock *sk) {
67
	assert(sk);
68

69
	assert(sk->p_ops != NULL);
70
	if (sk->p_ops->close == NULL) {
71
		sock_release(sk);
72
		return 0;
73
	}
74

75
	return sk->p_ops->close(sk);
76
}
77

78
static void __inet_bind(struct inet_sock *in_sk,
79
		const struct sockaddr_in *addr_in) {
80
	assert(in_sk != NULL);
81
	assert(addr_in != NULL);
82
	assert(addr_in->sin_family == AF_INET);
83
	memcpy(&in_sk->src_in, addr_in, sizeof *addr_in);
84
}
85

86
static int inet_addr_tester(const struct sockaddr *lhs_sa,
87
		const struct sockaddr *rhs_sa) {
88
	static const struct in_addr inaddr_any = {
89
		{ .s_addr = htonl(INADDR_ANY) }
90
	};
91
	const struct sockaddr_in *lhs_in, *rhs_in;
92

93
	assert(lhs_sa != NULL);
94
	assert(rhs_sa != NULL);
95

96
	lhs_in = (const struct sockaddr_in *)lhs_sa;
97
	rhs_in = (const struct sockaddr_in *)rhs_sa;
98

99
	assert(lhs_in->sin_family == AF_INET);
100
	return (lhs_in->sin_family == rhs_in->sin_family)
101
			&& ((0 == memcmp(&lhs_in->sin_addr, &rhs_in->sin_addr,
102
							sizeof lhs_in->sin_addr))
103
					|| (0 == memcmp(&lhs_in->sin_addr, &inaddr_any,
104
							sizeof lhs_in->sin_addr))
105
					|| (0 == memcmp(&rhs_in->sin_addr, &inaddr_any,
106
							sizeof rhs_in->sin_addr)))
107
			&& (lhs_in->sin_port == rhs_in->sin_port);
108
}
109
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
110
int sock_addr_is_busy_net_ns(const struct sock_proto_ops *p_ops,
111
		sock_addr_tester_ft tester, const struct sockaddr *addr,
112
		socklen_t addrlen, struct sock *src_sk) {
113
	const struct sock *sk;
114

115
	assert(p_ops != NULL);
116
	assert(tester != NULL);
117

118
	sock_foreach(sk, p_ops) {
119
		if (!cmp_net_ns(src_sk->net_ns, sk->net_ns)) {
120
			continue;
121
		}
122
		if ((sk->addr_len == addrlen)
123
				&& tester(addr, sk->src_addr)) {
124
			return 1;
125
		}
126
	}
127

128
	return 0;
129
}
130
#endif
131

132
static int inet_bind(struct sock *sk, const struct sockaddr *addr,
133
		socklen_t addrlen) {
134
	struct sockaddr_in addr_in;
135

136
	assert(sk);
137
	assert(addr);
138

139
	if (addrlen != sizeof addr_in) {
140
		return -EINVAL;
141
	}
142

143
	memcpy(&addr_in, addr, sizeof addr_in);
144

145
	if (addr_in.sin_family != AF_INET) {
146
		return -EAFNOSUPPORT;
147
	}
148
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
149
	else if ((addr_in.sin_addr.s_addr != htonl(INADDR_ANY)) &&
150
			!ip_is_local_net_ns(addr_in.sin_addr.s_addr,
151
								IP_LOCAL_BROADCAST | IP_LOCAL_MULTICAST,
152
								sk->net_ns)) {
153
		return -EADDRNOTAVAIL;
154
	}
155
#else
156
	else if ((addr_in.sin_addr.s_addr != htonl(INADDR_ANY)) &&
157
			!ip_is_local(addr_in.sin_addr.s_addr, IP_LOCAL_BROADCAST | IP_LOCAL_MULTICAST)) {
158
		return -EADDRNOTAVAIL;
159
	}
160
#endif
161

162
	if (addr_in.sin_port == 0) {
163
		/* Allocation of an ephemeral port, when the port number in a socket address is specified as 0,
164
		 * is not POSIX-specified behavior, but it used in Linux, BSD, Windows.
165
		 * E.g. manual for Linux - http://man7.org/linux/man-pages/man7/ip.7.html */
166
		if (!sock_addr_alloc_port(sk->p_ops, &addr_in.sin_port,
167
					inet_addr_tester, (const struct sockaddr *)&addr_in,
168
					sizeof addr_in)) {
169
			return -ENOMEM;
170
		}
171
	}
172
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
173
	else if (sock_addr_is_busy_net_ns(sk->p_ops, inet_addr_tester, (struct sockaddr *)&addr_in,
174
				addrlen, sk)) {
175
		/* TODO consider opt.so_reuseaddr */
176
		return -EADDRINUSE;
177
	}
178
#else
179
	else if (sock_addr_is_busy(sk->p_ops, inet_addr_tester, (struct sockaddr *)&addr_in,
180
			addrlen)) {
181
		/* TODO consider opt.so_reuseaddr */
182
		return -EADDRINUSE;
183
	}
184
#endif
185
	__inet_bind(to_inet_sock(sk), &addr_in);
186

187
	return 0;
188
}
189

190
static int inet_bind_local(struct sock *sk) {
191
	struct sockaddr_in addr_in;
192

193
	assert(sk);
194

195
	memset(&addr_in, 0, sizeof addr_in);
196

197
	addr_in.sin_family = AF_INET;
198
	addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
199

200
	if (!sock_addr_alloc_port(sk->p_ops, &addr_in.sin_port,
201
				inet_addr_tester, (const struct sockaddr *)&addr_in,
202
				sizeof addr_in)) {
203
		return -ENOMEM;
204
	}
205

206
	__inet_bind(to_inet_sock(sk), &addr_in);
207

208
	return 0;
209
}
210

211
static int __inet_connect(struct inet_sock *in_sk,
212
		const struct sockaddr_in *addr_in) {
213
	int ret;
214
	in_addr_t src_ip;
215

216
	assert(in_sk != NULL);
217
	assert(addr_in != NULL);
218
	assert(addr_in->sin_family == AF_INET);
219

220
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
221
	ret = rt_fib_source_ip_net_ns(addr_in->sin_addr.s_addr, NULL, &src_ip,
222
				((struct sock *)in_sk)->net_ns);
223
#else
224
	ret = rt_fib_source_ip(addr_in->sin_addr.s_addr, NULL, &src_ip);
225
#endif
226

227
	if (ret != 0) {
228
		return ret;
229
	}
230

231
	if ((in_sk->src_in.sin_addr.s_addr != htonl(INADDR_ANY))
232
			&& (in_sk->src_in.sin_addr.s_addr != src_ip)) {
233
		return -EINVAL;
234
	}
235

236
	in_sk->src_in.sin_addr.s_addr = src_ip;
237

238
	memcpy(&in_sk->dst_in, addr_in, sizeof *addr_in);
239

240
	return 0;
241
}
242

243
static int inet_stream_connect(struct sock *sk,
244
		const struct sockaddr *addr, socklen_t addrlen,
245
		int flags) {
246
	int ret;
247
	const struct sockaddr_in *addr_in;
248

249
	assert(sk);
250
	assert(addr);
251

252
	if (addrlen != sizeof *addr_in) {
253
		return -EINVAL;
254
	}
255

256
	addr_in = (const struct sockaddr_in *)addr;
257
	if (addr_in->sin_family != AF_INET) {
258
		return -EINVAL;
259
	}
260

261
	ret = __inet_connect(to_inet_sock(sk), addr_in);
262
	if (ret != 0) {
263
		return ret;
264
	}
265

266
	assert(sk->p_ops != NULL);
267
	if (sk->p_ops->connect == NULL) {
268
		return -EOPNOTSUPP;
269
	}
270

271
	return sk->p_ops->connect(sk, addr, addrlen, flags);
272
}
273

274
static int inet_nonstream_connect(struct sock *sk,
275
		const struct sockaddr *addr, socklen_t addrlen,
276
		int flags) {
277
	int ret;
278
	const struct sockaddr_in *addr_in;
279

280
	assert(sk);
281
	assert(addr);
282

283
	if (addrlen != sizeof *addr_in) {
284
		return -EINVAL;
285
	}
286

287
	addr_in = (const struct sockaddr_in *)addr;
288
	if (addr_in->sin_family != AF_INET) {
289
		return -EINVAL;
290
	}
291

292
	ret = __inet_connect(to_inet_sock(sk), addr_in);
293
	if (ret != 0) {
294
		return ret;
295
	}
296

297
	assert(sk->p_ops != NULL);
298
	if (sk->p_ops->connect == NULL) {
299
		return 0;
300
	}
301

302
	return sk->p_ops->connect(sk, addr, addrlen, flags);
303
}
304

305
static int inet_listen(struct sock *sk, int backlog) {
306
	assert(sk);
307
	assert(backlog >= 0);
308

309
	assert(sk->p_ops != NULL);
310
	if (sk->p_ops->listen == NULL) {
311
		return -EOPNOTSUPP;
312
	}
313

314
	return sk->p_ops->listen(sk, backlog);
315
}
316

317
static int inet_accept(struct sock *sk, struct sockaddr *addr,
318
		socklen_t *addrlen, int flags, struct sock **out_sk) {
319
	int ret;
320
	struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
321

322
	assert(sk);
323
	assert(out_sk);
324
	assert(addr || !addrlen);
325
	assert(!addr || addrlen);
326

327
	if (addrlen != NULL && *addrlen < sizeof *addr_in) {
328
		return -EINVAL;
329
	}
330

331
	assert(sk->p_ops != NULL);
332
	if (sk->p_ops->accept == NULL) {
333
		return -EOPNOTSUPP;
334
	}
335

336
	ret = sk->p_ops->accept(sk, addr, addrlen, flags, out_sk);
337
	if (ret != 0) {
338
		return ret;
339
	}
340

341
	if (addr_in != NULL) {
342
		memcpy(addr_in, &to_inet_sock(*out_sk)->dst_in, sizeof *addr_in);
343
		assert(addr_in->sin_family == AF_INET);
344
		*addrlen = sizeof *addr_in;
345
	}
346

347
	return 0;
348
}
349

350
static int inet_sendmsg(struct sock *sk, struct msghdr *msg,
351
		int flags) {
352
	const struct sockaddr_in *addr_in;
353

354
	assert(sk);
355
	assert(msg);
356

357
	addr_in = (const struct sockaddr_in *)msg->msg_name;
358
	if ((addr_in != NULL) &&
359
			((msg->msg_namelen != sizeof *addr_in)
360
				|| (addr_in->sin_family != AF_INET))) {
361
		return -EINVAL;
362
	}
363

364
	assert(sk->p_ops != NULL);
365
	if (sk->p_ops->sendmsg == NULL) {
366
		return -EOPNOTSUPP;
367
	}
368

369
	return sk->p_ops->sendmsg(sk, msg, flags);
370
}
371

372
static int inet_recvmsg(struct sock *sk, struct msghdr *msg,
373
		int flags) {
374
	struct sockaddr_in *addr_in;
375

376
	assert(sk);
377
	assert(msg);
378

379
	assert(sk->p_ops != NULL);
380
	if (sk->p_ops->recvmsg == NULL) {
381
		return -ENOSYS;
382
	}
383

384
	if (msg->msg_name != NULL) {
385
		if (msg->msg_namelen < sizeof *addr_in) {
386
			return -EINVAL;
387
		}
388
		addr_in = (struct sockaddr_in *)msg->msg_name;
389
		memcpy(addr_in, &to_inet_sock(sk)->dst_in, sizeof *addr_in);
390
		assert(addr_in->sin_family == AF_INET);
391
		msg->msg_namelen = sizeof *addr_in;
392
	}
393

394
	return sk->p_ops->recvmsg(sk, msg, flags);
395
}
396

397
static int inet_getsockname(struct sock *sk,
398
		struct sockaddr *addr, socklen_t *addrlen) {
399
	struct sockaddr_in *addr_in;
400

401
	assert(sk);
402
	assert(addr);
403
	assert(addrlen);
404

405
	if (*addrlen < sizeof *addr_in) {
406
		return -EINVAL;
407
	}
408

409
	addr_in = (struct sockaddr_in *)addr;
410
	memcpy(addr_in, &to_inet_sock(sk)->src_in, sizeof *addr_in);
411
#if 0
412
	assert((addr_in->sin_family == AF_UNSPEC)
413
			|| (addr_in->sin_family == AF_INET));
414
#else
415
	addr_in->sin_family = AF_INET;
416
#endif
417
	*addrlen = sizeof *addr_in;
418

419
	return 0;
420
}
421

422
static int inet_getpeername(struct sock *sk,
423
		struct sockaddr *addr, socklen_t *addrlen) {
424
	struct sockaddr_in *addr_in;
425

426
	assert(sk);
427
	assert(addr);
428
	assert(addrlen);
429

430
	if (*addrlen < sizeof *addr_in) {
431
		return -EINVAL;
432
	}
433

434
	addr_in = (struct sockaddr_in *)addr;
435
	memcpy(addr_in, &to_inet_sock(sk)->dst_in, sizeof *addr_in);
436
#if 0
437
	assert((addr_in->sin_family == AF_UNSPEC)
438
			|| (addr_in->sin_family == AF_INET));
439
#else
440
	addr_in->sin_family = AF_INET;
441
#endif
442
	*addrlen = sizeof *addr_in;
443

444
	return 0;
445
}
446

447
static int inet_getsockopt(struct sock *sk, int level,
448
		int optname, void *optval, socklen_t *optlen) {
449
	assert(sk);
450
	assert(optval);
451
	assert(optlen);
452
	assert(*optlen >= 0);
453

454
	if (level != IPPROTO_IP) {
455
		assert(sk->p_ops != NULL);
456
		if (sk->p_ops->getsockopt == NULL) {
457
			return -EOPNOTSUPP;
458
		}
459
		return sk->p_ops->getsockopt(sk, level, optname, optval,
460
				optlen);
461
	}
462

463
	switch (optname) {
464
	default:
465
		return -ENOPROTOOPT;
466
	}
467

468
	return 0;
469
}
470

471
static int inet_setsockopt(struct sock *sk, int level,
472
		int optname, const void *optval, socklen_t optlen) {
473
	struct inet_sock *inet;
474
	int val = 0;
475

476
	assert(sk);
477
	assert(optval);
478
	assert(optlen >= 0);
479

480
	inet = to_inet_sock(sk);
481

482
	if (level != IPPROTO_IP) {
483
		assert(sk->p_ops != NULL);
484
		if (sk->p_ops->setsockopt == NULL) {
485
			return -EOPNOTSUPP;
486
		}
487
		return sk->p_ops->setsockopt(sk, level, optname, optval,
488
				optlen);
489
	}
490

491
	switch (optname) {
492
	case IP_HDRINCL:
493
		if (optlen <= 0 || optlen > sizeof(int)) {
494
			return -EFAULT;
495
		}
496
		memcpy(&val, optval, optlen);
497
		break;
498
	}
499

500
	switch (optname) {
501
	case IP_HDRINCL:
502
		if (sk->opt.so_type != SOCK_RAW) {
503
			return -ENOPROTOOPT;
504
		}
505
		inet->opt.hdrincl = val ? 1 : 0;
506
		break;
507
	case IP_TOS:
508
		break;
509
	default:
510
		return -ENOPROTOOPT;
511
	}
512

513
	return 0;
514
}
515

516
static int inet_shutdown(struct sock *sk, int how) {
517
	assert(sk);
518
	assert(sk->p_ops != NULL);
519

520
	if (sk->p_ops->shutdown == NULL) {
521
		return -EOPNOTSUPP;
522
	}
523

524
	return sk->p_ops->shutdown(sk, how);
525
}
526

527
POOL_DEF(inet_sock_pool, struct inet_sock, MODOPS_AMOUNT_INET_SOCK);
528

529
static const struct sock_family_ops inet_stream_ops = {
530
	.init        = inet_init,
531
	.close       = inet_close,
532
	.bind        = inet_bind,
533
	.bind_local  = inet_bind_local,
534
	.connect     = inet_stream_connect,
535
	.listen      = inet_listen,
536
	.accept      = inet_accept,
537
	.sendmsg     = inet_sendmsg,
538
	.recvmsg     = inet_recvmsg,
539
	.getsockname = inet_getsockname,
540
	.getpeername = inet_getpeername,
541
	.getsockopt  = inet_getsockopt,
542
	.setsockopt  = inet_setsockopt,
543
	.shutdown    = inet_shutdown,
544
	.sock_pool   = &inet_sock_pool
545
};
546

547
static const struct sock_family_ops inet_dgram_ops = {
548
	.init        = inet_init,
549
	.close       = inet_close,
550
	.bind        = inet_bind,
551
	.bind_local  = inet_bind_local,
552
	.connect     = inet_nonstream_connect,
553
	.listen      = inet_listen,
554
	.accept      = inet_accept,
555
	.sendmsg     = inet_sendmsg,
556
	.recvmsg     = inet_recvmsg,
557
	.getsockname = inet_getsockname,
558
	.getpeername = inet_getpeername,
559
	.getsockopt  = inet_getsockopt,
560
	.setsockopt  = inet_setsockopt,
561
	.shutdown    = inet_shutdown,
562
	.sock_pool   = &inet_sock_pool
563
};
564

565
static const struct sock_family_ops inet_raw_ops = {
566
	.init        = inet_init,
567
	.close       = inet_close,
568
	.bind        = inet_bind,
569
	.bind_local  = inet_bind_local,
570
	.connect     = inet_nonstream_connect,
571
	.listen      = inet_listen,
572
	.accept      = inet_accept,
573
	.sendmsg     = inet_sendmsg,
574
	.recvmsg     = inet_recvmsg,
575
	.getsockname = inet_getsockname,
576
	.getpeername = inet_getpeername,
577
	.getsockopt  = inet_getsockopt,
578
	.setsockopt  = inet_setsockopt,
579
	.shutdown    = inet_shutdown,
580
	.sock_pool   = &inet_sock_pool
581
};
582

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

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

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

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