comparison src/lib/net.c @ 16276:d594ce839da3

net_getunixcred() support for NetBSD <v5.0. Fixed also building with other NetBSDs. Patch by Emmanuel Dreyfus
author Timo Sirainen <tss@iki.fi>
date Thu, 11 Apr 2013 13:15:39 +0300
parents 790bb5dfadc6
children c802c0b960e2
comparison
equal deleted inserted replaced
16275:e33ec9eb166e 16276:d594ce839da3
36 sizeof(so.sin6) : sizeof(so.sin)) 36 sizeof(so.sin6) : sizeof(so.sin))
37 #else 37 #else
38 # define SIZEOF_SOCKADDR(so) (sizeof(so.sin)) 38 # define SIZEOF_SOCKADDR(so) (sizeof(so.sin))
39 #endif 39 #endif
40 40
41 #if !defined(HAVE_GETPEEREID) && !defined(SO_PEERCRED) && !defined(HAVE_GETPEERUCRED) && defined(MSG_WAITALL) && defined(LOCAL_CREDS)
42 # define NEEDS_LOCAL_CREDS 1
43 #endif
44
41 bool net_ip_compare(const struct ip_addr *ip1, const struct ip_addr *ip2) 45 bool net_ip_compare(const struct ip_addr *ip1, const struct ip_addr *ip2)
42 { 46 {
43 return net_ip_cmp(ip1, ip2) == 0; 47 return net_ip_cmp(ip1, ip2) == 0;
44 } 48 }
45 49
300 ret = connect(fd, &sa.sa, sizeof(sa)); 304 ret = connect(fd, &sa.sa, sizeof(sa));
301 if (ret < 0 && errno != EINPROGRESS) { 305 if (ret < 0 && errno != EINPROGRESS) {
302 i_close_fd(&fd); 306 i_close_fd(&fd);
303 return -1; 307 return -1;
304 } 308 }
309
310 #ifdef NEEDS_LOCAL_CREDS
311 {
312 int on = 1;
313 if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof on)) {
314 i_error("setsockopt(LOCAL_CREDS) failed: %m");
315 return -1;
316 }
317 }
318 #endif
305 319
306 return fd; 320 return fd;
307 } 321 }
308 322
309 int net_connect_unix_with_retries(const char *path, unsigned int msecs) 323 int net_connect_unix_with_retries(const char *path, unsigned int msecs)
456 if (fd == -1) { 470 if (fd == -1) {
457 i_error("socket() failed: %m"); 471 i_error("socket() failed: %m");
458 return -1; 472 return -1;
459 } 473 }
460 474
475 #ifdef NEEDS_LOCAL_CREDS
476 {
477 int on = 1;
478 if (setsockopt(fd, 0, LOCAL_CREDS, &on, sizeof on)) {
479 i_error("setsockopt(LOCAL_CREDS) failed: %m");
480 return -1;
481 }
482 }
483 #endif
484
461 /* bind */ 485 /* bind */
462 if (bind(fd, &sa.sa, sizeof(sa)) < 0) { 486 if (bind(fd, &sa.sa, sizeof(sa)) < 0) {
463 if (errno != EADDRINUSE) 487 if (errno != EADDRINUSE)
464 i_error("bind(%s) failed: %m", path); 488 i_error("bind(%s) failed: %m", path);
465 } else { 489 } else {
719 #elif defined(LOCAL_PEEREID) 743 #elif defined(LOCAL_PEEREID)
720 /* NetBSD (may also provide getpeereid, but we also want pid) */ 744 /* NetBSD (may also provide getpeereid, but we also want pid) */
721 struct unpcbid ucred; 745 struct unpcbid ucred;
722 socklen_t len = sizeof(ucred); 746 socklen_t len = sizeof(ucred);
723 747
724 if (getsockopt(s, 0, LOCAL_PEEREID, &ucred, &len) < 0) { 748 if (getsockopt(fd, 0, LOCAL_PEEREID, &ucred, &len) < 0) {
725 i_error("getsockopt(LOCAL_PEEREID) failed: %m"); 749 i_error("getsockopt(LOCAL_PEEREID) failed: %m");
726 return -1; 750 return -1;
727 } 751 }
728 752
729 cred_r->uid = ucred.unp_euid; 753 cred_r->uid = ucred.unp_euid;
773 if (cred_r->uid == (uid_t)-1 || 797 if (cred_r->uid == (uid_t)-1 ||
774 cred_r->gid == (gid_t)-1) { 798 cred_r->gid == (gid_t)-1) {
775 errno = EINVAL; 799 errno = EINVAL;
776 return -1; 800 return -1;
777 } 801 }
802 return 0;
803 #elif NEEDS_LOCAL_CREDS
804 /* NetBSD < 5 */
805 int i, n, on;
806 struct iovec iov;
807 struct msghdr msg;
808 struct {
809 struct cmsghdr ch;
810 char buf[110];
811 } cdata;
812 struct sockcred *sc;
813
814 iov.iov_base = (char *)&on;
815 iov.iov_len = 1;
816
817 sc = (struct sockcred *)cdata.buf;
818 sc->sc_uid = sc->sc_euid = sc->sc_gid = sc->sc_egid = -1;
819 memset(&cdata.ch, 0, sizeof cdata.ch);
820
821 memset(&msg, 0, sizeof msg);
822
823 msg.msg_iov = &iov;
824 msg.msg_iovlen = 1;
825 msg.msg_control = &cdata;
826 msg.msg_controllen = sizeof(cdata.ch) + sizeof(cdata.buf);
827
828 for (i = 0; i < 10; i++) {
829 n = recvmsg(fd, &msg, MSG_WAITALL | MSG_PEEK);
830 if (n >= 0 || errno != EAGAIN)
831 break;
832 usleep(100);
833 }
834 if (n < 0) {
835 i_error("recvmsg() failed: %m");
836 return -1;
837 }
838 cred_r->uid = sc->sc_euid;
839 cred_r->gid = sc->sc_egid;
778 return 0; 840 return 0;
779 #else 841 #else
780 errno = EINVAL; 842 errno = EINVAL;
781 return -1; 843 return -1;
782 #endif 844 #endif