diff options
Diffstat (limited to 'io')
-rw-r--r-- | io/channel-buffer.c | 2 | ||||
-rw-r--r-- | io/channel-command.c | 2 | ||||
-rw-r--r-- | io/channel-file.c | 2 | ||||
-rw-r--r-- | io/channel-null.c | 2 | ||||
-rw-r--r-- | io/channel-socket.c | 41 | ||||
-rw-r--r-- | io/channel-tls.c | 160 | ||||
-rw-r--r-- | io/channel-websock.c | 4 | ||||
-rw-r--r-- | io/channel.c | 22 | ||||
-rw-r--r-- | io/dns-resolver.c | 21 | ||||
-rw-r--r-- | io/meson.build | 2 | ||||
-rw-r--r-- | io/trace-events | 5 |
11 files changed, 194 insertions, 69 deletions
diff --git a/io/channel-buffer.c b/io/channel-buffer.c index 8096180..189fa67 100644 --- a/io/channel-buffer.c +++ b/io/channel-buffer.c @@ -225,7 +225,7 @@ static GSource *qio_channel_buffer_create_watch(QIOChannel *ioc, static void qio_channel_buffer_class_init(ObjectClass *klass, - void *class_data G_GNUC_UNUSED) + const void *class_data G_GNUC_UNUSED) { QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); diff --git a/io/channel-command.c b/io/channel-command.c index 6d5f64e..8966dd3 100644 --- a/io/channel-command.c +++ b/io/channel-command.c @@ -358,7 +358,7 @@ static GSource *qio_channel_command_create_watch(QIOChannel *ioc, static void qio_channel_command_class_init(ObjectClass *klass, - void *class_data G_GNUC_UNUSED) + const void *class_data G_GNUC_UNUSED) { QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); diff --git a/io/channel-file.c b/io/channel-file.c index 2ea8d08..ca3f180 100644 --- a/io/channel-file.c +++ b/io/channel-file.c @@ -290,7 +290,7 @@ static GSource *qio_channel_file_create_watch(QIOChannel *ioc, } static void qio_channel_file_class_init(ObjectClass *klass, - void *class_data G_GNUC_UNUSED) + const void *class_data G_GNUC_UNUSED) { QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); diff --git a/io/channel-null.c b/io/channel-null.c index ef99586..49f1c80 100644 --- a/io/channel-null.c +++ b/io/channel-null.c @@ -207,7 +207,7 @@ qio_channel_null_create_watch(QIOChannel *ioc, static void qio_channel_null_class_init(ObjectClass *klass, - void *class_data G_GNUC_UNUSED) + const void *class_data G_GNUC_UNUSED) { QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); diff --git a/io/channel-socket.c b/io/channel-socket.c index 3a899b0..3b7ca92 100644 --- a/io/channel-socket.c +++ b/io/channel-socket.c @@ -78,6 +78,17 @@ qio_channel_socket_new(void) return sioc; } +int qio_channel_socket_set_send_buffer(QIOChannelSocket *ioc, + size_t size, + Error **errp) +{ + if (setsockopt(ioc->fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0) { + error_setg_errno(errp, errno, "Unable to set socket send buffer size"); + return -1; + } + + return 0; +} static int qio_channel_socket_set_fd(QIOChannelSocket *sioc, @@ -841,6 +852,33 @@ qio_channel_socket_set_cork(QIOChannel *ioc, socket_set_cork(sioc->fd, v); } +static int +qio_channel_socket_get_peerpid(QIOChannel *ioc, + unsigned int *pid, + Error **errp) +{ +#ifdef CONFIG_LINUX + QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc); + Error *err = NULL; + socklen_t len = sizeof(struct ucred); + + struct ucred cred; + if (getsockopt(sioc->fd, + SOL_SOCKET, SO_PEERCRED, + &cred, &len) == -1) { + error_setg_errno(&err, errno, "Unable to get peer credentials"); + error_propagate(errp, err); + *pid = -1; + return -1; + } + *pid = (unsigned int)cred.pid; + return 0; +#else + error_setg(errp, "Unsupported feature"); + *pid = -1; + return -1; +#endif +} static int qio_channel_socket_close(QIOChannel *ioc, @@ -922,7 +960,7 @@ static GSource *qio_channel_socket_create_watch(QIOChannel *ioc, } static void qio_channel_socket_class_init(ObjectClass *klass, - void *class_data G_GNUC_UNUSED) + const void *class_data G_GNUC_UNUSED) { QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); @@ -938,6 +976,7 @@ static void qio_channel_socket_class_init(ObjectClass *klass, #ifdef QEMU_MSG_ZEROCOPY ioc_klass->io_flush = qio_channel_socket_flush; #endif + ioc_klass->io_peerpid = qio_channel_socket_get_peerpid; } static const TypeInfo qio_channel_socket_info = { diff --git a/io/channel-tls.c b/io/channel-tls.c index 67b9700..db2ac1d 100644 --- a/io/channel-tls.c +++ b/io/channel-tls.c @@ -28,17 +28,16 @@ static ssize_t qio_channel_tls_write_handler(const char *buf, size_t len, - void *opaque) + void *opaque, + Error **errp) { QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque); ssize_t ret; - ret = qio_channel_write(tioc->master, buf, len, NULL); + ret = qio_channel_write(tioc->master, buf, len, errp); if (ret == QIO_CHANNEL_ERR_BLOCK) { - errno = EAGAIN; - return -1; + return QCRYPTO_TLS_SESSION_ERR_BLOCK; } else if (ret < 0) { - errno = EIO; return -1; } return ret; @@ -46,17 +45,16 @@ static ssize_t qio_channel_tls_write_handler(const char *buf, static ssize_t qio_channel_tls_read_handler(char *buf, size_t len, - void *opaque) + void *opaque, + Error **errp) { QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque); ssize_t ret; - ret = qio_channel_read(tioc->master, buf, len, NULL); + ret = qio_channel_read(tioc->master, buf, len, errp); if (ret == QIO_CHANNEL_ERR_BLOCK) { - errno = EAGAIN; - return -1; + return QCRYPTO_TLS_SESSION_ERR_BLOCK; } else if (ret < 0) { - errno = EIO; return -1; } return ret; @@ -164,16 +162,17 @@ static void qio_channel_tls_handshake_task(QIOChannelTLS *ioc, GMainContext *context) { Error *err = NULL; - QCryptoTLSSessionHandshakeStatus status; + int status; - if (qcrypto_tls_session_handshake(ioc->session, &err) < 0) { + status = qcrypto_tls_session_handshake(ioc->session, &err); + + if (status < 0) { trace_qio_channel_tls_handshake_fail(ioc); qio_task_set_error(task, err); qio_task_complete(task); return; } - status = qcrypto_tls_session_get_handshake_status(ioc->session); if (status == QCRYPTO_TLS_HANDSHAKE_COMPLETE) { trace_qio_channel_tls_handshake_complete(ioc); if (qcrypto_tls_session_check_credentials(ioc->session, @@ -249,6 +248,85 @@ void qio_channel_tls_handshake(QIOChannelTLS *ioc, qio_channel_tls_handshake_task(ioc, task, context); } +static gboolean qio_channel_tls_bye_io(QIOChannel *ioc, GIOCondition condition, + gpointer user_data); + +static void qio_channel_tls_bye_task(QIOChannelTLS *ioc, QIOTask *task, + GMainContext *context) +{ + GIOCondition condition; + QIOChannelTLSData *data; + int status; + Error *err = NULL; + + status = qcrypto_tls_session_bye(ioc->session, &err); + + if (status < 0) { + trace_qio_channel_tls_bye_fail(ioc); + qio_task_set_error(task, err); + qio_task_complete(task); + return; + } + + if (status == QCRYPTO_TLS_BYE_COMPLETE) { + qio_task_complete(task); + return; + } + + data = g_new0(typeof(*data), 1); + data->task = task; + data->context = context; + + if (context) { + g_main_context_ref(context); + } + + if (status == QCRYPTO_TLS_BYE_SENDING) { + condition = G_IO_OUT; + } else { + condition = G_IO_IN; + } + + trace_qio_channel_tls_bye_pending(ioc, status); + ioc->bye_ioc_tag = qio_channel_add_watch_full(ioc->master, condition, + qio_channel_tls_bye_io, + data, NULL, context); +} + + +static gboolean qio_channel_tls_bye_io(QIOChannel *ioc, GIOCondition condition, + gpointer user_data) +{ + QIOChannelTLSData *data = user_data; + QIOTask *task = data->task; + GMainContext *context = data->context; + QIOChannelTLS *tioc = QIO_CHANNEL_TLS(qio_task_get_source(task)); + + tioc->bye_ioc_tag = 0; + g_free(data); + qio_channel_tls_bye_task(tioc, task, context); + + if (context) { + g_main_context_unref(context); + } + + return FALSE; +} + +static void propagate_error(QIOTask *task, gpointer opaque) +{ + qio_task_propagate_error(task, opaque); +} + +void qio_channel_tls_bye(QIOChannelTLS *ioc, Error **errp) +{ + QIOTask *task; + + task = qio_task_new(OBJECT(ioc), propagate_error, errp, NULL); + + trace_qio_channel_tls_bye_start(ioc); + qio_channel_tls_bye_task(ioc, task, NULL); +} static void qio_channel_tls_init(Object *obj G_GNUC_UNUSED) { @@ -277,24 +355,20 @@ static ssize_t qio_channel_tls_readv(QIOChannel *ioc, ssize_t got = 0; for (i = 0 ; i < niov ; i++) { - ssize_t ret = qcrypto_tls_session_read(tioc->session, - iov[i].iov_base, - iov[i].iov_len); - if (ret < 0) { - if (errno == EAGAIN) { - if (got) { - return got; - } else { - return QIO_CHANNEL_ERR_BLOCK; - } - } else if (errno == ECONNABORTED && - (qatomic_load_acquire(&tioc->shutdown) & - QIO_CHANNEL_SHUTDOWN_READ)) { - return 0; + ssize_t ret = qcrypto_tls_session_read( + tioc->session, + iov[i].iov_base, + iov[i].iov_len, + flags & QIO_CHANNEL_READ_FLAG_RELAXED_EOF || + qatomic_load_acquire(&tioc->shutdown) & QIO_CHANNEL_SHUTDOWN_READ, + errp); + if (ret == QCRYPTO_TLS_SESSION_ERR_BLOCK) { + if (got) { + return got; + } else { + return QIO_CHANNEL_ERR_BLOCK; } - - error_setg_errno(errp, errno, - "Cannot read from TLS channel"); + } else if (ret < 0) { return -1; } got += ret; @@ -321,18 +395,15 @@ static ssize_t qio_channel_tls_writev(QIOChannel *ioc, for (i = 0 ; i < niov ; i++) { ssize_t ret = qcrypto_tls_session_write(tioc->session, iov[i].iov_base, - iov[i].iov_len); - if (ret <= 0) { - if (errno == EAGAIN) { - if (done) { - return done; - } else { - return QIO_CHANNEL_ERR_BLOCK; - } + iov[i].iov_len, + errp); + if (ret == QCRYPTO_TLS_SESSION_ERR_BLOCK) { + if (done) { + return done; + } else { + return QIO_CHANNEL_ERR_BLOCK; } - - error_setg_errno(errp, errno, - "Cannot write to TLS channel"); + } else if (ret < 0) { return -1; } done += ret; @@ -389,6 +460,11 @@ static int qio_channel_tls_close(QIOChannel *ioc, g_clear_handle_id(&tioc->hs_ioc_tag, g_source_remove); } + if (tioc->bye_ioc_tag) { + trace_qio_channel_tls_bye_cancel(ioc); + g_clear_handle_id(&tioc->bye_ioc_tag, g_source_remove); + } + return qio_channel_close(tioc->master, errp); } @@ -485,7 +561,7 @@ qio_channel_tls_get_session(QIOChannelTLS *ioc) } static void qio_channel_tls_class_init(ObjectClass *klass, - void *class_data G_GNUC_UNUSED) + const void *class_data G_GNUC_UNUSED) { QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); diff --git a/io/channel-websock.c b/io/channel-websock.c index de39f0d..08ddb27 100644 --- a/io/channel-websock.c +++ b/io/channel-websock.c @@ -351,7 +351,7 @@ static void qio_channel_websock_handshake_send_res_ok(QIOChannelWebsock *ioc, QIO_CHANNEL_WEBSOCK_GUID_LEN + 1); /* hash and encode it */ - if (qcrypto_hash_base64(QCRYPTO_HASH_ALG_SHA1, + if (qcrypto_hash_base64(QCRYPTO_HASH_ALGO_SHA1, combined_key, QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN + QIO_CHANNEL_WEBSOCK_GUID_LEN, @@ -1308,7 +1308,7 @@ static GSource *qio_channel_websock_create_watch(QIOChannel *ioc, } static void qio_channel_websock_class_init(ObjectClass *klass, - void *class_data G_GNUC_UNUSED) + const void *class_data G_GNUC_UNUSED) { QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); diff --git a/io/channel.c b/io/channel.c index a1f12f8..ebd9322 100644 --- a/io/channel.c +++ b/io/channel.c @@ -115,7 +115,8 @@ int coroutine_mixed_fn qio_channel_readv_all_eof(QIOChannel *ioc, size_t niov, Error **errp) { - return qio_channel_readv_full_all_eof(ioc, iov, niov, NULL, NULL, errp); + return qio_channel_readv_full_all_eof(ioc, iov, niov, NULL, NULL, 0, + errp); } int coroutine_mixed_fn qio_channel_readv_all(QIOChannel *ioc, @@ -130,6 +131,7 @@ int coroutine_mixed_fn qio_channel_readv_full_all_eof(QIOChannel *ioc, const struct iovec *iov, size_t niov, int **fds, size_t *nfds, + int flags, Error **errp) { int ret = -1; @@ -155,7 +157,7 @@ int coroutine_mixed_fn qio_channel_readv_full_all_eof(QIOChannel *ioc, while ((nlocal_iov > 0) || local_fds) { ssize_t len; len = qio_channel_readv_full(ioc, local_iov, nlocal_iov, local_fds, - local_nfds, 0, errp); + local_nfds, flags, errp); if (len == QIO_CHANNEL_ERR_BLOCK) { if (qemu_in_coroutine()) { qio_channel_yield(ioc, G_IO_IN); @@ -222,7 +224,8 @@ int coroutine_mixed_fn qio_channel_readv_full_all(QIOChannel *ioc, int **fds, size_t *nfds, Error **errp) { - int ret = qio_channel_readv_full_all_eof(ioc, iov, niov, fds, nfds, errp); + int ret = qio_channel_readv_full_all_eof(ioc, iov, niov, fds, nfds, 0, + errp); if (ret == 0) { error_setg(errp, "Unexpected end-of-file before all data were read"); @@ -548,6 +551,19 @@ void qio_channel_set_cork(QIOChannel *ioc, } } +int qio_channel_get_peerpid(QIOChannel *ioc, + unsigned int *pid, + Error **errp) +{ + QIOChannelClass *klass = QIO_CHANNEL_GET_CLASS(ioc); + + if (!klass->io_peerpid) { + error_setg(errp, "Channel does not support peer pid"); + return -1; + } + klass->io_peerpid(ioc, pid, errp); + return 0; +} off_t qio_channel_io_seek(QIOChannel *ioc, off_t offset, diff --git a/io/dns-resolver.c b/io/dns-resolver.c index 53b0e84..3712438 100644 --- a/io/dns-resolver.c +++ b/io/dns-resolver.c @@ -111,22 +111,11 @@ static int qio_dns_resolver_lookup_sync_inet(QIODNSResolver *resolver, uaddr, INET6_ADDRSTRLEN, uport, 32, NI_NUMERICHOST | NI_NUMERICSERV); - newaddr->u.inet = (InetSocketAddress){ - .host = g_strdup(uaddr), - .port = g_strdup(uport), - .has_numeric = true, - .numeric = true, - .has_to = iaddr->has_to, - .to = iaddr->to, - .has_ipv4 = iaddr->has_ipv4, - .ipv4 = iaddr->ipv4, - .has_ipv6 = iaddr->has_ipv6, - .ipv6 = iaddr->ipv6, -#ifdef HAVE_IPPROTO_MPTCP - .has_mptcp = iaddr->has_mptcp, - .mptcp = iaddr->mptcp, -#endif - }; + newaddr->u.inet = *iaddr; + newaddr->u.inet.host = g_strdup(uaddr), + newaddr->u.inet.port = g_strdup(uport), + newaddr->u.inet.has_numeric = true, + newaddr->u.inet.numeric = true, (*addrs)[i] = newaddr; } diff --git a/io/meson.build b/io/meson.build index 283b9b2..1164812 100644 --- a/io/meson.build +++ b/io/meson.build @@ -13,4 +13,4 @@ io_ss.add(files( 'dns-resolver.c', 'net-listener.c', 'task.c', -), gnutls) +)) diff --git a/io/trace-events b/io/trace-events index d4c0f84..dc3a63b 100644 --- a/io/trace-events +++ b/io/trace-events @@ -44,6 +44,11 @@ qio_channel_tls_handshake_pending(void *ioc, int status) "TLS handshake pending qio_channel_tls_handshake_fail(void *ioc) "TLS handshake fail ioc=%p" qio_channel_tls_handshake_complete(void *ioc) "TLS handshake complete ioc=%p" qio_channel_tls_handshake_cancel(void *ioc) "TLS handshake cancel ioc=%p" +qio_channel_tls_bye_start(void *ioc) "TLS termination start ioc=%p" +qio_channel_tls_bye_pending(void *ioc, int status) "TLS termination pending ioc=%p status=%d" +qio_channel_tls_bye_fail(void *ioc) "TLS termination fail ioc=%p" +qio_channel_tls_bye_complete(void *ioc) "TLS termination complete ioc=%p" +qio_channel_tls_bye_cancel(void *ioc) "TLS termination cancel ioc=%p" qio_channel_tls_credentials_allow(void *ioc) "TLS credentials allow ioc=%p" qio_channel_tls_credentials_deny(void *ioc) "TLS credentials deny ioc=%p" |