1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <poll.h>
6#include <stddef.h>
7#include <stdlib.h>
8#include <stdio.h>
9#include <string.h>
10#include <sys/ioctl.h>
11
12#include <zircon/processargs.h>
13#include <zircon/syscalls.h>
14
15#include <lib/fdio/io.h>
16#include <lib/fdio/remoteio.h>
17#include <lib/fdio/socket.h>
18#include <lib/fdio/util.h>
19
20#include "private-socket.h"
21
22static bool is_rio_message_valid(zxsio_msg_t* msg) {
23    if ((msg->datalen > ZXSIO_PAYLOAD_SZ) ||
24        (msg->hcount > 0)) {
25        return false;
26    }
27    return true;
28}
29
30static bool is_rio_message_reply_valid(zxsio_msg_t* msg, uint32_t size) {
31    if ((size < ZXSIO_HDR_SZ) ||
32        (msg->datalen != (size - ZXSIO_HDR_SZ))) {
33        return false;
34    }
35    return is_rio_message_valid(msg);
36}
37
38zx_status_t zxsio_accept(fdio_t* io, zx_handle_t* s2) {
39    zxsio_t* sio = (zxsio_t*)io;
40
41    if (!(sio->flags & ZXSIO_DID_LISTEN)) {
42        return ZX_ERR_BAD_STATE;
43    }
44
45    zx_status_t r;
46    for (;;) {
47        r = zx_socket_accept(sio->s, s2);
48        if (r == ZX_ERR_SHOULD_WAIT) {
49            if (io->ioflag & IOFLAG_NONBLOCK) {
50                return ZX_ERR_SHOULD_WAIT;
51            }
52
53            // wait for an incoming connection
54            zx_signals_t pending;
55            r = zx_object_wait_one(sio->s, ZX_SOCKET_ACCEPT | ZX_SOCKET_PEER_CLOSED, ZX_TIME_INFINITE, &pending);
56            if (r < 0) {
57                return r;
58            }
59            if (pending & ZX_SOCKET_ACCEPT) {
60                continue;
61            }
62            if (pending & ZX_SOCKET_PEER_CLOSED) {
63                return ZX_ERR_PEER_CLOSED;
64            }
65            // impossible
66            return ZX_ERR_INTERNAL;
67        }
68        break;
69    }
70    return r;
71}
72
73static ssize_t zxsio_read_stream(fdio_t* io, void* data, size_t len) {
74    zxsio_t* sio = (zxsio_t*)io;
75    int nonblock = sio->io.ioflag & IOFLAG_NONBLOCK;
76
77    // TODO: let the generic read() to do this loop
78    for (;;) {
79        ssize_t r;
80        size_t bytes_read;
81        if ((r = zx_socket_read(sio->s, 0, data, len, &bytes_read)) == ZX_OK) {
82            // zx_socket_read() sets *actual to the number of bytes in the buffer when data is NULL
83            // and len is 0. read() should return 0 in that case.
84            if (len == 0) {
85                return 0;
86            } else {
87                return (ssize_t)bytes_read;
88            }
89        }
90        if (r == ZX_ERR_PEER_CLOSED || r == ZX_ERR_BAD_STATE) {
91            return 0;
92        } else if (r == ZX_ERR_SHOULD_WAIT && !nonblock) {
93            zx_signals_t pending;
94            r = zx_object_wait_one(sio->s,
95                                   ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED | ZX_SOCKET_READ_DISABLED,
96                                   ZX_TIME_INFINITE, &pending);
97            if (r < 0) {
98                return r;
99            }
100            if (pending & ZX_SOCKET_READABLE) {
101                continue;
102            }
103            if (pending & (ZX_SOCKET_PEER_CLOSED | ZX_SOCKET_READ_DISABLED)) {
104                return 0;
105            }
106            // impossible
107            return ZX_ERR_INTERNAL;
108        }
109        return r;
110    }
111}
112
113static ssize_t zxsio_recvfrom(fdio_t* io, void* data, size_t len, int flags,
114                              struct sockaddr* restrict addr,
115                              socklen_t* restrict addrlen) {
116    struct iovec iov;
117    iov.iov_base = data;
118    iov.iov_len = len;
119
120    struct msghdr msg;
121    msg.msg_name = addr;
122    // the caller (recvfrom) checks if addrlen is NULL.
123    msg.msg_namelen = (addr == NULL) ? 0 : *addrlen;
124    msg.msg_iov = &iov;
125    msg.msg_iovlen = 1;
126    msg.msg_control = NULL;
127    msg.msg_controllen = 0;
128    msg.msg_flags = 0;
129
130    ssize_t r = io->ops->recvmsg(io, &msg, flags);
131    if (addr != NULL)
132        *addrlen = msg.msg_namelen;
133
134    return r;
135}
136
137static ssize_t zxsio_write_stream(fdio_t* io, const void* data, size_t len) {
138    zxsio_t* sio = (zxsio_t*)io;
139    int nonblock = sio->io.ioflag & IOFLAG_NONBLOCK;
140
141    // TODO: let the generic write() to do this loop
142    for (;;) {
143        ssize_t r;
144        if ((r = zx_socket_write(sio->s, 0, data, len, &len)) == ZX_OK) {
145            return (ssize_t) len;
146        }
147        if (r == ZX_ERR_SHOULD_WAIT && !nonblock) {
148            zx_signals_t pending;
149            r = zx_object_wait_one(sio->s,
150                                   ZX_SOCKET_WRITABLE | ZX_SOCKET_WRITE_DISABLED | ZX_SOCKET_PEER_CLOSED,
151                                   ZX_TIME_INFINITE, &pending);
152            if (r < 0) {
153                return r;
154            }
155            if (pending & (ZX_SOCKET_WRITE_DISABLED | ZX_SOCKET_PEER_CLOSED)) {
156                return ZX_ERR_PEER_CLOSED;
157            }
158            if (pending & ZX_SOCKET_WRITABLE) {
159                continue;
160            }
161            // impossible
162            return ZX_ERR_INTERNAL;
163        }
164        return r;
165    }
166}
167
168static ssize_t zxsio_sendto(fdio_t* io, const void* data, size_t len, int flags, const struct sockaddr* addr, socklen_t addrlen) {
169    struct iovec iov;
170    iov.iov_base = (void*)data;
171    iov.iov_len = len;
172
173    struct msghdr msg;
174    msg.msg_name = (void*)addr;
175    msg.msg_namelen = addrlen;
176    msg.msg_iov = &iov;
177    msg.msg_iovlen = 1;
178    msg.msg_control = NULL;
179    msg.msg_controllen = 0;
180    msg.msg_flags = 0; // this field is ignored
181
182    return io->ops->sendmsg(io, &msg, flags);
183}
184
185
186static ssize_t zxsio_recvmsg_stream(fdio_t* io, struct msghdr* msg, int flags) {
187    if (flags != 0) {
188        // TODO: support MSG_OOB
189        return ZX_ERR_NOT_SUPPORTED;
190    }
191    if (!(io->ioflag & IOFLAG_SOCKET_CONNECTED)) {
192        return ZX_ERR_BAD_STATE;
193    }
194    // we ignore msg_name and msg_namelen members.
195    // (this is a consistent behavior with other OS implementations for TCP protocol)
196    ssize_t total = 0;
197    for (int i = 0; i < msg->msg_iovlen; i++) {
198        struct iovec *iov = &msg->msg_iov[i];
199        ssize_t n = zxsio_read_stream(io, iov->iov_base, iov->iov_len);
200        if (n < 0) {
201            if (total == 0) {
202                return n;
203            }
204            return total;
205        }
206        total += n;
207        if ((size_t)n != iov->iov_len) {
208            break;
209        }
210    }
211    return total;
212}
213
214static ssize_t zxsio_sendmsg_stream(fdio_t* io, const struct msghdr* msg, int flags) {
215    if (flags != 0) {
216        // TODO: support MSG_OOB
217        return ZX_ERR_NOT_SUPPORTED;
218    }
219    // TODO: support flags and control messages
220    if (io->ioflag & IOFLAG_SOCKET_CONNECTED) {
221        // if connected, can't specify address
222        if (msg->msg_name != NULL || msg->msg_namelen != 0) {
223            return ZX_ERR_ALREADY_EXISTS;
224        }
225    } else {
226        return ZX_ERR_BAD_STATE;
227    }
228    ssize_t total = 0;
229    for (int i = 0; i < msg->msg_iovlen; i++) {
230        struct iovec *iov = &msg->msg_iov[i];
231        if (iov->iov_len <= 0) {
232            return ZX_ERR_INVALID_ARGS;
233        }
234        ssize_t n = zxsio_write_stream(io, iov->iov_base, iov->iov_len);
235        if (n < 0) {
236            return n;
237        }
238        total += n;
239        if ((size_t)n != iov->iov_len) {
240            break;
241        }
242    }
243    return total;
244}
245
246static zx_status_t zxsio_clone(fdio_t* io, zx_handle_t* handles, uint32_t* types) {
247    // TODO: support unconnected sockets
248    if (!(io->ioflag & IOFLAG_SOCKET_CONNECTED)) {
249        return ZX_ERR_BAD_STATE;
250    }
251    zxsio_t* sio = (void*)io;
252    zx_status_t r = zx_handle_duplicate(sio->s, ZX_RIGHT_SAME_RIGHTS, handles);
253    if (r < 0) {
254        return r;
255    }
256    types[0] = PA_FDIO_SOCKET;
257    return 1;
258}
259
260static zx_status_t zxsio_unwrap(fdio_t* io, zx_handle_t* handles, uint32_t* types) {
261    // TODO: support unconnected sockets
262    if (!(io->ioflag & IOFLAG_SOCKET_CONNECTED)) {
263        return ZX_ERR_BAD_STATE;
264    }
265    zxsio_t* sio = (void*)io;
266    zx_status_t r;
267    handles[0] = sio->s;
268    types[0] = PA_FDIO_SOCKET;
269    r = 1;
270    return r;
271}
272
273static void zxsio_wait_begin_stream(fdio_t* io, uint32_t events, zx_handle_t* handle, zx_signals_t* _signals) {
274    zxsio_t* sio = (void*)io;
275    *handle = sio->s;
276    // TODO: locking for flags/state
277    if (io->ioflag & IOFLAG_SOCKET_CONNECTING) {
278        // check the connection state
279        zx_signals_t observed;
280        zx_status_t r;
281        r = zx_object_wait_one(sio->s, ZXSIO_SIGNAL_CONNECTED, 0u,
282                               &observed);
283        if (r == ZX_OK || r == ZX_ERR_TIMED_OUT) {
284            if (observed & ZXSIO_SIGNAL_CONNECTED) {
285                io->ioflag &= ~IOFLAG_SOCKET_CONNECTING;
286                io->ioflag |= IOFLAG_SOCKET_CONNECTED;
287            }
288        }
289    }
290    zx_signals_t signals = ZXSIO_SIGNAL_ERROR;
291    if (io->ioflag & IOFLAG_SOCKET_CONNECTED) {
292        // if socket is connected
293        if (events & POLLIN) {
294            signals |= ZX_SOCKET_READABLE | ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED;
295        }
296        if (events & POLLOUT) {
297            signals |= ZX_SOCKET_WRITABLE | ZX_SOCKET_WRITE_DISABLED;
298        }
299    } else {
300        // if socket is not connected
301        if (events & POLLIN) {
302            // signal when a listening socket gets an incoming connection
303            // or a connecting socket gets connected and receives data
304            signals |= ZX_SOCKET_ACCEPT |
305                ZX_SOCKET_READABLE | ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED;
306        }
307        if (events & POLLOUT) {
308            // signal when connect() operation is finished
309            signals |= ZXSIO_SIGNAL_OUTGOING;
310        }
311    }
312    if (events & POLLRDHUP) {
313        signals |= ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED;
314    }
315    *_signals = signals;
316}
317
318static void zxsio_wait_end_stream(fdio_t* io, zx_signals_t signals, uint32_t* _events) {
319    // check the connection state
320    if (io->ioflag & IOFLAG_SOCKET_CONNECTING) {
321        if (signals & ZXSIO_SIGNAL_CONNECTED) {
322            io->ioflag &= ~IOFLAG_SOCKET_CONNECTING;
323            io->ioflag |= IOFLAG_SOCKET_CONNECTED;
324        }
325    }
326    uint32_t events = 0;
327    if (io->ioflag & IOFLAG_SOCKET_CONNECTED) {
328        if (signals & (ZX_SOCKET_READABLE | ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED)) {
329            events |= POLLIN;
330        }
331        if (signals & (ZX_SOCKET_WRITABLE | ZX_SOCKET_WRITE_DISABLED)) {
332            events |= POLLOUT;
333        }
334    } else {
335        if (signals & (ZX_SOCKET_ACCEPT | ZX_SOCKET_PEER_CLOSED)) {
336            events |= POLLIN;
337        }
338        if (signals & ZXSIO_SIGNAL_OUTGOING) {
339            events |= POLLOUT;
340        }
341    }
342    if (signals & ZXSIO_SIGNAL_ERROR) {
343        events |= POLLERR;
344    }
345    if (signals & (ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED)) {
346        events |= POLLRDHUP;
347    }
348    *_events = events;
349}
350
351static ssize_t zxsio_posix_ioctl_stream(fdio_t* io, int req, va_list va) {
352    zxsio_t* sio = (zxsio_t*)io;
353    switch (req) {
354    case FIONREAD: {
355        zx_status_t r;
356        size_t avail;
357        if ((r = zx_socket_read(sio->s, 0, NULL, 0, &avail)) < 0) {
358            return r;
359        }
360        if (avail > INT_MAX) {
361            avail = INT_MAX;
362        }
363        int* actual = va_arg(va, int*);
364        *actual = avail;
365        return ZX_OK;
366    }
367    default:
368        return ZX_ERR_NOT_SUPPORTED;
369    }
370}
371
372static ssize_t zxsio_rx_dgram(fdio_t* io, void* buf, size_t buflen) {
373    return zxsio_read_stream(io, buf, buflen);
374}
375
376static ssize_t zxsio_tx_dgram(fdio_t* io, const void* buf, size_t buflen) {
377    zx_status_t r = zxsio_write_stream(io, buf, buflen);
378    return (r < 0) ? r : ZX_OK;
379}
380
381static ssize_t zxsio_recvmsg_dgram(fdio_t* io, struct msghdr* msg, int flags);
382static ssize_t zxsio_sendmsg_dgram(fdio_t* io, const struct msghdr* msg, int flags);
383
384static ssize_t zxsio_read_dgram(fdio_t* io, void* data, size_t len) {
385    struct iovec iov;
386    iov.iov_base = data;
387    iov.iov_len = len;
388
389    struct msghdr msg;
390    msg.msg_name = NULL;
391    msg.msg_namelen = 0;
392    msg.msg_iov = &iov;
393    msg.msg_iovlen = 1;
394    msg.msg_control = NULL;
395    msg.msg_controllen = 0;
396    msg.msg_flags = 0;
397
398    return zxsio_recvmsg_dgram(io, &msg, 0);
399}
400
401static ssize_t zxsio_write_dgram(fdio_t* io, const void* data, size_t len) {
402    struct iovec iov;
403    iov.iov_base = (void*)data;
404    iov.iov_len = len;
405
406    struct msghdr msg;
407    msg.msg_name = NULL;
408    msg.msg_namelen = 0;
409    msg.msg_iov = &iov;
410    msg.msg_iovlen = 1;
411    msg.msg_control = NULL;
412    msg.msg_controllen = 0;
413    msg.msg_flags = 0;
414
415    return zxsio_sendmsg_dgram(io, &msg, 0);
416}
417
418static ssize_t zxsio_recvmsg_dgram(fdio_t* io, struct msghdr* msg, int flags) {
419    if (flags != 0) {
420        // TODO: support MSG_OOB
421        return ZX_ERR_NOT_SUPPORTED;
422    }
423    // Read 1 extra byte to detect if the buffer is too small to fit the whole
424    // packet, so we can set MSG_TRUNC flag if necessary.
425    size_t mlen = FDIO_SOCKET_MSG_HEADER_SIZE + 1;
426    for (int i = 0; i < msg->msg_iovlen; i++) {
427        struct iovec *iov = &msg->msg_iov[i];
428        if (iov->iov_len <= 0) {
429            return ZX_ERR_INVALID_ARGS;
430        }
431        mlen += iov->iov_len;
432    }
433
434    // TODO: avoid malloc
435    fdio_socket_msg_t* m = malloc(mlen);
436    ssize_t n = zxsio_rx_dgram(io, m, mlen);
437    if (n < 0) {
438        free(m);
439        return n;
440    }
441    if ((size_t)n < FDIO_SOCKET_MSG_HEADER_SIZE) {
442        free(m);
443        return ZX_ERR_INTERNAL;
444    }
445    n -= FDIO_SOCKET_MSG_HEADER_SIZE;
446    if (msg->msg_name != NULL) {
447        int bytes_to_copy = (msg->msg_namelen < m->addrlen) ? msg->msg_namelen : m->addrlen;
448        memcpy(msg->msg_name, &m->addr, bytes_to_copy);
449    }
450    msg->msg_namelen = m->addrlen;
451    msg->msg_flags = m->flags;
452    char* data = m->data;
453    size_t resid = n;
454    for (int i = 0; i < msg->msg_iovlen; i++) {
455        struct iovec *iov = &msg->msg_iov[i];
456        if (resid == 0) {
457            iov->iov_len = 0;
458        } else {
459            if (resid < iov->iov_len)
460                iov->iov_len = resid;
461            memcpy(iov->iov_base, data, iov->iov_len);
462            data += iov->iov_len;
463            resid -= iov->iov_len;
464        }
465    }
466
467    if (resid > 0) {
468        msg->msg_flags |= MSG_TRUNC;
469        n -= resid;
470    }
471
472    free(m);
473    return n;
474}
475
476static ssize_t zxsio_sendmsg_dgram(fdio_t* io, const struct msghdr* msg, int flags) {
477    if (flags != 0) {
478        // TODO: MSG_OOB
479        return ZX_ERR_NOT_SUPPORTED;
480    }
481    // TODO: support flags and control messages
482    if (io->ioflag & IOFLAG_SOCKET_CONNECTED) {
483        // if connected, can't specify address
484        if (msg->msg_name != NULL || msg->msg_namelen != 0) {
485            return ZX_ERR_ALREADY_EXISTS;
486        }
487    }
488    ssize_t n = 0;
489    for (int i = 0; i < msg->msg_iovlen; i++) {
490        struct iovec *iov = &msg->msg_iov[i];
491        if (iov->iov_len <= 0) {
492            return ZX_ERR_INVALID_ARGS;
493        }
494        n += iov->iov_len;
495    }
496    size_t mlen = n + FDIO_SOCKET_MSG_HEADER_SIZE;
497
498    // TODO: avoid malloc m
499    fdio_socket_msg_t* m = malloc(mlen);
500    if (msg->msg_name != NULL) {
501        memcpy(&m->addr, msg->msg_name, msg->msg_namelen);
502    }
503    m->addrlen = msg->msg_namelen;
504    m->flags = flags;
505    char* data = m->data;
506    for (int i = 0; i < msg->msg_iovlen; i++) {
507        struct iovec *iov = &msg->msg_iov[i];
508        memcpy(data, iov->iov_base, iov->iov_len);
509        data += iov->iov_len;
510    }
511    ssize_t r = zxsio_tx_dgram(io, m, mlen);
512    free(m);
513    return r == ZX_OK ? n : r;
514}
515
516static void zxsio_wait_begin_dgram(fdio_t* io, uint32_t events, zx_handle_t* handle, zx_signals_t* _signals) {
517    zxsio_t* sio = (void*)io;
518    *handle = sio->s;
519    zx_signals_t signals = ZXSIO_SIGNAL_ERROR;
520    if (events & POLLIN) {
521        signals |= ZX_SOCKET_READABLE | ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED;
522    }
523    if (events & POLLOUT) {
524        signals |= ZX_SOCKET_WRITABLE | ZX_SOCKET_WRITE_DISABLED;
525    }
526    if (events & POLLRDHUP) {
527        signals |=  ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED;
528    }
529    *_signals = signals;
530}
531
532static void zxsio_wait_end_dgram(fdio_t* io, zx_signals_t signals, uint32_t* _events) {
533    uint32_t events = 0;
534    if (signals & (ZX_SOCKET_READABLE | ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED)) {
535        events |= POLLIN;
536    }
537    if (signals & (ZX_SOCKET_WRITABLE | ZX_SOCKET_WRITE_DISABLED)) {
538        events |= POLLOUT;
539    }
540    if (signals & ZXSIO_SIGNAL_ERROR) {
541        events |= POLLERR;
542    }
543    if (signals & (ZX_SOCKET_READ_DISABLED | ZX_SOCKET_PEER_CLOSED)) {
544        events |= POLLRDHUP;
545    }
546    *_events = events;
547}
548
549static zx_status_t zxsio_write_control(zxsio_t* sio, zxsio_msg_t* msg) {
550    for (;;) {
551        ssize_t r;
552        size_t len = ZXSIO_HDR_SZ + msg->datalen;
553        if ((r = zx_socket_write(sio->s, ZX_SOCKET_CONTROL, msg, len, &len)) == ZX_OK) {
554            return (ssize_t) len;
555        }
556        // If the socket has no control plane then control messages are not
557        // supported.
558        if (r == ZX_ERR_BAD_STATE) {
559            return ZX_ERR_NOT_SUPPORTED;
560        }
561        if (r == ZX_ERR_SHOULD_WAIT) {
562            zx_signals_t pending;
563            r = zx_object_wait_one(sio->s,
564                                   ZX_SOCKET_CONTROL_WRITABLE | ZX_SOCKET_PEER_CLOSED,
565                                   ZX_TIME_INFINITE, &pending);
566            if (r < 0) {
567                return r;
568            }
569            if (pending & ZX_SOCKET_PEER_CLOSED) {
570                return ZX_ERR_PEER_CLOSED;
571            }
572            if (pending & ZX_SOCKET_CONTROL_WRITABLE) {
573                continue;
574            }
575            // impossible
576            return ZX_ERR_INTERNAL;
577        }
578        return r;
579    }
580}
581
582static ssize_t zxsio_read_control(zxsio_t* sio, void* data, size_t len) {
583    // TODO: let the generic read() to do this loop
584    for (;;) {
585        ssize_t r;
586        size_t bytes_read;
587        if ((r = zx_socket_read(sio->s, ZX_SOCKET_CONTROL, data, len, &bytes_read)) == ZX_OK) {
588            // zx_socket_read() sets *actual to the number of bytes in the buffer when data is NULL
589            // and len is 0. read() should return 0 in that case.
590            if (len == 0) {
591                return 0;
592            } else {
593                return (ssize_t)bytes_read;
594            }
595        }
596        if (r == ZX_ERR_PEER_CLOSED || r == ZX_ERR_BAD_STATE) {
597            return 0;
598        } else if (r == ZX_ERR_SHOULD_WAIT) {
599            zx_signals_t pending;
600            r = zx_object_wait_one(sio->s,
601                                   ZX_SOCKET_CONTROL_READABLE | ZX_SOCKET_PEER_CLOSED,
602                                   ZX_TIME_INFINITE, &pending);
603            if (r < 0) {
604                return r;
605            }
606            if (pending & ZX_SOCKET_CONTROL_READABLE) {
607                continue;
608            }
609            if (pending & ZX_SOCKET_PEER_CLOSED) {
610                return 0;
611            }
612            // impossible
613            return ZX_ERR_INTERNAL;
614        }
615        return r;
616    }
617}
618
619static zx_status_t zxsio_txn(zxsio_t* sio, zxsio_msg_t* msg) {
620    if (!is_rio_message_valid(msg)) {
621        return ZX_ERR_INVALID_ARGS;
622    }
623
624    zx_status_t r = zxsio_write_control(sio, msg);
625    if (r < 0)
626        return r;
627
628    const uint32_t request_op = msg->op;
629    r = zxsio_read_control(sio, msg, sizeof(*msg));
630    if (r < 0)
631        return r;
632
633    size_t dsize = (size_t)r;
634    // check for protocol errors
635    if (!is_rio_message_reply_valid(msg, dsize) || (msg->op != request_op)) {
636        return ZX_ERR_IO;
637    }
638    return msg->arg;
639}
640
641static zx_status_t zxsio_misc(fdio_t* io, uint32_t op, int64_t off,
642                              uint32_t maxreply, void* ptr, size_t len) {
643    zxsio_t* sio = (zxsio_t*)io;
644    zxsio_msg_t msg;
645    zx_status_t r;
646
647    if ((len > ZXSIO_PAYLOAD_SZ) || (maxreply > ZXSIO_PAYLOAD_SZ)) {
648        return ZX_ERR_INVALID_ARGS;
649    }
650
651    switch (op) {
652    case ZXSIO_GETSOCKNAME:
653    case ZXSIO_GETPEERNAME:
654    case ZXSIO_GETSOCKOPT:
655    case ZXSIO_SETSOCKOPT:
656    case ZXSIO_CONNECT:
657    case ZXSIO_BIND:
658    case ZXSIO_LISTEN:
659        break;
660    default:
661        return ZX_ERR_NOT_SUPPORTED;
662    }
663
664    memset(&msg, 0, ZXSIO_HDR_SZ);
665    msg.op = op;
666    msg.arg = maxreply;
667    msg.arg2.off = off;
668    msg.datalen = len;
669    if (ptr && len > 0) {
670        memcpy(msg.data, ptr, len);
671    }
672
673    if ((r = zxsio_txn(sio, &msg)) < 0) {
674        return r;
675    }
676    if (msg.datalen > maxreply) {
677        return ZX_ERR_IO;
678    }
679    if (ptr && msg.datalen > 0) {
680        memcpy(ptr, msg.data, msg.datalen);
681    }
682
683    if (op == ZXSIO_LISTEN && r == ZX_OK) {
684        sio->flags |= ZXSIO_DID_LISTEN;
685    }
686
687    return r;
688}
689
690static zx_status_t zxsio_close(fdio_t* io) {
691    zxsio_t* sio = (zxsio_t*)io;
692    zxsio_msg_t msg;
693    zx_status_t r;
694
695    memset(&msg, 0, ZXSIO_HDR_SZ);
696    msg.op = ZXSIO_CLOSE;
697    r = zxsio_txn(sio, &msg);
698
699    zx_handle_t h = sio->s;
700    sio->s = 0;
701    zx_handle_close(h);
702
703    return r;
704}
705
706static ssize_t zxsio_ioctl(fdio_t* io, uint32_t op, const void* in_buf,
707                           size_t in_len, void* out_buf, size_t out_len) {
708    zxsio_t* sio = (zxsio_t*)io;
709    const uint8_t* data = in_buf;
710    zx_status_t r = 0;
711    zxsio_msg_t msg;
712
713    if (in_len > ZXSIO_PAYLOAD_SZ || out_len > ZXSIO_PAYLOAD_SZ) {
714        return ZX_ERR_INVALID_ARGS;
715    }
716
717    if (IOCTL_KIND(op) != IOCTL_KIND_DEFAULT) {
718        return ZX_ERR_NOT_SUPPORTED;
719    }
720
721    memset(&msg, 0, ZXSIO_HDR_SZ);
722    msg.op = ZXSIO_IOCTL;
723    msg.datalen = in_len;
724    msg.arg = out_len;
725    msg.arg2.op = op;
726    memcpy(msg.data, data, in_len);
727
728    if ((r = zxsio_txn(sio, &msg)) < 0) {
729        return r;
730    }
731
732    size_t copy_len = msg.datalen;
733    if (msg.datalen > out_len) {
734        copy_len = out_len;
735    }
736
737    memcpy(out_buf, msg.data, copy_len);
738    return r;
739}
740
741static zx_status_t fdio_socket_shutdown(fdio_t* io, int how) {
742    if (!(io->ioflag & IOFLAG_SOCKET_CONNECTED)) {
743        return ZX_ERR_BAD_STATE;
744    }
745    zxsio_t* sio = (zxsio_t*)io;
746    if (how == SHUT_WR || how == SHUT_RDWR) {
747        // netstack expects this user signal to be set - raise it to keep that code working until
748        // it learns about the read/write disabled signals.
749        zx_object_signal_peer(sio->s, 0u, ZXSIO_SIGNAL_HALFCLOSED);
750    }
751    uint32_t options = 0;
752    switch (how) {
753    case SHUT_RD:
754        options = ZX_SOCKET_SHUTDOWN_READ;
755        break;
756    case SHUT_WR:
757        options = ZX_SOCKET_SHUTDOWN_WRITE;
758        break;
759    case SHUT_RDWR:
760        options = ZX_SOCKET_SHUTDOWN_READ | ZX_SOCKET_SHUTDOWN_WRITE;
761        break;
762    }
763    return zx_socket_write(sio->s, options, NULL, 0, NULL);
764}
765
766static fdio_ops_t fdio_socket_stream_ops = {
767    .read = zxsio_read_stream,
768    .read_at = fdio_default_read_at,
769    .write = zxsio_write_stream,
770    .write_at = fdio_default_write_at,
771    .seek = fdio_default_seek,
772    .misc = zxsio_misc,
773    .close = zxsio_close,
774    .open = fdio_default_open,
775    .clone = zxsio_clone,
776    .ioctl = zxsio_ioctl,
777    .wait_begin = zxsio_wait_begin_stream,
778    .wait_end = zxsio_wait_end_stream,
779    .unwrap = zxsio_unwrap,
780    .posix_ioctl = zxsio_posix_ioctl_stream,
781    .get_vmo = fdio_default_get_vmo,
782    .get_token = fdio_default_get_token,
783    .get_attr = fdio_default_get_attr,
784    .set_attr = fdio_default_set_attr,
785    .sync = fdio_default_sync,
786    .readdir = fdio_default_readdir,
787    .rewind = fdio_default_rewind,
788    .unlink = fdio_default_unlink,
789    .truncate = fdio_default_truncate,
790    .rename = fdio_default_rename,
791    .link = fdio_default_link,
792    .get_flags = fdio_default_get_flags,
793    .set_flags = fdio_default_set_flags,
794    .recvfrom = zxsio_recvfrom,
795    .sendto = zxsio_sendto,
796    .recvmsg = zxsio_recvmsg_stream,
797    .sendmsg = zxsio_sendmsg_stream,
798    .shutdown = fdio_socket_shutdown,
799};
800
801static fdio_ops_t fdio_socket_dgram_ops = {
802    .read = zxsio_read_dgram,
803    .read_at = fdio_default_read_at,
804    .write = zxsio_write_dgram,
805    .write_at = fdio_default_write_at,
806    .seek = fdio_default_seek,
807    .misc = zxsio_misc,
808    .close = zxsio_close,
809    .open = fdio_default_open,
810    .clone = zxsio_clone,
811    .ioctl = zxsio_ioctl,
812    .wait_begin = zxsio_wait_begin_dgram,
813    .wait_end = zxsio_wait_end_dgram,
814    .unwrap = zxsio_unwrap,
815    .posix_ioctl = fdio_default_posix_ioctl, // not supported
816    .get_vmo = fdio_default_get_vmo,
817    .get_token = fdio_default_get_token,
818    .get_attr = fdio_default_get_attr,
819    .set_attr = fdio_default_set_attr,
820    .sync = fdio_default_sync,
821    .readdir = fdio_default_readdir,
822    .rewind = fdio_default_rewind,
823    .unlink = fdio_default_unlink,
824    .truncate = fdio_default_truncate,
825    .rename = fdio_default_rename,
826    .link = fdio_default_link,
827    .get_flags = fdio_default_get_flags,
828    .set_flags = fdio_default_set_flags,
829    .recvfrom = zxsio_recvfrom,
830    .sendto = zxsio_sendto,
831    .recvmsg = zxsio_recvmsg_dgram,
832    .sendmsg = zxsio_sendmsg_dgram,
833    .shutdown = fdio_socket_shutdown,
834};
835
836static fdio_t* fdio_socket_create(zx_handle_t s, int flags, fdio_ops_t* ops) {
837    zxsio_t* sio = calloc(1, sizeof(*sio));
838    if (sio == NULL) {
839        zx_handle_close(s);
840        return NULL;
841    }
842    sio->io.ops = ops;
843    sio->io.magic = FDIO_MAGIC;
844    sio->io.refcount = 1;
845    sio->io.ioflag = IOFLAG_SOCKET | flags;
846    sio->s = s;
847    sio->flags = 0;
848    return &sio->io;
849}
850
851fdio_t* fdio_socket_create_stream(zx_handle_t s, int flags) {
852    return fdio_socket_create(s, flags, &fdio_socket_stream_ops);
853}
854
855fdio_t* fdio_socket_create_datagram(zx_handle_t s, int flags) {
856    return fdio_socket_create(s, flags, &fdio_socket_dgram_ops);
857}
858