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