Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / ktli / t_koptmgmt.c
blobe217c4dfcbb9d5dac731e168448087dbb769587e
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
24 /* All Rights Reserved */
27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
32 * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
36 * kTLI variant of t_optmgmt(3NSL)
37 * Returns 0 on success or an errno value.
38 * Similar to libnsl t_optmgmt.c
40 * Note: This expects the caller's struct t_optmgmt to contain the
41 * XTI version of struct T_opthdr (used with T_OPTMGMT_REQ == 27)
42 * not the old "struct opthdr" (used with T_SVR4_OPTMGMT_REQ == 9)
45 #include <sys/param.h>
46 #include <sys/types.h>
47 #include <sys/proc.h>
48 #include <sys/file.h>
49 #include <sys/user.h>
50 #include <sys/vnode.h>
51 #include <sys/errno.h>
52 #include <sys/stream.h>
53 #include <sys/ioctl.h>
54 #include <sys/stropts.h>
55 #include <sys/strsubr.h>
56 #define _SUN_TPI_VERSION 2
57 #include <sys/tihdr.h>
58 #include <sys/timod.h>
59 #include <sys/tiuser.h>
60 #include <sys/t_kuser.h>
61 #include <sys/kmem.h>
63 int
64 t_koptmgmt(TIUSER *tiptr, struct t_optmgmt *req, struct t_optmgmt *ret)
66 struct strioctl strioc;
67 struct T_optmgmt_req *opt_req;
68 struct T_optmgmt_ack *opt_ack;
69 file_t *fp;
70 vnode_t *vp;
71 char *ctlbuf = NULL;
72 char *opt_data;
73 t_scalar_t optlen;
74 int ctlsize;
75 int retval;
76 int error;
78 fp = tiptr->fp;
79 vp = fp->f_vnode;
81 optlen = req->opt.len;
82 if (optlen > 0) {
83 if (req->opt.buf == NULL)
84 return (EINVAL);
85 if (optlen < (t_scalar_t)sizeof (struct T_opthdr)) {
86 /* option buffer should atleast have an t_opthdr */
87 return (EINVAL);
89 /* sanity limit */
90 if (optlen > 4096) {
91 return (EINVAL);
95 ctlsize = sizeof (*opt_req) + optlen;
96 ctlbuf = kmem_alloc(ctlsize, KM_SLEEP);
98 /* LINTED E_BAD_PTR_CAST_ALIGN */
99 opt_req = (struct T_optmgmt_req *)ctlbuf;
100 opt_req->PRIM_type = T_OPTMGMT_REQ;
101 opt_req->MGMT_flags = req->flags;
102 opt_req->OPT_length = optlen;
103 opt_req->OPT_offset = sizeof (*opt_req);
104 if (optlen > 0) {
105 opt_data = ctlbuf + sizeof (*opt_req);
106 bcopy(req->opt.buf, opt_data, optlen);
109 strioc.ic_cmd = TI_OPTMGMT;
110 strioc.ic_timout = 0;
111 strioc.ic_dp = ctlbuf;
112 strioc.ic_len = ctlsize;
114 error = strdoioctl(vp->v_stream, &strioc, FNATIVE, K_TO_K,
115 fp->f_cred, &retval);
116 if (error)
117 goto errout;
119 if (retval) {
120 if ((retval & 0xff) == TSYSERR)
121 error = (retval >> 8) & 0xff;
122 else
123 error = t_tlitosyserr(retval & 0xff);
124 goto errout;
127 if (strioc.ic_len < sizeof (struct T_optmgmt_ack)) {
128 error = EPROTO;
129 goto errout;
132 /* LINTED pointer cast */
133 opt_ack = (struct T_optmgmt_ack *)ctlbuf;
134 if (opt_ack->PRIM_type != T_OPTMGMT_ACK) {
135 error = EPROTO;
136 goto errout;
139 if (ret->opt.maxlen > 0) {
140 if (opt_ack->OPT_length > ret->opt.maxlen) {
141 error = EMSGSIZE;
142 goto errout;
144 ret->opt.len = opt_ack->OPT_offset;
145 opt_data = ctlbuf + opt_ack->OPT_offset;
146 bcopy(opt_data, ret->opt.buf, ret->opt.len);
148 ret->flags = opt_ack->MGMT_flags;
150 errout:
151 if (ctlbuf != NULL)
152 kmem_free(ctlbuf, ctlsize);
153 return (error);