1 /* Copyright (c) 1999-2018 Dovecot authors, see the included COPYING file */
2
3 #define _GNU_SOURCE /* For Linux's struct ucred */
4 #include "lib.h"
5 #include "time-util.h"
6 #include "net.h"
7
8 #include <unistd.h>
9 #include <fcntl.h>
10 #include <ctype.h>
11 #include <sys/un.h>
12 #include <netinet/tcp.h>
13 #if defined(HAVE_UCRED_H)
14 # include <ucred.h> /* for getpeerucred() */
15 #elif defined(HAVE_SYS_UCRED_H)
16 # include <sys/ucred.h> /* for FreeBSD struct xucred */
17 #endif
18
19 union sockaddr_union {
20 struct sockaddr sa;
21 struct sockaddr_in sin;
22 struct sockaddr_in6 sin6;
23 };
24
25 union sockaddr_union_unix {
26 struct sockaddr sa;
27 struct sockaddr_un un;
28 };
29
30 #define SIZEOF_SOCKADDR(so) ((so).sa.sa_family == AF_INET6 ? \
31 sizeof(so.sin6) : sizeof(so.sin))
32
33 #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_GETPEERUCRED) && defined(MSG_WAITALL) && defined(LOCAL_CREDS)
34 # define NEEDS_LOCAL_CREDS 1
35 #else
36 # undef NEEDS_LOCAL_CREDS
37 #endif
38
39 /* If connect() fails with EADDRNOTAVAIL (or some others on FreeBSD), retry it
40 this many times.
41
42 This is needed on busy systems kernel may assign the same source port to two
43 sockets at bind() stage, which is what we generally want to allow more than
44 64k outgoing connections to different destinations. However, at bind() stage
45 the kernel doesn't know the destination yet. So it's possible that it
46 assigns the same source port to two (or more) sockets that have the same
47 destination IP+port as well. In this case connect() will fail with
48 EADDRNOTAVAIL. We'll need to retry this and hope that the next attempt won't
49 conflict. */
50 #define MAX_CONNECT_RETRIES 20
51
net_ip_compare(const struct ip_addr * ip1,const struct ip_addr * ip2)52 bool net_ip_compare(const struct ip_addr *ip1, const struct ip_addr *ip2)
53 {
54 return net_ip_cmp(ip1, ip2) == 0;
55 }
56
net_ip_cmp(const struct ip_addr * ip1,const struct ip_addr * ip2)57 int net_ip_cmp(const struct ip_addr *ip1, const struct ip_addr *ip2)
58 {
59 if (ip1->family != ip2->family)
60 return ip1->family - ip2->family;
61
62 switch (ip1->family) {
63 case AF_INET6:
64 return memcmp(&ip1->u.ip6, &ip2->u.ip6, sizeof(ip1->u.ip6));
65 case AF_INET:
66 return memcmp(&ip1->u.ip4, &ip2->u.ip4, sizeof(ip1->u.ip4));
67 default:
68 break;
69 }
70 return 0;
71 }
72
net_ip_hash(const struct ip_addr * ip)73 unsigned int net_ip_hash(const struct ip_addr *ip)
74 {
75 const unsigned char *p;
76 unsigned int len, g, h = 0;
77
78 if (ip->family == AF_INET6) {
79 p = ip->u.ip6.s6_addr;
80 len = sizeof(ip->u.ip6);
81 } else
82 {
83 return ip->u.ip4.s_addr;
84 }
85
86 for (; len > 0; len--, p++) {
87 h = (h << 4) + *p;
88 if ((g = h & 0xf0000000UL) != 0) {
89 h = h ^ (g >> 24);
90 h = h ^ g;
91 }
92 }
93
94 return h;
95 }
96
97 /* copy IP to sockaddr */
98 static inline void
sin_set_ip(union sockaddr_union * so,const struct ip_addr * ip)99 sin_set_ip(union sockaddr_union *so, const struct ip_addr *ip)
100 {
101 if (ip == NULL) {
102 so->sin6.sin6_family = AF_INET6;
103 so->sin6.sin6_addr = in6addr_any;
104 return;
105 }
106
107 so->sin.sin_family = ip->family;
108 if (ip->family == AF_INET6)
109 memcpy(&so->sin6.sin6_addr, &ip->u.ip6, sizeof(ip->u.ip6));
110 else
111 memcpy(&so->sin.sin_addr, &ip->u.ip4, sizeof(ip->u.ip4));
112 }
113
114 static inline void
sin_get_ip(const union sockaddr_union * so,struct ip_addr * ip)115 sin_get_ip(const union sockaddr_union *so, struct ip_addr *ip)
116 {
117 /* IP structs may be sent across processes. Clear the whole struct
118 first to make sure it won't leak any data across processes. */
119 i_zero(ip);
120
121 ip->family = so->sin.sin_family;
122
123 if (ip->family == AF_INET6)
124 memcpy(&ip->u.ip6, &so->sin6.sin6_addr, sizeof(ip->u.ip6));
125 else
126 if (ip->family == AF_INET)
127 memcpy(&ip->u.ip4, &so->sin.sin_addr, sizeof(ip->u.ip4));
128 else
129 i_zero(&ip->u);
130 }
131
sin_set_port(union sockaddr_union * so,in_port_t port)132 static inline void sin_set_port(union sockaddr_union *so, in_port_t port)
133 {
134 if (so->sin.sin_family == AF_INET6)
135 so->sin6.sin6_port = htons(port);
136 else
137 so->sin.sin_port = htons(port);
138 }
139
sin_get_port(union sockaddr_union * so)140 static inline in_port_t sin_get_port(union sockaddr_union *so)
141 {
142 if (so->sin.sin_family == AF_INET6)
143 return ntohs(so->sin6.sin6_port);
144 if (so->sin.sin_family == AF_INET)
145 return ntohs(so->sin.sin_port);
146
147 return 0;
148 }
149
net_connect_ip_once(const struct ip_addr * ip,in_port_t port,const struct ip_addr * my_ip,int sock_type,bool blocking)150 static int net_connect_ip_once(const struct ip_addr *ip, in_port_t port,
151 const struct ip_addr *my_ip, int sock_type, bool blocking)
152 {
153 union sockaddr_union so;
154 int fd, ret, opt = 1;
155
156 if (my_ip != NULL && ip->family != my_ip->family) {
157 i_warning("net_connect_ip(): ip->family != my_ip->family");
158 my_ip = NULL;
159 }
160
161 /* create the socket */
162 i_zero(&so);
163 so.sin.sin_family = ip->family;
164 fd = socket(ip->family, sock_type, 0);
165
166 if (fd == -1) {
167 i_error("socket() failed: %m");
168 return -1;
169 }
170
171 /* set socket options */
172 (void)setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
173 if (sock_type == SOCK_STREAM)
174 (void)setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt));
175 if (!blocking)
176 net_set_nonblock(fd, TRUE);
177
178 /* set our own address */
179 if (my_ip != NULL) {
180 sin_set_ip(&so, my_ip);
181 if (bind(fd, &so.sa, SIZEOF_SOCKADDR(so)) == -1) {
182 i_error("bind(%s) failed: %m", net_ip2addr(my_ip));
183 i_close_fd(&fd);
184 return -1;
185 }
186 }
187
188 /* connect */
189 sin_set_ip(&so, ip);
190 sin_set_port(&so, port);
191 ret = connect(fd, &so.sa, SIZEOF_SOCKADDR(so));
192
193 #ifndef WIN32
194 if (ret < 0 && errno != EINPROGRESS)
195 #else
196 if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
197 #endif
198 {
199 i_close_fd(&fd);
200 return -1;
201 }
202
203 return fd;
204 }
205
net_connect_ip_full(const struct ip_addr * ip,in_port_t port,const struct ip_addr * my_ip,int sock_type,bool blocking)206 static int net_connect_ip_full(const struct ip_addr *ip, in_port_t port,
207 const struct ip_addr *my_ip, int sock_type,
208 bool blocking)
209 {
210 int fd, try;
211
212 for (try = 0;;) {
213 fd = net_connect_ip_once(ip, port, my_ip, sock_type, blocking);
214 if (fd != -1 || try++ >= MAX_CONNECT_RETRIES ||
215 (errno != EADDRNOTAVAIL
216 #ifdef __FreeBSD__
217 /* busy */
218 && errno != EADDRINUSE
219 /* pf may cause this if another connection used
220 the same port recently */
221 && errno != EACCES
222 #endif
223 ))
224 break;
225 }
226 return fd;
227 }
228
net_connect_ip(const struct ip_addr * ip,in_port_t port,const struct ip_addr * my_ip)229 int net_connect_ip(const struct ip_addr *ip, in_port_t port,
230 const struct ip_addr *my_ip)
231 {
232 return net_connect_ip_full(ip, port, my_ip, SOCK_STREAM, FALSE);
233 }
234
net_connect_ip_blocking(const struct ip_addr * ip,in_port_t port,const struct ip_addr * my_ip)235 int net_connect_ip_blocking(const struct ip_addr *ip, in_port_t port,
236 const struct ip_addr *my_ip)
237 {
238 return net_connect_ip_full(ip, port, my_ip, SOCK_STREAM, TRUE);
239 }
240
net_connect_udp(const struct ip_addr * ip,in_port_t port,const struct ip_addr * my_ip)241 int net_connect_udp(const struct ip_addr *ip, in_port_t port,
242 const struct ip_addr *my_ip)
243 {
244 return net_connect_ip_full(ip, port, my_ip, SOCK_DGRAM, FALSE);
245 }
246
net_try_bind(const struct ip_addr * ip)247 int net_try_bind(const struct ip_addr *ip)
248 {
249 union sockaddr_union so;
250 int fd;
251
252 /* create the socket */
253 i_zero(&so);
254 so.sin.sin_family = ip->family;
255 fd = socket(ip->family, SOCK_STREAM, 0);
256 if (fd == -1) {
257 i_error("socket() failed: %m");
258 return -1;
259 }
260
261 sin_set_ip(&so, ip);
262 if (bind(fd, &so.sa, SIZEOF_SOCKADDR(so)) == -1) {
263 i_close_fd(&fd);
264 return -1;
265 }
266 i_close_fd(&fd);
267 return 0;
268 }
269
net_connect_unix(const char * path)270 int net_connect_unix(const char *path)
271 {
272 union sockaddr_union_unix sa;
273 int fd, ret;
274
275 i_zero(&sa);
276 sa.un.sun_family = AF_UNIX;
277 if (i_strocpy(sa.un.sun_path, path, sizeof(sa.un.sun_path)) < 0) {
278 /* too long path */
279 #ifdef ENAMETOOLONG
280 errno = ENAMETOOLONG;
281 #else
282 errno = EOVERFLOW;
283 #endif
284 return -1;
285 }
286
287 /* create the socket */
288 fd = socket(PF_UNIX, SOCK_STREAM, 0);
289 if (fd == -1) {
290 i_error("socket(%s) failed: %m", path);
291 return -1;
292 }
293
294 net_set_nonblock(fd, TRUE);
295
296 /* connect */
297 ret = connect(fd, &sa.sa, sizeof(sa));
298 if (ret < 0 && errno != EINPROGRESS) {
299 i_close_fd(&fd);
300 return -1;
301 }
302
303 #ifdef NEEDS_LOCAL_CREDS
304 {
305 int on = 1;
306 if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof on)) {
307 i_error("setsockopt(LOCAL_CREDS) failed: %m");
308 return -1;
309 }
310 }
311 #endif
312
313 return fd;
314 }
315
net_connect_unix_with_retries(const char * path,unsigned int msecs)316 int net_connect_unix_with_retries(const char *path, unsigned int msecs)
317 {
318 struct timeval start, now;
319 int fd;
320
321 i_gettimeofday(&start);
322
323 do {
324 fd = net_connect_unix(path);
325 if (fd != -1 || (errno != EAGAIN && errno != ECONNREFUSED))
326 break;
327
328 /* busy. wait for a while. */
329 usleep(i_rand_minmax(1, 10) * 10000);
330 i_gettimeofday(&now);
331 } while (timeval_diff_msecs(&now, &start) < (int)msecs);
332 return fd;
333 }
334
net_disconnect(int fd)335 void net_disconnect(int fd)
336 {
337 /* FreeBSD's close() fails with ECONNRESET if socket still has unsent
338 data in transmit buffer. We don't care. */
339 if (close(fd) < 0 && errno != ECONNRESET)
340 i_error("net_disconnect() failed: %m");
341 }
342
net_set_nonblock(int fd,bool nonblock)343 void net_set_nonblock(int fd, bool nonblock)
344 {
345 fd_set_nonblock(fd, nonblock);
346 }
347
net_set_cork(int fd ATTR_UNUSED,bool cork ATTR_UNUSED)348 int net_set_cork(int fd ATTR_UNUSED, bool cork ATTR_UNUSED)
349 {
350 #ifdef TCP_CORK
351 int val = cork;
352
353 return setsockopt(fd, IPPROTO_TCP, TCP_CORK, &val, sizeof(val));
354 #else
355 errno = ENOPROTOOPT;
356 return -1;
357 #endif
358 }
359
net_set_tcp_nodelay(int fd,bool nodelay)360 int net_set_tcp_nodelay(int fd, bool nodelay)
361 {
362 int val = nodelay;
363
364 return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
365 }
366
net_set_tcp_quickack(int fd ATTR_UNUSED,bool quickack ATTR_UNUSED)367 int net_set_tcp_quickack(int fd ATTR_UNUSED, bool quickack ATTR_UNUSED)
368 {
369 #ifdef TCP_QUICKACK
370 int val = quickack;
371
372 return setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &val, sizeof(val));
373 #else
374 errno = ENOPROTOOPT;
375 return -1;
376 #endif
377 }
378
net_set_send_buffer_size(int fd,size_t size)379 int net_set_send_buffer_size(int fd, size_t size)
380 {
381 int opt;
382
383 if (size > INT_MAX) {
384 errno = EINVAL;
385 return -1;
386 }
387 opt = (int)size;
388 return setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt));
389 }
390
net_set_recv_buffer_size(int fd,size_t size)391 int net_set_recv_buffer_size(int fd, size_t size)
392 {
393 int opt;
394
395 if (size > INT_MAX) {
396 errno = EINVAL;
397 return -1;
398 }
399 opt = (int)size;
400 return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
401 }
402
403 const struct ip_addr net_ip4_any = {
404 .family = AF_INET,
405 .u.ip4.s_addr = INADDR_ANY
406 };
407
408 const struct ip_addr net_ip6_any = {
409 .family = AF_INET6,
410 .u.ip6 = IN6ADDR_ANY_INIT
411 };
412
413 const struct ip_addr net_ip4_loopback = {
414 .family = AF_INET,
415 .u.ip4.s_addr = INADDR_LOOPBACK
416 };
417
418 const struct ip_addr net_ip6_loopback = {
419 .family = AF_INET6,
420 .u.ip6 = IN6ADDR_LOOPBACK_INIT
421 };
422
net_listen(const struct ip_addr * my_ip,in_port_t * port,int backlog)423 int net_listen(const struct ip_addr *my_ip, in_port_t *port, int backlog)
424 {
425 enum net_listen_flags flags = 0;
426
427 return net_listen_full(my_ip, port, &flags, backlog);
428 }
429
net_listen_full(const struct ip_addr * my_ip,in_port_t * port,enum net_listen_flags * flags,int backlog)430 int net_listen_full(const struct ip_addr *my_ip, in_port_t *port,
431 enum net_listen_flags *flags, int backlog)
432 {
433 union sockaddr_union so;
434 int ret, fd, opt = 1;
435 socklen_t len;
436
437 i_zero(&so);
438 sin_set_port(&so, *port);
439 sin_set_ip(&so, my_ip);
440
441 /* create the socket */
442 fd = socket(so.sin.sin_family, SOCK_STREAM, 0);
443 if (fd == -1 && my_ip == NULL &&
444 (errno == EINVAL || errno == EAFNOSUPPORT)) {
445 /* IPv6 is not supported by OS */
446 so.sin.sin_family = AF_INET;
447 so.sin.sin_addr.s_addr = INADDR_ANY;
448
449 fd = socket(AF_INET, SOCK_STREAM, 0);
450 }
451 if (fd == -1) {
452 i_error("socket() failed: %m");
453 return -1;
454 }
455
456 /* set socket options */
457 (void)setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
458 (void)setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(opt));
459
460 if ((*flags & NET_LISTEN_FLAG_REUSEPORT) != 0) {
461 #ifdef SO_REUSEPORT
462 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT,
463 &opt, sizeof(opt)) < 0)
464 #endif
465 *flags &= ENUM_NEGATE(NET_LISTEN_FLAG_REUSEPORT);
466 }
467
468 /* If using IPv6, bind only to IPv6 if possible. This avoids
469 ambiguities with IPv4-mapped IPv6 addresses. */
470 #ifdef IPV6_V6ONLY
471 if (so.sin.sin_family == AF_INET6) {
472 opt = 1;
473 (void)setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
474 }
475 #endif
476 /* specify the address/port we want to listen in */
477 ret = bind(fd, &so.sa, SIZEOF_SOCKADDR(so));
478 if (ret < 0) {
479 if (errno != EADDRINUSE) {
480 i_error("bind(%s, %u) failed: %m",
481 my_ip == NULL ? "" : net_ip2addr(my_ip), *port);
482 }
483 } else {
484 /* get the actual port we started listen */
485 len = SIZEOF_SOCKADDR(so);
486 ret = getsockname(fd, &so.sa, &len);
487 if (ret >= 0) {
488 *port = sin_get_port(&so);
489
490 /* start listening */
491 if (listen(fd, backlog) >= 0)
492 return fd;
493
494 if (errno != EADDRINUSE)
495 i_error("listen() failed: %m");
496 }
497 }
498
499 /* error */
500 i_close_fd(&fd);
501 return -1;
502 }
503
net_listen_unix(const char * path,int backlog)504 int net_listen_unix(const char *path, int backlog)
505 {
506 union {
507 struct sockaddr sa;
508 struct sockaddr_un un;
509 } sa;
510 int fd;
511
512 i_zero(&sa);
513 sa.un.sun_family = AF_UNIX;
514 if (i_strocpy(sa.un.sun_path, path, sizeof(sa.un.sun_path)) < 0) {
515 /* too long path */
516 #ifdef ENAMETOOLONG
517 errno = ENAMETOOLONG;
518 #else
519 errno = EOVERFLOW;
520 #endif
521 return -1;
522 }
523
524 /* create the socket */
525 fd = socket(PF_UNIX, SOCK_STREAM, 0);
526 if (fd == -1) {
527 i_error("socket() failed: %m");
528 return -1;
529 }
530
531 #ifdef NEEDS_LOCAL_CREDS
532 {
533 int on = 1;
534 if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof on)) {
535 i_error("setsockopt(LOCAL_CREDS) failed: %m");
536 return -1;
537 }
538 }
539 #endif
540
541 /* bind */
542 if (bind(fd, &sa.sa, sizeof(sa)) < 0) {
543 if (errno != EADDRINUSE)
544 i_error("bind(%s) failed: %m", path);
545 } else {
546 /* start listening */
547 if (listen(fd, backlog) == 0)
548 return fd;
549
550 if (errno != EADDRINUSE)
551 i_error("listen() failed: %m");
552 }
553
554 i_close_fd(&fd);
555 return -1;
556 }
557
net_listen_unix_unlink_stale(const char * path,int backlog)558 int net_listen_unix_unlink_stale(const char *path, int backlog)
559 {
560 unsigned int i = 0;
561 int fd;
562
563 while ((fd = net_listen_unix(path, backlog)) == -1) {
564 if (errno != EADDRINUSE || ++i == 2)
565 return -1;
566
567 /* see if it really exists */
568 fd = net_connect_unix(path);
569 if (fd != -1 || errno != ECONNREFUSED) {
570 i_close_fd(&fd);
571 errno = EADDRINUSE;
572 return -1;
573 }
574
575 /* delete and try again */
576 if (i_unlink_if_exists(path) < 0) {
577 errno = EADDRINUSE;
578 return -1;
579 }
580 }
581 return fd;
582 }
583
net_accept(int fd,struct ip_addr * addr_r,in_port_t * port_r)584 int net_accept(int fd, struct ip_addr *addr_r, in_port_t *port_r)
585 {
586 union sockaddr_union so;
587 int ret;
588 socklen_t addrlen;
589
590 i_assert(fd >= 0);
591
592 i_zero(&so);
593 addrlen = sizeof(so);
594 ret = accept(fd, &so.sa, &addrlen);
595
596 if (ret < 0) {
597 if (errno == EAGAIN || errno == ECONNABORTED)
598 return -1;
599 else
600 return -2;
601 }
602 if (so.sin.sin_family == AF_UNIX) {
603 if (addr_r != NULL)
604 i_zero(addr_r);
605 if (port_r != NULL) *port_r = 0;
606 } else {
607 if (addr_r != NULL) sin_get_ip(&so, addr_r);
608 if (port_r != NULL) *port_r = sin_get_port(&so);
609 }
610 return ret;
611 }
612
net_receive(int fd,void * buf,size_t len)613 ssize_t net_receive(int fd, void *buf, size_t len)
614 {
615 ssize_t ret;
616
617 i_assert(fd >= 0);
618 i_assert(len <= SSIZE_T_MAX);
619
620 ret = read(fd, buf, len);
621 if (ret == 0) {
622 /* disconnected */
623 errno = 0;
624 return -2;
625 }
626
627 if (unlikely(ret < 0)) {
628 if (errno == EINTR || errno == EAGAIN)
629 return 0;
630
631 if (errno == ECONNRESET || errno == ETIMEDOUT) {
632 /* treat as disconnection */
633 return -2;
634 }
635 }
636
637 return ret;
638 }
639
net_gethostbyname(const char * addr,struct ip_addr ** ips,unsigned int * ips_count)640 int net_gethostbyname(const char *addr, struct ip_addr **ips,
641 unsigned int *ips_count)
642 {
643 /* @UNSAFE */
644 union sockaddr_union *so;
645 struct addrinfo hints, *ai, *origai;
646 struct ip_addr ip;
647 int host_error;
648 int count;
649
650 *ips = NULL;
651 *ips_count = 0;
652
653 /* support [ipv6] style addresses here so they work globally */
654 if (addr[0] == '[' && net_addr2ip(addr, &ip) == 0) {
655 *ips_count = 1;
656 *ips = t_new(struct ip_addr, 1);
657 **ips = ip;
658 return 0;
659 }
660
661 i_zero(&hints);
662 hints.ai_socktype = SOCK_STREAM;
663
664 /* save error to host_error for later use */
665 host_error = getaddrinfo(addr, NULL, &hints, &ai);
666 if (host_error != 0)
667 return host_error;
668
669 /* get number of IPs */
670 origai = ai;
671 for (count = 0; ai != NULL; ai = ai->ai_next)
672 count++;
673
674 *ips_count = count;
675 *ips = t_new(struct ip_addr, count);
676
677 count = 0;
678 for (ai = origai; ai != NULL; ai = ai->ai_next, count++) {
679 so = (union sockaddr_union *) ai->ai_addr;
680
681 sin_get_ip(so, &(*ips)[count]);
682 }
683 freeaddrinfo(origai);
684
685 return 0;
686 }
687
net_gethostbyaddr(const struct ip_addr * ip,const char ** name_r)688 int net_gethostbyaddr(const struct ip_addr *ip, const char **name_r)
689 {
690 union sockaddr_union so;
691 socklen_t addrlen = sizeof(so);
692 char hbuf[NI_MAXHOST];
693 int ret;
694
695 i_zero(&so);
696 sin_set_ip(&so, ip);
697 ret = getnameinfo(&so.sa, addrlen, hbuf, sizeof(hbuf), NULL, 0,
698 NI_NAMEREQD);
699 if (ret != 0)
700 return ret;
701
702 *name_r = t_strdup(hbuf);
703 return 0;
704 }
705
net_getsockname(int fd,struct ip_addr * addr,in_port_t * port)706 int net_getsockname(int fd, struct ip_addr *addr, in_port_t *port)
707 {
708 union sockaddr_union so;
709 socklen_t addrlen;
710
711 i_assert(fd >= 0);
712
713 i_zero(&so);
714 addrlen = sizeof(so);
715 if (getsockname(fd, &so.sa, &addrlen) == -1)
716 return -1;
717 if (so.sin.sin_family == AF_UNIX) {
718 if (addr != NULL)
719 i_zero(addr);
720 if (port != NULL) *port = 0;
721 } else {
722 if (addr != NULL) sin_get_ip(&so, addr);
723 if (port != NULL) *port = sin_get_port(&so);
724 }
725 return 0;
726 }
727
net_getpeername(int fd,struct ip_addr * addr,in_port_t * port)728 int net_getpeername(int fd, struct ip_addr *addr, in_port_t *port)
729 {
730 union sockaddr_union so;
731 socklen_t addrlen;
732
733 i_assert(fd >= 0);
734
735 i_zero(&so);
736 addrlen = sizeof(so);
737 if (getpeername(fd, &so.sa, &addrlen) == -1)
738 return -1;
739 if (so.sin.sin_family == AF_UNIX) {
740 if (addr != NULL)
741 i_zero(addr);
742 if (port != NULL) *port = 0;
743 } else {
744 if (addr != NULL) sin_get_ip(&so, addr);
745 if (port != NULL) *port = sin_get_port(&so);
746 }
747 return 0;
748 }
749
net_getunixname(int fd,const char ** name_r)750 int net_getunixname(int fd, const char **name_r)
751 {
752 union sockaddr_union_unix so;
753 socklen_t addrlen = sizeof(so);
754
755 i_zero(&so);
756 if (getsockname(fd, &so.sa, &addrlen) < 0)
757 return -1;
758 if (so.un.sun_family != AF_UNIX) {
759 errno = ENOTSOCK;
760 return -1;
761 }
762 *name_r = t_strdup(so.un.sun_path);
763 return 0;
764 }
765
net_getunixcred(int fd,struct net_unix_cred * cred_r)766 int net_getunixcred(int fd, struct net_unix_cred *cred_r)
767 {
768 #if defined(SO_PEERCRED)
769 # if defined(HAVE_STRUCT_SOCKPEERCRED)
770 /* OpenBSD (may also provide getpeereid, but we also want pid) */
771 struct sockpeercred ucred;
772 # else
773 /* Linux */
774 struct ucred ucred;
775 # endif
776 socklen_t len = sizeof(ucred);
777
778 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) {
779 i_error("getsockopt(SO_PEERCRED) failed: %m");
780 return -1;
781 }
782 cred_r->uid = ucred.uid;
783 cred_r->gid = ucred.gid;
784 cred_r->pid = ucred.pid;
785 return 0;
786 #elif defined(LOCAL_PEEREID)
787 /* NetBSD (may also provide getpeereid, but we also want pid) */
788 struct unpcbid ucred;
789 socklen_t len = sizeof(ucred);
790
791 if (getsockopt(fd, 0, LOCAL_PEEREID, &ucred, &len) < 0) {
792 i_error("getsockopt(LOCAL_PEEREID) failed: %m");
793 return -1;
794 }
795
796 cred_r->uid = ucred.unp_euid;
797 cred_r->gid = ucred.unp_egid;
798 cred_r->pid = ucred.unp_pid;
799 return 0;
800 #elif defined(HAVE_GETPEEREID)
801 /* OSX 10.4+, FreeBSD 4.6+, OpenBSD 3.0+, NetBSD 5.0+ */
802 if (getpeereid(fd, &cred_r->uid, &cred_r->gid) < 0) {
803 i_error("getpeereid() failed: %m");
804 return -1;
805 }
806 cred_r->pid = (pid_t)-1;
807 return 0;
808 #elif defined(LOCAL_PEERCRED)
809 /* Older FreeBSD */
810 struct xucred ucred;
811 socklen_t len = sizeof(ucred);
812
813 if (getsockopt(fd, 0, LOCAL_PEERCRED, &ucred, &len) < 0) {
814 i_error("getsockopt(LOCAL_PEERCRED) failed: %m");
815 return -1;
816 }
817
818 if (ucred.cr_version != XUCRED_VERSION) {
819 errno = EINVAL;
820 return -1;
821 }
822
823 cred_r->uid = ucred.cr_uid;
824 cred_r->gid = ucred.cr_gid;
825 cred_r->pid = (pid_t)-1;
826 return 0;
827 #elif defined(HAVE_GETPEERUCRED)
828 /* Solaris */
829 ucred_t *ucred = NULL;
830
831 if (getpeerucred(fd, &ucred) < 0) {
832 i_error("getpeerucred() failed: %m");
833 return -1;
834 }
835 cred_r->uid = ucred_geteuid(ucred);
836 cred_r->gid = ucred_getrgid(ucred);
837 cred_r->pid = ucred_getpid(ucred);
838 ucred_free(ucred);
839
840 if (cred_r->uid == (uid_t)-1 ||
841 cred_r->gid == (gid_t)-1) {
842 errno = EINVAL;
843 return -1;
844 }
845 return 0;
846 #elif defined(NEEDS_LOCAL_CREDS)
847 /* NetBSD < 5 */
848 int i, n, on;
849 struct iovec iov;
850 struct msghdr msg;
851 struct {
852 struct cmsghdr ch;
853 char buf[110];
854 } cdata;
855 struct sockcred *sc;
856
857 iov.iov_base = (char *)&on;
858 iov.iov_len = 1;
859
860 sc = (struct sockcred *)cdata.buf;
861 sc->sc_uid = sc->sc_euid = sc->sc_gid = sc->sc_egid = -1;
862 i_zero(&cdata.ch);
863
864 i_zero(&msg);
865
866 msg.msg_iov = &iov;
867 msg.msg_iovlen = 1;
868 msg.msg_control = &cdata;
869 msg.msg_controllen = sizeof(cdata.ch) + sizeof(cdata.buf);
870
871 for (i = 0; i < 10; i++) {
872 n = recvmsg(fd, &msg, MSG_WAITALL | MSG_PEEK);
873 if (n >= 0 || errno != EAGAIN)
874 break;
875 usleep(100);
876 }
877 if (n < 0) {
878 i_error("recvmsg() failed: %m");
879 return -1;
880 }
881 cred_r->uid = sc->sc_euid;
882 cred_r->gid = sc->sc_egid;
883 cred_r->pid = (pid_t)-1;
884 return 0;
885 #else
886 errno = EINVAL;
887 return -1;
888 #endif
889 }
890
net_ip2addr(const struct ip_addr * ip)891 const char *net_ip2addr(const struct ip_addr *ip)
892 {
893 char *addr = t_malloc_no0(MAX_IP_LEN+1);
894
895 if (inet_ntop(ip->family, &ip->u.ip6, addr, MAX_IP_LEN) == NULL)
896 return "";
897
898 return addr;
899 }
900
net_addr2ip_inet4_fast(const char * addr,struct ip_addr * ip)901 static bool net_addr2ip_inet4_fast(const char *addr, struct ip_addr *ip)
902 {
903 uint8_t *saddr = (void *)&ip->u.ip4.s_addr;
904 unsigned int i, num;
905
906 if (str_parse_uint(addr, &num, &addr) < 0)
907 return FALSE;
908 if (*addr == '\0' && num <= 0xffffffff) {
909 /* single-number IPv4 address */
910 ip->u.ip4.s_addr = htonl(num);
911 ip->family = AF_INET;
912 return TRUE;
913 }
914
915 /* try to parse as a.b.c.d */
916 i = 0;
917 for (;;) {
918 if (num >= 256)
919 return FALSE;
920 saddr[i] = num;
921 if (i == 3)
922 break;
923 i++;
924 if (*addr != '.')
925 return FALSE;
926 addr++;
927 if (str_parse_uint(addr, &num, &addr) < 0)
928 return FALSE;
929 }
930 if (*addr != '\0')
931 return FALSE;
932 ip->family = AF_INET;
933 return TRUE;
934 }
935
net_addr2ip(const char * addr,struct ip_addr * ip)936 int net_addr2ip(const char *addr, struct ip_addr *ip)
937 {
938 int ret;
939
940 if (net_addr2ip_inet4_fast(addr, ip))
941 return 0;
942
943 if (strchr(addr, ':') != NULL) {
944 /* IPv6 */
945 T_BEGIN {
946 if (addr[0] == '[') {
947 /* allow [ipv6 addr] */
948 size_t len = strlen(addr);
949 if (addr[len-1] == ']')
950 addr = t_strndup(addr+1, len-2);
951 }
952 ret = inet_pton(AF_INET6, addr, &ip->u.ip6);
953 } T_END;
954 if (ret == 0)
955 return -1;
956 ip->family = AF_INET6;
957 } else {
958 /* IPv4 */
959 if (inet_aton(addr, &ip->u.ip4) == 0)
960 return -1;
961 ip->family = AF_INET;
962 }
963 return 0;
964 }
965
net_str2port(const char * str,in_port_t * port_r)966 int net_str2port(const char *str, in_port_t *port_r)
967 {
968 uintmax_t l;
969
970 if (str_to_uintmax(str, &l) < 0)
971 return -1;
972
973 if (l == 0 || l > (in_port_t)-1)
974 return -1;
975 *port_r = (in_port_t)l;
976 return 0;
977 }
978
net_str2port_zero(const char * str,in_port_t * port_r)979 int net_str2port_zero(const char *str, in_port_t *port_r)
980 {
981 uintmax_t l;
982
983 if (str_to_uintmax(str, &l) < 0)
984 return -1;
985
986 if (l > (in_port_t)-1)
987 return -1;
988 *port_r = (in_port_t)l;
989 return 0;
990 }
991
net_str2hostport(const char * str,in_port_t default_port,const char ** host_r,in_port_t * port_r)992 int net_str2hostport(const char *str, in_port_t default_port,
993 const char **host_r, in_port_t *port_r)
994 {
995 const char *p, *host;
996 in_port_t port;
997
998 if (str[0] == '[') {
999 /* [IPv6] address, possibly followed by :port */
1000 p = strchr(str, ']');
1001 if (p == NULL)
1002 return -1;
1003 host = t_strdup_until(str+1, p++);
1004 } else {
1005 p = strchr(str, ':');
1006 if (p == NULL || strchr(p+1, ':') != NULL) {
1007 /* host or IPv6 address */
1008 *host_r = str;
1009 *port_r = default_port;
1010 return 0;
1011 }
1012 host = t_strdup_until(str, p);
1013 }
1014 if (p[0] == '\0') {
1015 *host_r = host;
1016 *port_r = default_port;
1017 return 0;
1018 }
1019 if (p[0] != ':')
1020 return -1;
1021 if (net_str2port(p+1, &port) < 0)
1022 return -1;
1023 *host_r = host;
1024 *port_r = port;
1025 return 0;
1026 }
1027
net_ipport2str(const struct ip_addr * ip,in_port_t port,const char ** str_r)1028 int net_ipport2str(const struct ip_addr *ip, in_port_t port, const char **str_r)
1029 {
1030 if (!IPADDR_IS_V4(ip) && !IPADDR_IS_V6(ip)) return -1;
1031
1032 *str_r = t_strdup_printf("%s%s%s:%u",
1033 IPADDR_IS_V6(ip) ? "[" : "",
1034 net_ip2addr(ip),
1035 IPADDR_IS_V6(ip) ? "]" : "",
1036 port);
1037 return 0;
1038 }
1039
net_ipv6_mapped_ipv4_convert(const struct ip_addr * src,struct ip_addr * dest)1040 int net_ipv6_mapped_ipv4_convert(const struct ip_addr *src,
1041 struct ip_addr *dest)
1042 {
1043 static uint8_t v4_prefix[] =
1044 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
1045
1046 if (!IPADDR_IS_V6(src))
1047 return -1;
1048 if (memcmp(src->u.ip6.s6_addr, v4_prefix, sizeof(v4_prefix)) != 0)
1049 return -1;
1050
1051 i_zero(dest);
1052 dest->family = AF_INET;
1053 memcpy(&dest->u.ip6, &src->u.ip6.s6_addr[3*4], 4);
1054 return 0;
1055 }
1056
net_geterror(int fd)1057 int net_geterror(int fd)
1058 {
1059 int data;
1060 socklen_t len = sizeof(data);
1061
1062 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &data, &len) == -1) {
1063 /* we're now really returning the getsockopt()'s error code
1064 instead of the socket's, but normally we should never get
1065 here anyway. */
1066 return errno;
1067 }
1068
1069 return data;
1070 }
1071
net_gethosterror(int error)1072 const char *net_gethosterror(int error)
1073 {
1074 i_assert(error != 0);
1075
1076 return gai_strerror(error);
1077 }
1078
net_get_hosterror_type(int error)1079 enum net_hosterror_type net_get_hosterror_type(int error)
1080 {
1081 const struct {
1082 int error;
1083 enum net_hosterror_type type;
1084 } error_map[] = {
1085 #ifdef EAI_ADDRFAMILY /* Obsoleted by RFC 2553bis-02 */
1086 { EAI_ADDRFAMILY, NET_HOSTERROR_TYPE_NOT_FOUND },
1087 #endif
1088 { EAI_AGAIN, NET_HOSTERROR_TYPE_NAMESERVER },
1089 { EAI_BADFLAGS, NET_HOSTERROR_TYPE_INTERNAL_ERROR },
1090 { EAI_FAIL, NET_HOSTERROR_TYPE_NAMESERVER },
1091 { EAI_FAMILY, NET_HOSTERROR_TYPE_INTERNAL_ERROR },
1092 { EAI_MEMORY, NET_HOSTERROR_TYPE_INTERNAL_ERROR },
1093 #ifdef EAI_NODATA /* Obsoleted by RFC 2553bis-02 */
1094 { EAI_NODATA, NET_HOSTERROR_TYPE_NOT_FOUND },
1095 #endif
1096 { EAI_NONAME, NET_HOSTERROR_TYPE_NOT_FOUND },
1097 { EAI_SERVICE, NET_HOSTERROR_TYPE_INTERNAL_ERROR },
1098 { EAI_SOCKTYPE, NET_HOSTERROR_TYPE_INTERNAL_ERROR },
1099 { EAI_SYSTEM, NET_HOSTERROR_TYPE_INTERNAL_ERROR },
1100 };
1101 for (unsigned int i = 0; i < N_ELEMENTS(error_map); i++) {
1102 if (error_map[i].error == error)
1103 return error_map[i].type;
1104 }
1105
1106 /* shouldn't happen? assume internal error */
1107 return NET_HOSTERROR_TYPE_INTERNAL_ERROR;
1108 }
1109
net_hosterror_notfound(int error)1110 int net_hosterror_notfound(int error)
1111 {
1112 #ifdef EAI_NODATA /* NODATA is depricated */
1113 return (error != 1 && (error == EAI_NONAME || error == EAI_NODATA)) ? 1 : 0;
1114 #else
1115 return (error != 1 && (error == EAI_NONAME)) ? 1 : 0;
1116 #endif
1117 }
1118
net_getservbyport(in_port_t port)1119 const char *net_getservbyport(in_port_t port)
1120 {
1121 struct servent *entry;
1122
1123 entry = getservbyport(htons(port), "tcp");
1124 return entry == NULL ? NULL : entry->s_name;
1125 }
1126
is_ipv4_address(const char * addr)1127 bool is_ipv4_address(const char *addr)
1128 {
1129 while (*addr != '\0') {
1130 if (*addr != '.' && !i_isdigit(*addr))
1131 return FALSE;
1132 addr++;
1133 }
1134
1135 return TRUE;
1136 }
1137
is_ipv6_address(const char * addr)1138 bool is_ipv6_address(const char *addr)
1139 {
1140 bool have_prefix = FALSE;
1141
1142 if (*addr == '[') {
1143 have_prefix = TRUE;
1144 addr++;
1145 }
1146 while (*addr != '\0') {
1147 if (*addr != ':' && !i_isxdigit(*addr)) {
1148 if (have_prefix && *addr == ']' && addr[1] == '\0')
1149 break;
1150 return FALSE;
1151 }
1152 addr++;
1153 }
1154
1155 return TRUE;
1156 }
1157
net_parse_range(const char * network,struct ip_addr * ip_r,unsigned int * bits_r)1158 int net_parse_range(const char *network, struct ip_addr *ip_r,
1159 unsigned int *bits_r)
1160 {
1161 const char *p;
1162 unsigned int bits, max_bits;
1163
1164 p = strchr(network, '/');
1165 if (p != NULL)
1166 network = t_strdup_until(network, p++);
1167
1168 if (net_addr2ip(network, ip_r) < 0)
1169 return -1;
1170
1171 max_bits = IPADDR_BITS(ip_r);
1172 if (p == NULL) {
1173 /* full IP address must match */
1174 bits = max_bits;
1175 } else {
1176 /* get the network mask */
1177 if (str_to_uint(p, &bits) < 0 || bits > max_bits)
1178 return -1;
1179 }
1180 *bits_r = bits;
1181 return 0;
1182 }
1183
net_is_in_network(const struct ip_addr * ip,const struct ip_addr * net_ip,unsigned int bits)1184 bool net_is_in_network(const struct ip_addr *ip,
1185 const struct ip_addr *net_ip, unsigned int bits)
1186 {
1187 struct ip_addr tmp_ip;
1188 const uint32_t *ip1, *ip2;
1189 uint32_t mask, i1, i2;
1190 unsigned int pos, i;
1191
1192 if (net_ipv6_mapped_ipv4_convert(ip, &tmp_ip) == 0) {
1193 /* IPv4 address mapped disguised as IPv6 address */
1194 ip = &tmp_ip;
1195 }
1196
1197 if (ip->family == 0 || net_ip->family == 0) {
1198 /* non-IPv4/IPv6 address (e.g. UNIX socket) never matches
1199 anything */
1200 return FALSE;
1201 }
1202 if (IPADDR_IS_V4(ip) != IPADDR_IS_V4(net_ip)) {
1203 /* one is IPv6 and one is IPv4 */
1204 return FALSE;
1205 }
1206 i_assert(IPADDR_IS_V6(ip) == IPADDR_IS_V6(net_ip));
1207
1208 if (IPADDR_IS_V4(ip)) {
1209 ip1 = &ip->u.ip4.s_addr;
1210 ip2 = &net_ip->u.ip4.s_addr;
1211 } else {
1212 ip1 = (const void *)&ip->u.ip6;
1213 ip2 = (const void *)&net_ip->u.ip6;
1214 }
1215
1216 /* check first the full 32bit ints */
1217 for (pos = 0, i = 0; pos + 32 <= bits; pos += 32, i++) {
1218 if (ip1[i] != ip2[i])
1219 return FALSE;
1220 }
1221 i1 = htonl(ip1[i]);
1222 i2 = htonl(ip2[i]);
1223
1224 /* check the last full bytes */
1225 for (mask = 0xff000000; pos + 8 <= bits; pos += 8, mask >>= 8) {
1226 if ((i1 & mask) != (i2 & mask))
1227 return FALSE;
1228 }
1229
1230 /* check the last bits, they're reversed in bytes */
1231 bits -= pos;
1232 for (mask = 0x80000000 >> (pos % 32); bits > 0; bits--, mask >>= 1) {
1233 if ((i1 & mask) != (i2 & mask))
1234 return FALSE;
1235 }
1236 return TRUE;
1237 }
1238