clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name anet.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -D REDIS_STATIC= -I ../deps/hiredis -I ../deps/linenoise -I ../deps/lua/src -I ../deps/hdr_histogram -D USE_JEMALLOC -I ../deps/jemalloc/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-c11-extensions -Wno-missing-field-initializers -std=c11 -fdebug-compilation-dir /home/netto/Desktop/redis-6.2.1/src -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-03-14-133648-8817-1 -x c anet.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | #include "fmacros.h" |
32 | |
33 | #include <sys/types.h> |
34 | #include <sys/socket.h> |
35 | #include <sys/stat.h> |
36 | #include <sys/un.h> |
37 | #include <sys/time.h> |
38 | #include <netinet/in.h> |
39 | #include <netinet/tcp.h> |
40 | #include <arpa/inet.h> |
41 | #include <unistd.h> |
42 | #include <fcntl.h> |
43 | #include <string.h> |
44 | #include <netdb.h> |
45 | #include <errno.h> |
46 | #include <stdarg.h> |
47 | #include <stdio.h> |
48 | |
49 | #include "anet.h" |
50 | |
51 | static void anetSetError(char *err, const char *fmt, ...) |
52 | { |
53 | va_list ap; |
54 | |
55 | if (!err) return; |
56 | va_start(ap, fmt); |
57 | vsnprintf(err, ANET_ERR_LEN, fmt, ap); |
58 | va_end(ap); |
59 | } |
60 | |
61 | int anetSetBlock(char *err, int fd, int non_block) { |
62 | int flags; |
63 | |
64 | |
65 | |
66 | |
67 | if ((flags = fcntl(fd, F_GETFL)) == -1) { |
68 | anetSetError(err, "fcntl(F_GETFL): %s", strerror(errno)); |
69 | return ANET_ERR; |
70 | } |
71 | |
72 | |
73 | |
74 | if (!!(flags & O_NONBLOCK) == !!non_block) |
75 | return ANET_OK; |
76 | |
77 | if (non_block) |
78 | flags |= O_NONBLOCK; |
79 | else |
80 | flags &= ~O_NONBLOCK; |
81 | |
82 | if (fcntl(fd, F_SETFL, flags) == -1) { |
83 | anetSetError(err, "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno)); |
84 | return ANET_ERR; |
85 | } |
86 | return ANET_OK; |
87 | } |
88 | |
89 | int anetNonBlock(char *err, int fd) { |
90 | return anetSetBlock(err,fd,1); |
91 | } |
92 | |
93 | int anetBlock(char *err, int fd) { |
94 | return anetSetBlock(err,fd,0); |
95 | } |
96 | |
97 | |
98 | |
99 | |
100 | int anetCloexec(int fd) { |
101 | int r; |
102 | int flags; |
103 | |
104 | do { |
105 | r = fcntl(fd, F_GETFD); |
106 | } while (r == -1 && errno == EINTR); |
107 | |
108 | if (r == -1 || (r & FD_CLOEXEC)) |
109 | return r; |
110 | |
111 | flags = r | FD_CLOEXEC; |
112 | |
113 | do { |
114 | r = fcntl(fd, F_SETFD, flags); |
115 | } while (r == -1 && errno == EINTR); |
116 | |
117 | return r; |
118 | } |
119 | |
120 | |
121 | |
122 | |
123 | int anetKeepAlive(char *err, int fd, int interval) |
124 | { |
125 | int val = 1; |
126 | |
127 | if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1) |
128 | { |
129 | anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); |
130 | return ANET_ERR; |
131 | } |
132 | |
133 | #ifdef __linux__ |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | val = interval; |
140 | if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) { |
141 | anetSetError(err, "setsockopt TCP_KEEPIDLE: %s\n", strerror(errno)); |
142 | return ANET_ERR; |
143 | } |
144 | |
145 | |
146 | |
147 | |
148 | val = interval/3; |
149 | if (val == 0) val = 1; |
150 | if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) { |
151 | anetSetError(err, "setsockopt TCP_KEEPINTVL: %s\n", strerror(errno)); |
152 | return ANET_ERR; |
153 | } |
154 | |
155 | |
156 | |
157 | val = 3; |
158 | if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) { |
159 | anetSetError(err, "setsockopt TCP_KEEPCNT: %s\n", strerror(errno)); |
160 | return ANET_ERR; |
161 | } |
162 | #else |
163 | ((void) interval); |
164 | #endif |
165 | |
166 | return ANET_OK; |
167 | } |
168 | |
169 | static int anetSetTcpNoDelay(char *err, int fd, int val) |
170 | { |
171 | if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)) == -1) |
172 | { |
173 | anetSetError(err, "setsockopt TCP_NODELAY: %s", strerror(errno)); |
174 | return ANET_ERR; |
175 | } |
176 | return ANET_OK; |
177 | } |
178 | |
179 | int anetEnableTcpNoDelay(char *err, int fd) |
180 | { |
181 | return anetSetTcpNoDelay(err, fd, 1); |
182 | } |
183 | |
184 | int anetDisableTcpNoDelay(char *err, int fd) |
185 | { |
186 | return anetSetTcpNoDelay(err, fd, 0); |
187 | } |
188 | |
189 | |
190 | int anetSetSendBuffer(char *err, int fd, int buffsize) |
191 | { |
192 | if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffsize, sizeof(buffsize)) == -1) |
193 | { |
194 | anetSetError(err, "setsockopt SO_SNDBUF: %s", strerror(errno)); |
195 | return ANET_ERR; |
196 | } |
197 | return ANET_OK; |
198 | } |
199 | |
200 | int anetTcpKeepAlive(char *err, int fd) |
201 | { |
202 | int yes = 1; |
203 | if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1) { |
204 | anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno)); |
205 | return ANET_ERR; |
206 | } |
207 | return ANET_OK; |
208 | } |
209 | |
210 | |
211 | |
212 | int anetSendTimeout(char *err, int fd, long long ms) { |
213 | struct timeval tv; |
214 | |
215 | tv.tv_sec = ms/1000; |
216 | tv.tv_usec = (ms%1000)*1000; |
217 | if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) == -1) { |
218 | anetSetError(err, "setsockopt SO_SNDTIMEO: %s", strerror(errno)); |
219 | return ANET_ERR; |
220 | } |
221 | return ANET_OK; |
222 | } |
223 | |
224 | |
225 | |
226 | int anetRecvTimeout(char *err, int fd, long long ms) { |
227 | struct timeval tv; |
228 | |
229 | tv.tv_sec = ms/1000; |
230 | tv.tv_usec = (ms%1000)*1000; |
231 | if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) { |
232 | anetSetError(err, "setsockopt SO_RCVTIMEO: %s", strerror(errno)); |
233 | return ANET_ERR; |
234 | } |
235 | return ANET_OK; |
236 | } |
237 | |
238 | |
239 | |
240 | |
241 | |
242 | |
243 | |
244 | int anetResolve(char *err, char *host, char *ipbuf, size_t ipbuf_len, |
245 | int flags) |
246 | { |
247 | struct addrinfo hints, *info; |
248 | int rv; |
249 | |
250 | memset(&hints,0,sizeof(hints)); |
251 | if (flags & ANET_IP_ONLY) hints.ai_flags = AI_NUMERICHOST; |
252 | hints.ai_family = AF_UNSPEC; |
253 | hints.ai_socktype = SOCK_STREAM; |
254 | |
255 | if ((rv = getaddrinfo(host, NULL, &hints, &info)) != 0) { |
256 | anetSetError(err, "%s", gai_strerror(rv)); |
257 | return ANET_ERR; |
258 | } |
259 | if (info->ai_family == AF_INET) { |
260 | struct sockaddr_in *sa = (struct sockaddr_in *)info->ai_addr; |
261 | inet_ntop(AF_INET, &(sa->sin_addr), ipbuf, ipbuf_len); |
262 | } else { |
263 | struct sockaddr_in6 *sa = (struct sockaddr_in6 *)info->ai_addr; |
264 | inet_ntop(AF_INET6, &(sa->sin6_addr), ipbuf, ipbuf_len); |
265 | } |
266 | |
267 | freeaddrinfo(info); |
268 | return ANET_OK; |
269 | } |
270 | |
271 | static int anetSetReuseAddr(char *err, int fd) { |
272 | int yes = 1; |
273 | |
274 | |
275 | if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { |
276 | anetSetError(err, "setsockopt SO_REUSEADDR: %s", strerror(errno)); |
277 | return ANET_ERR; |
278 | } |
279 | return ANET_OK; |
280 | } |
281 | |
282 | static int anetCreateSocket(char *err, int domain) { |
283 | int s; |
284 | if ((s = socket(domain, SOCK_STREAM, 0)) == -1) { |
285 | anetSetError(err, "creating socket: %s", strerror(errno)); |
286 | return ANET_ERR; |
287 | } |
288 | |
289 | |
290 | |
291 | if (anetSetReuseAddr(err,s) == ANET_ERR) { |
292 | close(s); |
293 | return ANET_ERR; |
294 | } |
295 | return s; |
296 | } |
297 | |
298 | #define ANET_CONNECT_NONE 0 |
299 | #define ANET_CONNECT_NONBLOCK 1 |
300 | #define ANET_CONNECT_BE_BINDING 2 /* Best effort binding. */ |
301 | static int anetTcpGenericConnect(char *err, const char *addr, int port, |
302 | const char *source_addr, int flags) |
303 | { |
304 | int s = ANET_ERR, rv; |
305 | char portstr[6]; |
306 | struct addrinfo hints, *servinfo, *bservinfo, *p, *b; |
307 | |
308 | snprintf(portstr,sizeof(portstr),"%d",port); |
309 | memset(&hints,0,sizeof(hints)); |
310 | hints.ai_family = AF_UNSPEC; |
311 | hints.ai_socktype = SOCK_STREAM; |
312 | |
313 | if ((rv = getaddrinfo(addr,portstr,&hints,&servinfo)) != 0) { |
314 | anetSetError(err, "%s", gai_strerror(rv)); |
315 | return ANET_ERR; |
316 | } |
317 | for (p = servinfo; p != NULL; p = p->ai_next) { |
318 | |
319 | |
320 | |
321 | if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) |
322 | continue; |
323 | if (anetSetReuseAddr(err,s) == ANET_ERR) goto error; |
324 | if (flags & ANET_CONNECT_NONBLOCK && anetNonBlock(err,s) != ANET_OK) |
325 | goto error; |
326 | if (source_addr) { |
327 | int bound = 0; |
328 | |
329 | if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) |
330 | { |
331 | anetSetError(err, "%s", gai_strerror(rv)); |
332 | goto error; |
333 | } |
334 | for (b = bservinfo; b != NULL; b = b->ai_next) { |
335 | if (bind(s,b->ai_addr,b->ai_addrlen) != -1) { |
336 | bound = 1; |
337 | break; |
338 | } |
339 | } |
340 | freeaddrinfo(bservinfo); |
341 | if (!bound) { |
342 | anetSetError(err, "bind: %s", strerror(errno)); |
343 | goto error; |
344 | } |
345 | } |
346 | if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { |
347 | |
348 | |
349 | if (errno == EINPROGRESS && flags & ANET_CONNECT_NONBLOCK) |
350 | goto end; |
351 | close(s); |
352 | s = ANET_ERR; |
353 | continue; |
354 | } |
355 | |
356 | |
357 | |
358 | goto end; |
359 | } |
360 | if (p == NULL) |
361 | anetSetError(err, "creating socket: %s", strerror(errno)); |
362 | |
363 | error: |
364 | if (s != ANET_ERR) { |
365 | close(s); |
366 | s = ANET_ERR; |
367 | } |
368 | |
369 | end: |
370 | freeaddrinfo(servinfo); |
371 | |
372 | |
373 | |
374 | if (s == ANET_ERR && source_addr && (flags & ANET_CONNECT_BE_BINDING)) { |
375 | return anetTcpGenericConnect(err,addr,port,NULL,flags); |
376 | } else { |
377 | return s; |
378 | } |
379 | } |
380 | |
381 | int anetTcpConnect(char *err, const char *addr, int port) |
382 | { |
383 | return anetTcpGenericConnect(err,addr,port,NULL,ANET_CONNECT_NONE); |
384 | } |
385 | |
386 | int anetTcpNonBlockConnect(char *err, const char *addr, int port) |
387 | { |
388 | return anetTcpGenericConnect(err,addr,port,NULL,ANET_CONNECT_NONBLOCK); |
389 | } |
390 | |
391 | int anetTcpNonBlockBindConnect(char *err, const char *addr, int port, |
392 | const char *source_addr) |
393 | { |
394 | return anetTcpGenericConnect(err,addr,port,source_addr, |
395 | ANET_CONNECT_NONBLOCK); |
396 | } |
397 | |
398 | int anetTcpNonBlockBestEffortBindConnect(char *err, const char *addr, int port, |
399 | const char *source_addr) |
400 | { |
401 | return anetTcpGenericConnect(err,addr,port,source_addr, |
402 | ANET_CONNECT_NONBLOCK|ANET_CONNECT_BE_BINDING); |
403 | } |
404 | |
405 | int anetUnixGenericConnect(char *err, const char *path, int flags) |
406 | { |
407 | int s; |
408 | struct sockaddr_un sa; |
409 | |
410 | if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR) |
411 | return ANET_ERR; |
412 | |
413 | sa.sun_family = AF_LOCAL; |
414 | strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); |
415 | if (flags & ANET_CONNECT_NONBLOCK) { |
416 | if (anetNonBlock(err,s) != ANET_OK) { |
417 | close(s); |
418 | return ANET_ERR; |
419 | } |
420 | } |
421 | if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) == -1) { |
422 | if (errno == EINPROGRESS && |
423 | flags & ANET_CONNECT_NONBLOCK) |
424 | return s; |
425 | |
426 | anetSetError(err, "connect: %s", strerror(errno)); |
427 | close(s); |
428 | return ANET_ERR; |
429 | } |
430 | return s; |
431 | } |
432 | |
433 | int anetUnixConnect(char *err, const char *path) |
434 | { |
435 | return anetUnixGenericConnect(err,path,ANET_CONNECT_NONE); |
436 | } |
437 | |
438 | int anetUnixNonBlockConnect(char *err, const char *path) |
439 | { |
440 | return anetUnixGenericConnect(err,path,ANET_CONNECT_NONBLOCK); |
441 | } |
442 | |
443 | |
444 | |
445 | int anetRead(int fd, char *buf, int count) |
446 | { |
447 | ssize_t nread, totlen = 0; |
448 | while(totlen != count) { |
449 | nread = read(fd,buf,count-totlen); |
450 | if (nread == 0) return totlen; |
451 | if (nread == -1) return -1; |
452 | totlen += nread; |
453 | buf += nread; |
454 | } |
455 | return totlen; |
456 | } |
457 | |
458 | |
459 | |
460 | int anetWrite(int fd, char *buf, int count) |
461 | { |
462 | ssize_t nwritten, totlen = 0; |
463 | while(totlen != count) { |
464 | nwritten = write(fd,buf,count-totlen); |
465 | if (nwritten == 0) return totlen; |
466 | if (nwritten == -1) return -1; |
467 | totlen += nwritten; |
468 | buf += nwritten; |
469 | } |
470 | return totlen; |
471 | } |
472 | |
473 | static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len, int backlog) { |
474 | if (bind(s,sa,len) == -1) { |
475 | anetSetError(err, "bind: %s", strerror(errno)); |
476 | close(s); |
477 | return ANET_ERR; |
478 | } |
479 | |
480 | if (listen(s, backlog) == -1) { |
481 | anetSetError(err, "listen: %s", strerror(errno)); |
482 | close(s); |
483 | return ANET_ERR; |
484 | } |
485 | return ANET_OK; |
486 | } |
487 | |
488 | static int anetV6Only(char *err, int s) { |
489 | int yes = 1; |
490 | if (setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,&yes,sizeof(yes)) == -1) { |
491 | anetSetError(err, "setsockopt: %s", strerror(errno)); |
492 | return ANET_ERR; |
493 | } |
494 | return ANET_OK; |
495 | } |
496 | |
497 | static int _anetTcpServer(char *err, int port, char *bindaddr, int af, int backlog) |
498 | { |
499 | int s = -1, rv; |
500 | char _port[6]; |
501 | struct addrinfo hints, *servinfo, *p; |
502 | |
503 | snprintf(_port,6,"%d",port); |
504 | memset(&hints,0,sizeof(hints)); |
505 | hints.ai_family = af; |
506 | hints.ai_socktype = SOCK_STREAM; |
507 | hints.ai_flags = AI_PASSIVE; |
508 | if (bindaddr && !strcmp("*", bindaddr)) |
509 | bindaddr = NULL; |
510 | if (af == AF_INET6 && bindaddr && !strcmp("::*", bindaddr)) |
511 | bindaddr = NULL; |
512 | |
513 | if ((rv = getaddrinfo(bindaddr,_port,&hints,&servinfo)) != 0) { |
514 | anetSetError(err, "%s", gai_strerror(rv)); |
515 | return ANET_ERR; |
516 | } |
517 | for (p = servinfo; p != NULL; p = p->ai_next) { |
518 | if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) |
519 | continue; |
520 | |
521 | if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error; |
522 | if (anetSetReuseAddr(err,s) == ANET_ERR) goto error; |
523 | if (anetListen(err,s,p->ai_addr,p->ai_addrlen,backlog) == ANET_ERR) s = ANET_ERR; |
524 | goto end; |
525 | } |
526 | if (p == NULL) { |
527 | anetSetError(err, "unable to bind socket, errno: %d", errno); |
528 | goto error; |
529 | } |
530 | |
531 | error: |
532 | if (s != -1) close(s); |
533 | s = ANET_ERR; |
534 | end: |
535 | freeaddrinfo(servinfo); |
536 | return s; |
537 | } |
538 | |
539 | int anetTcpServer(char *err, int port, char *bindaddr, int backlog) |
540 | { |
541 | return _anetTcpServer(err, port, bindaddr, AF_INET, backlog); |
542 | } |
543 | |
544 | int anetTcp6Server(char *err, int port, char *bindaddr, int backlog) |
545 | { |
546 | return _anetTcpServer(err, port, bindaddr, AF_INET6, backlog); |
547 | } |
548 | |
549 | int anetUnixServer(char *err, char *path, mode_t perm, int backlog) |
550 | { |
551 | int s; |
552 | struct sockaddr_un sa; |
553 | |
554 | if ((s = anetCreateSocket(err,AF_LOCAL)) == ANET_ERR) |
555 | return ANET_ERR; |
556 | |
557 | memset(&sa,0,sizeof(sa)); |
558 | sa.sun_family = AF_LOCAL; |
559 | strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); |
560 | if (anetListen(err,s,(struct sockaddr*)&sa,sizeof(sa),backlog) == ANET_ERR) |
561 | return ANET_ERR; |
562 | if (perm) |
563 | chmod(sa.sun_path, perm); |
564 | return s; |
565 | } |
566 | |
567 | static int anetGenericAccept(char *err, int s, struct sockaddr *sa, socklen_t *len) { |
568 | int fd; |
569 | while(1) { |
570 | fd = accept(s,sa,len); |
571 | if (fd == -1) { |
572 | if (errno == EINTR) |
573 | continue; |
574 | else { |
575 | anetSetError(err, "accept: %s", strerror(errno)); |
576 | return ANET_ERR; |
577 | } |
578 | } |
579 | break; |
580 | } |
581 | return fd; |
582 | } |
583 | |
584 | int anetTcpAccept(char *err, int s, char *ip, size_t ip_len, int *port) { |
585 | int fd; |
586 | struct sockaddr_storage sa; |
587 | socklen_t salen = sizeof(sa); |
588 | if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == -1) |
589 | return ANET_ERR; |
590 | |
591 | if (sa.ss_family == AF_INET) { |
592 | struct sockaddr_in *s = (struct sockaddr_in *)&sa; |
593 | if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len); |
594 | if (port) *port = ntohs(s->sin_port); |
595 | } else { |
596 | struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa; |
597 | if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len); |
598 | if (port) *port = ntohs(s->sin6_port); |
599 | } |
600 | return fd; |
601 | } |
602 | |
603 | int anetUnixAccept(char *err, int s) { |
604 | int fd; |
605 | struct sockaddr_un sa; |
606 | socklen_t salen = sizeof(sa); |
607 | if ((fd = anetGenericAccept(err,s,(struct sockaddr*)&sa,&salen)) == -1) |
608 | return ANET_ERR; |
609 | |
610 | return fd; |
611 | } |
612 | |
613 | int anetFdToString(int fd, char *ip, size_t ip_len, int *port, int fd_to_str_type) { |
614 | struct sockaddr_storage sa; |
615 | socklen_t salen = sizeof(sa); |
616 | |
617 | if (fd_to_str_type == FD_TO_PEER_NAME) { |
| 2 | | Assuming 'fd_to_str_type' is not equal to FD_TO_PEER_NAME | |
|
| |
618 | if (getpeername(fd, (struct sockaddr *)&sa, &salen) == -1) goto error; |
619 | } else { |
620 | if (getsockname(fd, (struct sockaddr *)&sa, &salen) == -1) goto error; |
| 4 | | Assuming the condition is false | |
|
| |
621 | } |
622 | if (ip_len == 0) goto error; |
| |
623 | |
624 | if (sa.ss_family == AF_INET) { |
| 7 | | The left operand of '==' is a garbage value |
|
625 | struct sockaddr_in *s = (struct sockaddr_in *)&sa; |
626 | if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len); |
627 | if (port) *port = ntohs(s->sin_port); |
628 | } else if (sa.ss_family == AF_INET6) { |
629 | struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa; |
630 | if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len); |
631 | if (port) *port = ntohs(s->sin6_port); |
632 | } else if (sa.ss_family == AF_UNIX) { |
633 | if (ip) snprintf(ip, ip_len, "/unixsocket"); |
634 | if (port) *port = 0; |
635 | } else { |
636 | goto error; |
637 | } |
638 | return 0; |
639 | |
640 | error: |
641 | if (ip) { |
642 | if (ip_len >= 2) { |
643 | ip[0] = '?'; |
644 | ip[1] = '\0'; |
645 | } else if (ip_len == 1) { |
646 | ip[0] = '\0'; |
647 | } |
648 | } |
649 | if (port) *port = 0; |
650 | return -1; |
651 | } |
652 | |
653 | |
654 | |
655 | |
656 | int anetFormatAddr(char *buf, size_t buf_len, char *ip, int port) { |
657 | return snprintf(buf,buf_len, strchr(ip,':') ? |
658 | "[%s]:%d" : "%s:%d", ip, port); |
659 | } |
660 | |
661 | |
662 | int anetFormatFdAddr(int fd, char *buf, size_t buf_len, int fd_to_str_type) { |
663 | char ip[INET6_ADDRSTRLEN]; |
664 | int port; |
665 | |
666 | anetFdToString(fd,ip,sizeof(ip),&port,fd_to_str_type); |
| 1 | Calling 'anetFdToString' | |
|
667 | return anetFormatAddr(buf, buf_len, ip, port); |
668 | } |