1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2021 Tintri by DDN, Inc. All rights reserved. 14 */ 15 16 /* 17 * Shim to implement ksocket_sendmblk on top of ksocket_sendmsg 18 */ 19 20 #include <sys/types.h> 21 #include <sys/systm.h> 22 #include <sys/cred.h> 23 #include <sys/errno.h> 24 #include <sys/socket.h> 25 #include <sys/ksocket.h> 26 #include <sys/stream.h> 27 #include <sys/strsubr.h> 28 #include <sys/strsun.h> 29 #include <sys/debug.h> 30 #include <sys/kmem.h> 31 #include <limits.h> 32 #include <unistd.h> 33 #include <errno.h> 34 #include <umem.h> 35 36 int 37 ksocket_sendmblk(ksocket_t ks, struct nmsghdr *msg, int flags, 38 mblk_t **mpp, cred_t *cr) 39 { 40 struct msghdr tmsg; 41 mblk_t *m; 42 iovec_t *iov = NULL; 43 size_t iov_sz = 0; 44 size_t tlen, sent; 45 int i, nseg; 46 int rc; 47 48 /* 49 * Setup the IOV. First, count the number of IOV segments 50 * and get the total length. 51 */ 52 nseg = 0; 53 tlen = 0; 54 m = *mpp; 55 while (m != NULL) { 56 nseg++; 57 tlen += MBLKL(m); 58 m = m->b_cont; 59 } 60 ASSERT(tlen > 0); 61 if (tlen == 0) { 62 rc = 0; 63 goto out; 64 } 65 66 iov_sz = nseg * sizeof (iovec_t); 67 iov = kmem_alloc(iov_sz, KM_SLEEP); 68 69 /* 70 * Build the iov list 71 */ 72 i = 0; 73 m = *mpp; 74 while (m != NULL) { 75 iov[i].iov_base = (void *) m->b_rptr; 76 iov[i++].iov_len = MBLKL(m); 77 m = m->b_cont; 78 } 79 ASSERT3S(i, ==, nseg); 80 81 bzero(&tmsg, sizeof (tmsg)); 82 tmsg.msg_iov = iov; 83 tmsg.msg_iovlen = nseg; 84 while (tlen > 0) { 85 sent = 0; 86 rc = ksocket_sendmsg(ks, &tmsg, 0, &sent, CRED()); 87 if (rc != 0) 88 break; 89 tlen -= sent; 90 } 91 92 out: 93 if (iov != NULL) 94 kmem_free(iov, iov_sz); 95 if (*mpp != NULL) { 96 freemsg(*mpp); 97 *mpp = NULL; 98 } 99 100 return (rc); 101 } 102