xref: /spdk/module/sock/posix/posix.c (revision 407e88fd2ab020d753e33014cf759353a9901b51)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 
36 #if defined(__linux__)
37 #include <sys/epoll.h>
38 #elif defined(__FreeBSD__)
39 #include <sys/event.h>
40 #endif
41 
42 #include "spdk/log.h"
43 #include "spdk/sock.h"
44 #include "spdk_internal/sock.h"
45 
46 #define MAX_TMPBUF 1024
47 #define PORTNUMLEN 32
48 
49 struct spdk_posix_sock {
50 	struct spdk_sock	base;
51 	int			fd;
52 };
53 
54 struct spdk_posix_sock_group_impl {
55 	struct spdk_sock_group_impl	base;
56 	int				fd;
57 };
58 
59 static int
60 get_addr_str(struct sockaddr *sa, char *host, size_t hlen)
61 {
62 	const char *result = NULL;
63 
64 	if (sa == NULL || host == NULL) {
65 		return -1;
66 	}
67 
68 	switch (sa->sa_family) {
69 	case AF_INET:
70 		result = inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
71 				   host, hlen);
72 		break;
73 	case AF_INET6:
74 		result = inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
75 				   host, hlen);
76 		break;
77 	default:
78 		break;
79 	}
80 
81 	if (result != NULL) {
82 		return 0;
83 	} else {
84 		return -1;
85 	}
86 }
87 
88 #define __posix_sock(sock) (struct spdk_posix_sock *)sock
89 #define __posix_group_impl(group) (struct spdk_posix_sock_group_impl *)group
90 
91 static int
92 spdk_posix_sock_getaddr(struct spdk_sock *_sock, char *saddr, int slen, uint16_t *sport,
93 			char *caddr, int clen, uint16_t *cport)
94 {
95 	struct spdk_posix_sock *sock = __posix_sock(_sock);
96 	struct sockaddr_storage sa;
97 	socklen_t salen;
98 	int rc;
99 
100 	assert(sock != NULL);
101 
102 	memset(&sa, 0, sizeof sa);
103 	salen = sizeof sa;
104 	rc = getsockname(sock->fd, (struct sockaddr *) &sa, &salen);
105 	if (rc != 0) {
106 		SPDK_ERRLOG("getsockname() failed (errno=%d)\n", errno);
107 		return -1;
108 	}
109 
110 	switch (sa.ss_family) {
111 	case AF_UNIX:
112 		/* Acceptable connection types that don't have IPs */
113 		return 0;
114 	case AF_INET:
115 	case AF_INET6:
116 		/* Code below will get IP addresses */
117 		break;
118 	default:
119 		/* Unsupported socket family */
120 		return -1;
121 	}
122 
123 	rc = get_addr_str((struct sockaddr *)&sa, saddr, slen);
124 	if (rc != 0) {
125 		SPDK_ERRLOG("getnameinfo() failed (errno=%d)\n", errno);
126 		return -1;
127 	}
128 
129 	if (sport) {
130 		if (sa.ss_family == AF_INET) {
131 			*sport = ntohs(((struct sockaddr_in *) &sa)->sin_port);
132 		} else if (sa.ss_family == AF_INET6) {
133 			*sport = ntohs(((struct sockaddr_in6 *) &sa)->sin6_port);
134 		}
135 	}
136 
137 	memset(&sa, 0, sizeof sa);
138 	salen = sizeof sa;
139 	rc = getpeername(sock->fd, (struct sockaddr *) &sa, &salen);
140 	if (rc != 0) {
141 		SPDK_ERRLOG("getpeername() failed (errno=%d)\n", errno);
142 		return -1;
143 	}
144 
145 	rc = get_addr_str((struct sockaddr *)&sa, caddr, clen);
146 	if (rc != 0) {
147 		SPDK_ERRLOG("getnameinfo() failed (errno=%d)\n", errno);
148 		return -1;
149 	}
150 
151 	if (cport) {
152 		if (sa.ss_family == AF_INET) {
153 			*cport = ntohs(((struct sockaddr_in *) &sa)->sin_port);
154 		} else if (sa.ss_family == AF_INET6) {
155 			*cport = ntohs(((struct sockaddr_in6 *) &sa)->sin6_port);
156 		}
157 	}
158 
159 	return 0;
160 }
161 
162 enum spdk_posix_sock_create_type {
163 	SPDK_SOCK_CREATE_LISTEN,
164 	SPDK_SOCK_CREATE_CONNECT,
165 };
166 
167 static struct spdk_sock *
168 spdk_posix_sock_create(const char *ip, int port, enum spdk_posix_sock_create_type type)
169 {
170 	struct spdk_posix_sock *sock;
171 	char buf[MAX_TMPBUF];
172 	char portnum[PORTNUMLEN];
173 	char *p;
174 	struct addrinfo hints, *res, *res0;
175 	int fd, flag;
176 	int val = 1;
177 	int rc;
178 
179 	if (ip == NULL) {
180 		return NULL;
181 	}
182 	if (ip[0] == '[') {
183 		snprintf(buf, sizeof(buf), "%s", ip + 1);
184 		p = strchr(buf, ']');
185 		if (p != NULL) {
186 			*p = '\0';
187 		}
188 		ip = (const char *) &buf[0];
189 	}
190 
191 	snprintf(portnum, sizeof portnum, "%d", port);
192 	memset(&hints, 0, sizeof hints);
193 	hints.ai_family = PF_UNSPEC;
194 	hints.ai_socktype = SOCK_STREAM;
195 	hints.ai_flags = AI_NUMERICSERV;
196 	hints.ai_flags |= AI_PASSIVE;
197 	hints.ai_flags |= AI_NUMERICHOST;
198 	rc = getaddrinfo(ip, portnum, &hints, &res0);
199 	if (rc != 0) {
200 		SPDK_ERRLOG("getaddrinfo() failed (errno=%d)\n", errno);
201 		return NULL;
202 	}
203 
204 	/* try listen */
205 	fd = -1;
206 	for (res = res0; res != NULL; res = res->ai_next) {
207 retry:
208 		fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
209 		if (fd < 0) {
210 			/* error */
211 			continue;
212 		}
213 		rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val);
214 		if (rc != 0) {
215 			close(fd);
216 			/* error */
217 			continue;
218 		}
219 		rc = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof val);
220 		if (rc != 0) {
221 			close(fd);
222 			/* error */
223 			continue;
224 		}
225 
226 		if (res->ai_family == AF_INET6) {
227 			rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof val);
228 			if (rc != 0) {
229 				close(fd);
230 				/* error */
231 				continue;
232 			}
233 		}
234 
235 		if (type == SPDK_SOCK_CREATE_LISTEN) {
236 			rc = bind(fd, res->ai_addr, res->ai_addrlen);
237 			if (rc != 0) {
238 				SPDK_ERRLOG("bind() failed at port %d, errno = %d\n", port, errno);
239 				switch (errno) {
240 				case EINTR:
241 					/* interrupted? */
242 					close(fd);
243 					goto retry;
244 				case EADDRNOTAVAIL:
245 					SPDK_ERRLOG("IP address %s not available. "
246 						    "Verify IP address in config file "
247 						    "and make sure setup script is "
248 						    "run before starting spdk app.\n", ip);
249 				/* FALLTHROUGH */
250 				default:
251 					/* try next family */
252 					close(fd);
253 					fd = -1;
254 					continue;
255 				}
256 			}
257 			/* bind OK */
258 			rc = listen(fd, 512);
259 			if (rc != 0) {
260 				SPDK_ERRLOG("listen() failed, errno = %d\n", errno);
261 				close(fd);
262 				fd = -1;
263 				break;
264 			}
265 		} else if (type == SPDK_SOCK_CREATE_CONNECT) {
266 			rc = connect(fd, res->ai_addr, res->ai_addrlen);
267 			if (rc != 0) {
268 				SPDK_ERRLOG("connect() failed, errno = %d\n", errno);
269 				/* try next family */
270 				close(fd);
271 				fd = -1;
272 				continue;
273 			}
274 		}
275 
276 		flag = fcntl(fd, F_GETFL);
277 		if (fcntl(fd, F_SETFL, flag | O_NONBLOCK) < 0) {
278 			SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%d)\n", fd, errno);
279 			close(fd);
280 			fd = -1;
281 			break;
282 		}
283 		break;
284 	}
285 	freeaddrinfo(res0);
286 
287 	if (fd < 0) {
288 		return NULL;
289 	}
290 
291 	sock = calloc(1, sizeof(*sock));
292 	if (sock == NULL) {
293 		SPDK_ERRLOG("sock allocation failed\n");
294 		close(fd);
295 		return NULL;
296 	}
297 
298 	sock->fd = fd;
299 	return &sock->base;
300 }
301 
302 static struct spdk_sock *
303 spdk_posix_sock_listen(const char *ip, int port)
304 {
305 	return spdk_posix_sock_create(ip, port, SPDK_SOCK_CREATE_LISTEN);
306 }
307 
308 static struct spdk_sock *
309 spdk_posix_sock_connect(const char *ip, int port)
310 {
311 	return spdk_posix_sock_create(ip, port, SPDK_SOCK_CREATE_CONNECT);
312 }
313 
314 static struct spdk_sock *
315 spdk_posix_sock_accept(struct spdk_sock *_sock)
316 {
317 	struct spdk_posix_sock		*sock = __posix_sock(_sock);
318 	struct sockaddr_storage		sa;
319 	socklen_t			salen;
320 	int				rc;
321 	struct spdk_posix_sock		*new_sock;
322 	int				flag;
323 
324 	memset(&sa, 0, sizeof(sa));
325 	salen = sizeof(sa);
326 
327 	assert(sock != NULL);
328 
329 	rc = accept(sock->fd, (struct sockaddr *)&sa, &salen);
330 
331 	if (rc == -1) {
332 		return NULL;
333 	}
334 
335 	flag = fcntl(rc, F_GETFL);
336 	if ((!(flag & O_NONBLOCK)) && (fcntl(rc, F_SETFL, flag | O_NONBLOCK) < 0)) {
337 		SPDK_ERRLOG("fcntl can't set nonblocking mode for socket, fd: %d (%d)\n", rc, errno);
338 		close(rc);
339 		return NULL;
340 	}
341 
342 	new_sock = calloc(1, sizeof(*sock));
343 	if (new_sock == NULL) {
344 		SPDK_ERRLOG("sock allocation failed\n");
345 		close(rc);
346 		return NULL;
347 	}
348 
349 	new_sock->fd = rc;
350 	return &new_sock->base;
351 }
352 
353 static int
354 spdk_posix_sock_close(struct spdk_sock *_sock)
355 {
356 	struct spdk_posix_sock *sock = __posix_sock(_sock);
357 	int rc;
358 
359 	rc = close(sock->fd);
360 	if (rc == 0) {
361 		free(sock);
362 	}
363 
364 	return rc;
365 }
366 
367 static ssize_t
368 spdk_posix_sock_recv(struct spdk_sock *_sock, void *buf, size_t len)
369 {
370 	struct spdk_posix_sock *sock = __posix_sock(_sock);
371 
372 	return recv(sock->fd, buf, len, MSG_DONTWAIT);
373 }
374 
375 static ssize_t
376 spdk_posix_sock_readv(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
377 {
378 	struct spdk_posix_sock *sock = __posix_sock(_sock);
379 
380 	return readv(sock->fd, iov, iovcnt);
381 }
382 
383 static ssize_t
384 spdk_posix_sock_writev(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
385 {
386 	struct spdk_posix_sock *sock = __posix_sock(_sock);
387 
388 	return writev(sock->fd, iov, iovcnt);
389 }
390 
391 static int
392 spdk_posix_sock_set_recvlowat(struct spdk_sock *_sock, int nbytes)
393 {
394 	struct spdk_posix_sock *sock = __posix_sock(_sock);
395 	int val;
396 	int rc;
397 
398 	assert(sock != NULL);
399 
400 	val = nbytes;
401 	rc = setsockopt(sock->fd, SOL_SOCKET, SO_RCVLOWAT, &val, sizeof val);
402 	if (rc != 0) {
403 		return -1;
404 	}
405 	return 0;
406 }
407 
408 static int
409 spdk_posix_sock_set_recvbuf(struct spdk_sock *_sock, int sz)
410 {
411 	struct spdk_posix_sock *sock = __posix_sock(_sock);
412 
413 	assert(sock != NULL);
414 
415 	return setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF,
416 			  &sz, sizeof(sz));
417 }
418 
419 static int
420 spdk_posix_sock_set_sendbuf(struct spdk_sock *_sock, int sz)
421 {
422 	struct spdk_posix_sock *sock = __posix_sock(_sock);
423 
424 	assert(sock != NULL);
425 
426 	return setsockopt(sock->fd, SOL_SOCKET, SO_SNDBUF,
427 			  &sz, sizeof(sz));
428 }
429 
430 static int
431 spdk_posix_sock_set_priority(struct spdk_sock *_sock, int priority)
432 {
433 	int rc = 0;
434 
435 #if defined(SO_PRIORITY)
436 	struct spdk_posix_sock *sock = __posix_sock(_sock);
437 
438 	assert(sock != NULL);
439 
440 	rc = setsockopt(sock->fd, SOL_SOCKET, SO_PRIORITY,
441 			&priority, sizeof(priority));
442 #endif
443 	return rc;
444 }
445 
446 static bool
447 spdk_posix_sock_is_ipv6(struct spdk_sock *_sock)
448 {
449 	struct spdk_posix_sock *sock = __posix_sock(_sock);
450 	struct sockaddr_storage sa;
451 	socklen_t salen;
452 	int rc;
453 
454 	assert(sock != NULL);
455 
456 	memset(&sa, 0, sizeof sa);
457 	salen = sizeof sa;
458 	rc = getsockname(sock->fd, (struct sockaddr *) &sa, &salen);
459 	if (rc != 0) {
460 		SPDK_ERRLOG("getsockname() failed (errno=%d)\n", errno);
461 		return false;
462 	}
463 
464 	return (sa.ss_family == AF_INET6);
465 }
466 
467 static bool
468 spdk_posix_sock_is_ipv4(struct spdk_sock *_sock)
469 {
470 	struct spdk_posix_sock *sock = __posix_sock(_sock);
471 	struct sockaddr_storage sa;
472 	socklen_t salen;
473 	int rc;
474 
475 	assert(sock != NULL);
476 
477 	memset(&sa, 0, sizeof sa);
478 	salen = sizeof sa;
479 	rc = getsockname(sock->fd, (struct sockaddr *) &sa, &salen);
480 	if (rc != 0) {
481 		SPDK_ERRLOG("getsockname() failed (errno=%d)\n", errno);
482 		return false;
483 	}
484 
485 	return (sa.ss_family == AF_INET);
486 }
487 
488 static int
489 spdk_posix_sock_get_placement_id(struct spdk_sock *_sock, int *placement_id)
490 {
491 	int rc = -1;
492 
493 #if defined(SO_INCOMING_NAPI_ID)
494 	struct spdk_posix_sock *sock = __posix_sock(_sock);
495 	socklen_t salen = sizeof(int);
496 
497 	rc = getsockopt(sock->fd, SOL_SOCKET, SO_INCOMING_NAPI_ID, placement_id, &salen);
498 	if (rc != 0) {
499 		SPDK_ERRLOG("getsockopt() failed (errno=%d)\n", errno);
500 	}
501 
502 #endif
503 	return rc;
504 }
505 
506 static struct spdk_sock_group_impl *
507 spdk_posix_sock_group_impl_create(void)
508 {
509 	struct spdk_posix_sock_group_impl *group_impl;
510 	int fd;
511 
512 #if defined(__linux__)
513 	fd = epoll_create1(0);
514 #elif defined(__FreeBSD__)
515 	fd = kqueue();
516 #endif
517 	if (fd == -1) {
518 		return NULL;
519 	}
520 
521 	group_impl = calloc(1, sizeof(*group_impl));
522 	if (group_impl == NULL) {
523 		SPDK_ERRLOG("group_impl allocation failed\n");
524 		close(fd);
525 		return NULL;
526 	}
527 
528 	group_impl->fd = fd;
529 
530 	return &group_impl->base;
531 }
532 
533 static int
534 spdk_posix_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock)
535 {
536 	struct spdk_posix_sock_group_impl *group = __posix_group_impl(_group);
537 	struct spdk_posix_sock *sock = __posix_sock(_sock);
538 	int rc;
539 
540 #if defined(__linux__)
541 	struct epoll_event event;
542 
543 	memset(&event, 0, sizeof(event));
544 	event.events = EPOLLIN;
545 	event.data.ptr = sock;
546 
547 	rc = epoll_ctl(group->fd, EPOLL_CTL_ADD, sock->fd, &event);
548 #elif defined(__FreeBSD__)
549 	struct kevent event;
550 	struct timespec ts = {0};
551 
552 	EV_SET(&event, sock->fd, EVFILT_READ, EV_ADD, 0, 0, sock);
553 
554 	rc = kevent(group->fd, &event, 1, NULL, 0, &ts);
555 #endif
556 	return rc;
557 }
558 
559 static int
560 spdk_posix_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group, struct spdk_sock *_sock)
561 {
562 	struct spdk_posix_sock_group_impl *group = __posix_group_impl(_group);
563 	struct spdk_posix_sock *sock = __posix_sock(_sock);
564 	int rc;
565 #if defined(__linux__)
566 	struct epoll_event event;
567 
568 	/* Event parameter is ignored but some old kernel version still require it. */
569 	rc = epoll_ctl(group->fd, EPOLL_CTL_DEL, sock->fd, &event);
570 #elif defined(__FreeBSD__)
571 	struct kevent event;
572 	struct timespec ts = {0};
573 
574 	EV_SET(&event, sock->fd, EVFILT_READ, EV_DELETE, 0, 0, NULL);
575 
576 	rc = kevent(group->fd, &event, 1, NULL, 0, &ts);
577 	if (rc == 0 && event.flags & EV_ERROR) {
578 		rc = -1;
579 		errno = event.data;
580 	}
581 #endif
582 	return rc;
583 }
584 
585 static int
586 spdk_posix_sock_group_impl_poll(struct spdk_sock_group_impl *_group, int max_events,
587 				struct spdk_sock **socks)
588 {
589 	struct spdk_posix_sock_group_impl *group = __posix_group_impl(_group);
590 	int num_events, i;
591 
592 #if defined(__linux__)
593 	struct epoll_event events[MAX_EVENTS_PER_POLL];
594 
595 	num_events = epoll_wait(group->fd, events, max_events, 0);
596 #elif defined(__FreeBSD__)
597 	struct kevent events[MAX_EVENTS_PER_POLL];
598 	struct timespec ts = {0};
599 
600 	num_events = kevent(group->fd, NULL, 0, events, max_events, &ts);
601 #endif
602 
603 	if (num_events == -1) {
604 		return -1;
605 	}
606 
607 	for (i = 0; i < num_events; i++) {
608 #if defined(__linux__)
609 		socks[i] = events[i].data.ptr;
610 #elif defined(__FreeBSD__)
611 		socks[i] = events[i].udata;
612 #endif
613 	}
614 
615 	return num_events;
616 }
617 
618 static int
619 spdk_posix_sock_group_impl_close(struct spdk_sock_group_impl *_group)
620 {
621 	struct spdk_posix_sock_group_impl *group = __posix_group_impl(_group);
622 
623 	return close(group->fd);
624 }
625 
626 static struct spdk_net_impl g_posix_net_impl = {
627 	.name		= "posix",
628 	.getaddr	= spdk_posix_sock_getaddr,
629 	.connect	= spdk_posix_sock_connect,
630 	.listen		= spdk_posix_sock_listen,
631 	.accept		= spdk_posix_sock_accept,
632 	.close		= spdk_posix_sock_close,
633 	.recv		= spdk_posix_sock_recv,
634 	.readv		= spdk_posix_sock_readv,
635 	.writev		= spdk_posix_sock_writev,
636 	.set_recvlowat	= spdk_posix_sock_set_recvlowat,
637 	.set_recvbuf	= spdk_posix_sock_set_recvbuf,
638 	.set_sendbuf	= spdk_posix_sock_set_sendbuf,
639 	.set_priority	= spdk_posix_sock_set_priority,
640 	.is_ipv6	= spdk_posix_sock_is_ipv6,
641 	.is_ipv4	= spdk_posix_sock_is_ipv4,
642 	.get_placement_id	= spdk_posix_sock_get_placement_id,
643 	.group_impl_create	= spdk_posix_sock_group_impl_create,
644 	.group_impl_add_sock	= spdk_posix_sock_group_impl_add_sock,
645 	.group_impl_remove_sock = spdk_posix_sock_group_impl_remove_sock,
646 	.group_impl_poll	= spdk_posix_sock_group_impl_poll,
647 	.group_impl_close	= spdk_posix_sock_group_impl_close,
648 };
649 
650 SPDK_NET_IMPL_REGISTER(posix, &g_posix_net_impl);
651