Exemplo n.º 1
0
static size_t
fill_buffer_from_fd(const int fd, void * const dst, const size_t buf_size)
{
  char *buf = dst;
  size_t pos = 0;

  RUNTIME_ASSERT(buf);
  RUNTIME_ASSERT(buf_size > 0);
  RUNTIME_ASSERT((size_t) -1 != buf_size);

  while (pos < buf_size) {
    ssize_t ret;
    size_t size;

    size = buf_size - pos;
    ret = read(fd, &buf[pos], size);
    if ((ssize_t) -1 == ret) {
      if (!is_temporary_error(errno) || wait_for_fd(fd) < 0) {
        return -1;
      }
    } else if (0 == ret) {
      if (pos != 0) {
        errno = EIO;
        return -1;
      }
      return 0; /* EOF */
    } else {
      RUNTIME_ASSERT((size_t) ret <= size);
      pos += (size_t) ret;
    }
  }

  return 1;
}
Exemplo n.º 2
0
MINDY_NORETURN
void wait_for_output(struct thread *thread, int fd,
                     MINDY_NORETURN
                     void (*advance)(struct thread *thread))
{
    wait_for_fd(thread, fd, &Writers, advance);
}
Exemplo n.º 3
0
static int
write_timeout(int fd, const void *buf, int len)
{
    int n = 0, rc = 0;
    const char *b = buf;

    while(n < len) {
        rc = write(fd, b + n, len - n);
        if(rc < 0) {
            if(errno == EAGAIN || errno == EINTR) {
                rc = wait_for_fd(1, fd, 100);
                if(rc > 0) {
                    rc = write(fd, b + n, len - n);
                }
            }
        }
        if(rc > 0)
            n += rc;
        else
            break;
    }

    if(n >= len)
        return 1;
    else {
        if(rc >= 0)
            errno = EAGAIN;
        return -1;
    }
}
Exemplo n.º 4
0
int
babel_send(int s,
           void *buf1, int buflen1, void *buf2, int buflen2,
           struct sockaddr *sin, int slen)
{
    struct iovec iovec[2];
    struct msghdr msg;
    int rc;

    iovec[0].iov_base = buf1;
    iovec[0].iov_len = buflen1;
    iovec[1].iov_base = buf2;
    iovec[1].iov_len = buflen2;
    memset(&msg, 0, sizeof(msg));
    msg.msg_name = (struct sockaddr*)sin;
    msg.msg_namelen = slen;
    msg.msg_iov = iovec;
    msg.msg_iovlen = 2;

 again:
    rc = sendmsg(s, &msg, 0);
    if(rc < 0) {
        if(errno == EINTR)
            goto again;
        else if(errno == EAGAIN) {
            int rc2;
            rc2 = wait_for_fd(1, s, 5);
            if(rc2 > 0)
                goto again;
            errno = EAGAIN;
        }
    }
    return rc;
}
Exemplo n.º 5
0
static int
netlink_talk(struct nlmsghdr *nh)
{

    int rc;
    struct sockaddr_nl nladdr;
    struct msghdr msg;
    struct iovec iov;

    memset(&nladdr, 0, sizeof(nladdr));
    nladdr.nl_family = AF_NETLINK;
    nladdr.nl_pid = 0;

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = &nladdr;
    msg.msg_namelen = sizeof(nladdr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    iov.iov_base = nh;
    iov.iov_len = nh->nlmsg_len;

    nh->nlmsg_flags |= NLM_F_ACK;
    nh->nlmsg_seq = ++nl_command.seqno;

    rc = sendmsg(nl_command.sock, &msg, 0);
    if(rc < 0 && (errno == EAGAIN || errno == EINTR)) {
        rc = wait_for_fd(1, nl_command.sock, 100);
        if(rc <= 0) {
            if(rc == 0)
                errno = EAGAIN;
        } else {
            rc = sendmsg(nl_command.sock, &msg, 0);
        }
    }

    if(rc < nh->nlmsg_len) {
        int saved_errno = errno;
        perror("sendmsg");
        errno = saved_errno;
        return -1;
    }

    rc = netlink_read(&nl_command, NULL, 1, NULL, NULL); /* ACK */

    return rc;
}
Exemplo n.º 6
0
static int
netlink_send(struct nlmsghdr *nh, int sock)
{
    int rc;
    struct sockaddr_nl nladdr;
    struct msghdr msg;
    struct iovec iov;

    memset(&nladdr, 0, sizeof(nladdr));
    nladdr.nl_family = AF_NETLINK;
    nladdr.nl_pid = 0;

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = &nladdr;
    msg.msg_namelen = sizeof(nladdr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    iov.iov_base = nh;
    iov.iov_len = nh->nlmsg_len;

    nh->nlmsg_flags |= NLM_F_ACK;
    nh->nlmsg_seq = ++nl_seqno;
    pending_ack = nl_seqno;

    rc = sendmsg(sock, &msg, 0);
    if(rc < 0 && (errno == EAGAIN || errno == EINTR)) {
        rc = wait_for_fd(1, sock, 100);
        if(rc <= 0) {
            if(rc == 0)
                errno = EAGAIN;
        } else {
            rc = sendmsg(sock, &msg, 0);
        }
    }

    if(rc < nh->nlmsg_len) {
        log_msg(LOG_PERROR, "sendmsg");
        return -1;
    }

    return rc;
}
Exemplo n.º 7
0
static int
netlink_read_ack(int sock)
{
    int rc, again = 0;
    assert(pending_ack >= 0);
 again:
    rc = netlink_read_all(sock);
    if(!again && rc >= 0 && pending_ack >= 0) {
        rc = wait_for_fd(1, nl_socket, 100);
        if(rc <= 0) {
            if(rc == 0)
                errno = EAGAIN;
        } else {
            again = 1;
            goto again;
        }
    }
    return pending_ack < 0 ? 0 : -1;
}
Exemplo n.º 8
0
static void
ssl_recv_tcp_send(SSL *recvssl, int sendfd)
{
	static unsigned char buf[65536];
	unsigned char *ptr;
	ssize_t tcpdone;
	size_t todo;
	int recvfd, ssldone;

	recvfd = SSL_get_fd(recvssl);
	PJDLOG_ASSERT(recvfd >= 0);
	pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd);
	for (;;) {
		ssldone = SSL_read(recvssl, buf, sizeof(buf));
		pjdlog_debug(2, "%s: SSL_read() returned %d", __func__,
		    ssldone);
		if (ssl_check_error(recvssl, ssldone) == -1)
			break;
		todo = (size_t)ssldone;
		ptr = buf;
		do {
			tcpdone = send(sendfd, ptr, todo, MSG_NOSIGNAL);
			pjdlog_debug(2, "%s: send() returned %zd", __func__,
			    tcpdone);
			if (tcpdone == 0) {
				pjdlog_debug(1, "Connection terminated.");
				exit(0);
			} else if (tcpdone == -1) {
				if (errno == EINTR || errno == ENOBUFS)
					continue;
				if (errno == EAGAIN) {
					(void)wait_for_fd(sendfd, -1);
					continue;
				}
				pjdlog_exit(EX_TEMPFAIL, "send() failed");
			}
			todo -= tcpdone;
			ptr += tcpdone;
		} while (todo > 0);
	}
	pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd);
}
Exemplo n.º 9
0
Arquivo: net.c Projeto: jech/babeld
int
babel_send(int s,
           const void *buf1, int buflen1, const void *buf2, int buflen2,
           const struct sockaddr *sin, int slen)
{
    struct iovec iovec[2];
    struct msghdr msg;
    int rc, count = 0;

    iovec[0].iov_base = (void*)buf1;
    iovec[0].iov_len = buflen1;
    iovec[1].iov_base = (void*)buf2;
    iovec[1].iov_len = buflen2;
    memset(&msg, 0, sizeof(msg));
    msg.msg_name = (struct sockaddr*)sin;
    msg.msg_namelen = slen;
    msg.msg_iov = iovec;
    msg.msg_iovlen = 2;

    /* The Linux kernel can apparently keep returning EAGAIN indefinitely. */

again:
    rc = sendmsg(s, &msg, 0);
    if(rc < 0) {
        if(errno == EINTR) {
            count++;
            if(count < 100)
                goto again;
        } else if(errno == EAGAIN) {
            int rc2;
            rc2 = wait_for_fd(1, s, 5);
            if(rc2 > 0) {
                count++;
                if(count < 100)
                    goto again;
            }
            errno = EAGAIN;
        }
    }
    return rc;
}
Exemplo n.º 10
0
static int
tls_connect_wait(void *ctx, int timeout)
{
	struct tls_ctx *tlsctx = ctx;
	int error, sockfd;
	uint8_t connected;

	PJDLOG_ASSERT(tlsctx != NULL);
	PJDLOG_ASSERT(tlsctx->tls_magic == TLS_CTX_MAGIC);
	PJDLOG_ASSERT(tlsctx->tls_side == TLS_SIDE_CLIENT);
	PJDLOG_ASSERT(tlsctx->tls_sock != NULL);
	PJDLOG_ASSERT(!tlsctx->tls_wait_called);
	PJDLOG_ASSERT(timeout >= 0);

	sockfd = proto_descriptor(tlsctx->tls_sock);
	error = wait_for_fd(sockfd, timeout);
	if (error != 0)
		return (error);

	for (;;) {
		switch (recv(sockfd, &connected, sizeof(connected),
		    MSG_WAITALL)) {
		case -1:
			if (errno == EINTR || errno == ENOBUFS)
				continue;
			error = errno;
			break;
		case 0:
			pjdlog_debug(1, "Connection terminated.");
			error = ENOTCONN;
			break;
		case 1:
			tlsctx->tls_wait_called = true;
			break;
		}
		break;
	}

	return (error);
}
Exemplo n.º 11
0
static void
tcp_recv_ssl_send(int recvfd, SSL *sendssl)
{
	static unsigned char buf[65536];
	ssize_t tcpdone;
	int sendfd, ssldone;

	sendfd = SSL_get_fd(sendssl);
	PJDLOG_ASSERT(sendfd >= 0);
	pjdlog_debug(2, "%s: start %d -> %d", __func__, recvfd, sendfd);
	for (;;) {
		tcpdone = recv(recvfd, buf, sizeof(buf), 0);
		pjdlog_debug(2, "%s: recv() returned %zd", __func__, tcpdone);
		if (tcpdone == 0) {
			pjdlog_debug(1, "Connection terminated.");
			exit(0);
		} else if (tcpdone == -1) {
			if (errno == EINTR)
				continue;
			else if (errno == EAGAIN)
				break;
			pjdlog_exit(EX_TEMPFAIL, "recv() failed");
		}
		for (;;) {
			ssldone = SSL_write(sendssl, buf, (int)tcpdone);
			pjdlog_debug(2, "%s: send() returned %d", __func__,
			    ssldone);
			if (ssl_check_error(sendssl, ssldone) == -1) {
				(void)wait_for_fd(sendfd, -1);
				continue;
			}
			PJDLOG_ASSERT(ssldone == tcpdone);
			break;
		}
	}
	pjdlog_debug(2, "%s: done %d -> %d", __func__, recvfd, sendfd);
}
Exemplo n.º 12
0
static void
tls_exec_client(const char *user, int startfd, const char *srcaddr,
    const char *dstaddr, const char *fingerprint, const char *defport,
    int timeout, int debuglevel)
{
	struct proto_conn *tcp;
	char *saddr, *daddr;
	SSL_CTX *sslctx;
	SSL *ssl;
	long ret;
	int sockfd, tcpfd;
	uint8_t connected;

	pjdlog_debug_set(debuglevel);
	pjdlog_prefix_set("[TLS sandbox] (client) ");
#ifdef HAVE_SETPROCTITLE
	setproctitle("[TLS sandbox] (client) ");
#endif
	proto_set("tcp:port", defport);

	sockfd = startfd;

	/* Change tls:// to tcp://. */
	if (srcaddr == NULL) {
		saddr = NULL;
	} else {
		saddr = strdup(srcaddr);
		if (saddr == NULL)
			pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory.");
		bcopy("tcp://", saddr, 6);
	}
	daddr = strdup(dstaddr);
	if (daddr == NULL)
		pjdlog_exitx(EX_TEMPFAIL, "Unable to allocate memory.");
	bcopy("tcp://", daddr, 6);

	/* Establish TCP connection. */
	if (proto_connect(saddr, daddr, timeout, &tcp) == -1)
		exit(EX_TEMPFAIL);

	SSL_load_error_strings();
	SSL_library_init();

	/*
	 * TODO: On FreeBSD we could move this below sandbox() once libc and
	 *       libcrypto use sysctl kern.arandom to obtain random data
	 *       instead of /dev/urandom and friends.
	 */
	sslctx = SSL_CTX_new(TLSv1_client_method());
	if (sslctx == NULL)
		pjdlog_exitx(EX_TEMPFAIL, "SSL_CTX_new() failed.");

	if (sandbox(user, true, "proto_tls client: %s", dstaddr) != 0)
		pjdlog_exitx(EX_CONFIG, "Unable to sandbox TLS client.");
	pjdlog_debug(1, "Privileges successfully dropped.");

	SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);

	/* Load CA certs. */
	/* TODO */
	//SSL_CTX_load_verify_locations(sslctx, cacerts_file, NULL);

	ssl = SSL_new(sslctx);
	if (ssl == NULL)
		pjdlog_exitx(EX_TEMPFAIL, "SSL_new() failed.");

	tcpfd = proto_descriptor(tcp);

	block(tcpfd);

	if (SSL_set_fd(ssl, tcpfd) != 1)
		pjdlog_exitx(EX_TEMPFAIL, "SSL_set_fd() failed.");

	ret = SSL_connect(ssl);
	ssl_check_error(ssl, (int)ret);

	nonblock(sockfd);
	nonblock(tcpfd);

	tls_certificate_verify(ssl, fingerprint);

	/*
	 * The following byte is send to make proto_connect_wait() to work.
	 */
	connected = 1;
	for (;;) {
		switch (send(sockfd, &connected, sizeof(connected), 0)) {
		case -1:
			if (errno == EINTR || errno == ENOBUFS)
				continue;
			if (errno == EAGAIN) {
				(void)wait_for_fd(sockfd, -1);
				continue;
			}
			pjdlog_exit(EX_TEMPFAIL, "send() failed");
		case 0:
			pjdlog_debug(1, "Connection terminated.");
			exit(0);
		case 1:
			break;
		}
		break;
	}

	tls_loop(sockfd, ssl);
}
Exemplo n.º 13
0
static int
netlink_read(struct netlink *nl, struct netlink *nl_ignore, int answer,
             int (*fn)(struct nlmsghdr *nh, void *data), void *data)
{

    /* 'answer' must be true when we just have send a request on 'nl_socket' */

    /* 'nl_ignore' is used in kernel_callback to ignore message originating  */
    /*  from 'nl_command' while reading 'nl_listen'                          */

    /* Return code :                                       */
    /* -1 : error                                          */
    /*  0 : if(fn) found_interesting; else found_ack;      */
    /*  1 : only if(fn) nothing interesting has been found */
    /*  2 : nothing found, retry                           */

    int err;
    struct msghdr msg;
    struct sockaddr_nl nladdr;
    struct iovec iov;
    struct nlmsghdr *nh;
    int len;
    int interesting = 0;
    int done = 0;

    char buf[8192];

    memset(&nladdr, 0, sizeof(nladdr));
    nladdr.nl_family = AF_NETLINK;

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = &nladdr;
    msg.msg_namelen = sizeof(nladdr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    iov.iov_base = &buf;

    do {
        iov.iov_len = sizeof(buf);
        len = recvmsg(nl->sock, &msg, 0);

        if(len < 0 && (errno == EAGAIN || errno == EINTR)) {
            int rc;
            rc = wait_for_fd(0, nl->sock, 100);
            if(rc <= 0) {
                if(rc == 0)
                    errno = EAGAIN;
            } else {
                len = recvmsg(nl->sock, &msg, 0);
            }
        }

        if(len < 0) {
            perror("netlink_read: recvmsg()");
            return 2;
        } else if(len == 0) {
            fprintf(stderr, "netlink_read: EOF\n");
            goto socket_error;
        } else if(msg.msg_namelen != nl->socklen) {
            fprintf(stderr,
                    "netlink_read: unexpected sender address length (%d)\n",
                    msg.msg_namelen);
            goto socket_error;
        } else if(nladdr.nl_pid != 0) {
            kdebugf("netlink_read: message not sent by kernel.\n");
            return 2;
        }

        kdebugf("Netlink message: ");

        for(nh = (struct nlmsghdr *)buf;
            NLMSG_OK(nh, len);
            nh = NLMSG_NEXT(nh, len)) {
            kdebugf("%s", (nh->nlmsg_flags & NLM_F_MULTI) ? "[multi] " : "");
            if(!answer)
                done = 1;
            if(nl_ignore && nh->nlmsg_pid == nl_ignore->sockaddr.nl_pid) {
                kdebugf("(ignore), ");
                continue;
            } else if(answer && (nh->nlmsg_pid != nl->sockaddr.nl_pid ||
                                 nh->nlmsg_seq != nl->seqno)) {
                kdebugf("(wrong seqno %d %d /pid %d %d), ",
                       nh->nlmsg_seq, nl->seqno,
                       nh->nlmsg_pid, nl->sockaddr.nl_pid);
                continue;
            } else if(nh->nlmsg_type == NLMSG_DONE) {
                kdebugf("(done)\n");
                done = 1;
                break;
            } else if(nh->nlmsg_type == NLMSG_ERROR) {
                struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh);
                if(err->error == 0) {
                    kdebugf("(ACK)\n");
                    return 0;
                } else {
                    kdebugf("netlink_read: %s\n", strerror(-err->error));
                    errno = -err->error;
                    return -1;
                }
            } else if(fn) {
                kdebugf("(msg -> \"");
                err = fn(nh,data);
                kdebugf("\" %d), ", err);
                if(err < 0) return err;
                interesting = interesting || err;
                continue;
            }
            kdebugf(", ");
        }
        kdebugf("\n");

        if(msg.msg_flags & MSG_TRUNC)
            fprintf(stderr, "netlink_read: message truncated\n");

    } while (!done);

    return interesting;

    socket_error:
        close(nl->sock);
        nl->sock = -1;
        errno = EIO;
        return -1;
    }