4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
36 #include <netinet/in.h>
37 #include <netinet/tcp.h>
43 #include <sys/ioctl.h>
44 #include <sys/socket.h>
47 #include "spdk/event.h"
51 #define MAX_TMPBUF 1024
54 static int get_addr_str(struct sockaddr_in
*paddr
, char *host
, size_t hlen
)
56 if (paddr
== NULL
|| host
== NULL
)
59 uint8_t *pa
= (uint8_t *)&paddr
->sin_addr
.s_addr
;
60 snprintf(host
, hlen
, "%u.%u.%u.%u", pa
[0], pa
[1], pa
[2], pa
[3]);
66 spdk_sock_getaddr(int sock
, char *saddr
, int slen
, char *caddr
, int clen
)
68 struct sockaddr_storage sa
;
72 memset(&sa
, 0, sizeof sa
);
74 rc
= getsockname(sock
, (struct sockaddr
*) &sa
, &salen
);
76 SPDK_ERRLOG("getsockname() failed (errno=%d)\n", errno
);
80 switch (sa
.ss_family
) {
82 /* Acceptable connection types that don't have IPs */
86 /* Code below will get IP addresses */
89 /* Unsupported socket family */
93 rc
= get_addr_str((struct sockaddr_in
*)&sa
, saddr
, slen
);
95 SPDK_ERRLOG("getnameinfo() failed (errno=%d)\n", errno
);
99 memset(&sa
, 0, sizeof sa
);
101 rc
= getpeername(sock
, (struct sockaddr
*) &sa
, &salen
);
103 SPDK_ERRLOG("getpeername() failed (errno=%d)\n", errno
);
107 rc
= get_addr_str((struct sockaddr_in
*)&sa
, caddr
, clen
);
109 SPDK_ERRLOG("getnameinfo() failed (errno=%d)\n", errno
);
116 enum spdk_sock_create_type
{
117 SPDK_SOCK_CREATE_LISTEN
,
118 SPDK_SOCK_CREATE_CONNECT
,
122 spdk_sock_create(const char *ip
, int port
, enum spdk_sock_create_type type
)
124 char buf
[MAX_TMPBUF
];
125 char portnum
[PORTNUMLEN
];
127 struct addrinfo hints
, *res
, *res0
;
135 snprintf(buf
, sizeof(buf
), "%s", ip
+ 1);
136 p
= strchr(buf
, ']');
139 ip
= (const char *) &buf
[0];
140 if (strcasecmp(ip
, "*") == 0) {
141 snprintf(buf
, sizeof(buf
), "::");
142 ip
= (const char *) &buf
[0];
144 } else if (strcasecmp(ip
, "*") == 0) {
145 snprintf(buf
, sizeof(buf
), "0.0.0.0");
146 ip
= (const char *) &buf
[0];
149 snprintf(portnum
, sizeof portnum
, "%d", port
);
150 memset(&hints
, 0, sizeof hints
);
151 hints
.ai_family
= PF_UNSPEC
;
152 hints
.ai_socktype
= SOCK_STREAM
;
153 hints
.ai_flags
= AI_NUMERICSERV
;
154 hints
.ai_flags
|= AI_PASSIVE
;
155 hints
.ai_flags
|= AI_NUMERICHOST
;
156 rc
= getaddrinfo(ip
, portnum
, &hints
, &res0
);
158 SPDK_ERRLOG("getaddrinfo() failed (errno=%d)\n", errno
);
164 for (res
= res0
; res
!= NULL
; res
= res
->ai_next
) {
166 sock
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
171 rc
= setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, &val
, sizeof val
);
177 rc
= setsockopt(sock
, IPPROTO_TCP
, TCP_NODELAY
, &val
, sizeof val
);
184 if (type
== SPDK_SOCK_CREATE_LISTEN
) {
185 rc
= bind(sock
, res
->ai_addr
, res
->ai_addrlen
);
187 SPDK_ERRLOG("bind() failed, errno = %d\n", errno
);
194 SPDK_ERRLOG("IP address %s not available. "
195 "Verify IP address in config file "
196 "and make sure setup script is "
197 "run before starting spdk app.\n", ip
);
200 /* try next family */
207 rc
= listen(sock
, 512);
209 SPDK_ERRLOG("listen() failed, errno = %d\n", errno
);
214 } else if (type
== SPDK_SOCK_CREATE_CONNECT
) {
215 rc
= connect(sock
, res
->ai_addr
, res
->ai_addrlen
);
217 SPDK_ERRLOG("connect() failed, errno = %d\n", errno
);
218 /* try next family */
226 rc
= ioctl(sock
, FIONBIO
, &nonblock
);
228 SPDK_ERRLOG("ioctl(FIONBIO) failed\n");
244 spdk_sock_listen(const char *ip
, int port
)
246 return spdk_sock_create(ip
, port
, SPDK_SOCK_CREATE_LISTEN
);
250 spdk_sock_connect(const char *ip
, int port
)
252 return spdk_sock_create(ip
, port
, SPDK_SOCK_CREATE_CONNECT
);
256 spdk_sock_accept(int sock
)
258 struct sockaddr_storage sa
;
261 memset(&sa
, 0, sizeof(sa
));
263 return accept(sock
, (struct sockaddr
*)&sa
, &salen
);
267 spdk_sock_close(int sock
)
273 spdk_sock_recv(int sock
, void *buf
, size_t len
)
275 return recv(sock
, buf
, len
, MSG_DONTWAIT
);
279 spdk_sock_writev(int sock
, struct iovec
*iov
, int iovcnt
)
281 return writev(sock
, iov
, iovcnt
);
285 spdk_sock_set_recvlowat(int s
, int nbytes
)
291 rc
= setsockopt(s
, SOL_SOCKET
, SO_RCVLOWAT
, &val
, sizeof val
);
298 spdk_sock_set_recvbuf(int sock
, int sz
)
300 return setsockopt(sock
, SOL_SOCKET
, SO_RCVBUF
,
305 spdk_sock_set_sendbuf(int sock
, int sz
)
307 return setsockopt(sock
, SOL_SOCKET
, SO_SNDBUF
,
312 spdk_sock_is_ipv6(int sock
)
314 struct sockaddr_storage sa
;
318 memset(&sa
, 0, sizeof sa
);
320 rc
= getsockname(sock
, (struct sockaddr
*) &sa
, &salen
);
322 SPDK_ERRLOG("getsockname() failed (errno=%d)\n", errno
);
326 return (sa
.ss_family
== AF_INET6
);
330 spdk_sock_is_ipv4(int sock
)
332 struct sockaddr_storage sa
;
336 memset(&sa
, 0, sizeof sa
);
338 rc
= getsockname(sock
, (struct sockaddr
*) &sa
, &salen
);
340 SPDK_ERRLOG("getsockname() failed (errno=%d)\n", errno
);
344 return (sa
.ss_family
== AF_INET
);