xref: /illumos-gate/usr/src/uts/common/io/ib/clients/rds/rds_ioctl.c (revision b86efd96f8acd85ddaa930a2f0c1d664237e4aaf)
1*b86efd96Sagiri /*
2*b86efd96Sagiri  * CDDL HEADER START
3*b86efd96Sagiri  *
4*b86efd96Sagiri  * The contents of this file are subject to the terms of the
5*b86efd96Sagiri  * Common Development and Distribution License (the "License").
6*b86efd96Sagiri  * You may not use this file except in compliance with the License.
7*b86efd96Sagiri  *
8*b86efd96Sagiri  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*b86efd96Sagiri  * or http://www.opensolaris.org/os/licensing.
10*b86efd96Sagiri  * See the License for the specific language governing permissions
11*b86efd96Sagiri  * and limitations under the License.
12*b86efd96Sagiri  *
13*b86efd96Sagiri  * When distributing Covered Code, include this CDDL HEADER in each
14*b86efd96Sagiri  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*b86efd96Sagiri  * If applicable, add the following below this CDDL HEADER, with the
16*b86efd96Sagiri  * fields enclosed by brackets "[]" replaced with your own identifying
17*b86efd96Sagiri  * information: Portions Copyright [yyyy] [name of copyright owner]
18*b86efd96Sagiri  *
19*b86efd96Sagiri  * CDDL HEADER END
20*b86efd96Sagiri  */
21*b86efd96Sagiri /*
22*b86efd96Sagiri  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*b86efd96Sagiri  * Use is subject to license terms.
24*b86efd96Sagiri  */
25*b86efd96Sagiri 
26*b86efd96Sagiri #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*b86efd96Sagiri 
28*b86efd96Sagiri #define	AF_INET_OFFLOAD	30
29*b86efd96Sagiri 
30*b86efd96Sagiri #include <sys/sockio.h>
31*b86efd96Sagiri #include <sys/stream.h>
32*b86efd96Sagiri #include <sys/errno.h>
33*b86efd96Sagiri #include <sys/cmn_err.h>
34*b86efd96Sagiri #include <sys/strsun.h>
35*b86efd96Sagiri #include <inet/common.h>
36*b86efd96Sagiri #include <net/if.h>
37*b86efd96Sagiri #include <inet/mi.h>
38*b86efd96Sagiri #include <sys/t_kuser.h>
39*b86efd96Sagiri #include <sys/stropts.h>
40*b86efd96Sagiri #include <sys/pathname.h>
41*b86efd96Sagiri #include <sys/kstr.h>
42*b86efd96Sagiri #include <sys/timod.h>
43*b86efd96Sagiri #include <sys/ib/clients/rds/rds.h>
44*b86efd96Sagiri #include <sys/ib/clients/rds/rds_transport.h>
45*b86efd96Sagiri 
46*b86efd96Sagiri static	sin_t	sin_null;	/* Zero address for quick clears */
47*b86efd96Sagiri 
48*b86efd96Sagiri #define	isdigit(ch)	((ch) >= '0' && (ch) <= '9')
49*b86efd96Sagiri 
50*b86efd96Sagiri #define	isalpha(ch)	(((ch) >= 'a' && (ch) <= 'z') || \
51*b86efd96Sagiri 			((ch) >= 'A' && (ch) <= 'Z'))
52*b86efd96Sagiri 
53*b86efd96Sagiri 
54*b86efd96Sagiri /*
55*b86efd96Sagiri  * Just pass the ioctl to IP and the result to the caller.
56*b86efd96Sagiri  */
57*b86efd96Sagiri int
58*b86efd96Sagiri rds_do_ip_ioctl(int cmd, int len, caddr_t arg)
59*b86efd96Sagiri {
60*b86efd96Sagiri 	vnode_t	*kvp, *vp;
61*b86efd96Sagiri 	TIUSER	*tiptr;
62*b86efd96Sagiri 	struct	strioctl iocb;
63*b86efd96Sagiri 	int	err = 0;
64*b86efd96Sagiri 
65*b86efd96Sagiri 	if (lookupname("/dev/udp", UIO_SYSSPACE, FOLLOW, NULLVPP,
66*b86efd96Sagiri 	    &kvp) == 0) {
67*b86efd96Sagiri 		if (t_kopen((file_t *)NULL, kvp->v_rdev, FREAD|FWRITE,
68*b86efd96Sagiri 		    &tiptr, CRED()) == 0) {
69*b86efd96Sagiri 			vp = tiptr->fp->f_vnode;
70*b86efd96Sagiri 		} else {
71*b86efd96Sagiri 			VN_RELE(kvp);
72*b86efd96Sagiri 			return (EPROTO);
73*b86efd96Sagiri 		}
74*b86efd96Sagiri 	} else {
75*b86efd96Sagiri 			return (EPROTO);
76*b86efd96Sagiri 	}
77*b86efd96Sagiri 
78*b86efd96Sagiri 	iocb.ic_cmd = cmd;
79*b86efd96Sagiri 	iocb.ic_timout = 0;
80*b86efd96Sagiri 	iocb.ic_len = len;
81*b86efd96Sagiri 	iocb.ic_dp = arg;
82*b86efd96Sagiri 	err = kstr_ioctl(vp, I_STR, (intptr_t)&iocb);
83*b86efd96Sagiri 	(void) t_kclose(tiptr, 0);
84*b86efd96Sagiri 	VN_RELE(kvp);
85*b86efd96Sagiri 	return (err);
86*b86efd96Sagiri }
87*b86efd96Sagiri 
88*b86efd96Sagiri static int
89*b86efd96Sagiri rds_dl_info(ldi_handle_t lh, dl_info_ack_t *info)
90*b86efd96Sagiri {
91*b86efd96Sagiri 	dl_info_req_t *info_req;
92*b86efd96Sagiri 	union DL_primitives *dl_prim;
93*b86efd96Sagiri 	mblk_t *mp;
94*b86efd96Sagiri 	int error;
95*b86efd96Sagiri 
96*b86efd96Sagiri 	if ((mp = allocb(sizeof (dl_info_req_t), BPRI_MED)) == NULL) {
97*b86efd96Sagiri 		return (ENOMEM);
98*b86efd96Sagiri 	}
99*b86efd96Sagiri 
100*b86efd96Sagiri 	mp->b_datap->db_type = M_PROTO;
101*b86efd96Sagiri 
102*b86efd96Sagiri 	info_req = (dl_info_req_t *)(uintptr_t)mp->b_wptr;
103*b86efd96Sagiri 	mp->b_wptr += sizeof (dl_info_req_t);
104*b86efd96Sagiri 	info_req->dl_primitive = DL_INFO_REQ;
105*b86efd96Sagiri 
106*b86efd96Sagiri 	if ((error = ldi_putmsg(lh, mp)) != 0) {
107*b86efd96Sagiri 		return (error);
108*b86efd96Sagiri 	}
109*b86efd96Sagiri 	if ((error = ldi_getmsg(lh, &mp, (timestruc_t *)NULL)) != 0) {
110*b86efd96Sagiri 		return (error);
111*b86efd96Sagiri 	}
112*b86efd96Sagiri 
113*b86efd96Sagiri 	dl_prim = (union DL_primitives *)(uintptr_t)mp->b_rptr;
114*b86efd96Sagiri 	switch (dl_prim->dl_primitive) {
115*b86efd96Sagiri 	case DL_INFO_ACK:
116*b86efd96Sagiri 		if (((uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr) <
117*b86efd96Sagiri 		    sizeof (dl_info_ack_t)) {
118*b86efd96Sagiri 			error = -1;
119*b86efd96Sagiri 		} else {
120*b86efd96Sagiri 			*info = *(dl_info_ack_t *)(uintptr_t)mp->b_rptr;
121*b86efd96Sagiri 			error = 0;
122*b86efd96Sagiri 		}
123*b86efd96Sagiri 		break;
124*b86efd96Sagiri 	default:
125*b86efd96Sagiri 		error = -1;
126*b86efd96Sagiri 		break;
127*b86efd96Sagiri 	}
128*b86efd96Sagiri 
129*b86efd96Sagiri 	freemsg(mp);
130*b86efd96Sagiri 	return (error);
131*b86efd96Sagiri }
132*b86efd96Sagiri 
133*b86efd96Sagiri 
134*b86efd96Sagiri static boolean_t
135*b86efd96Sagiri rds_is_ib_interface(char *name)
136*b86efd96Sagiri {
137*b86efd96Sagiri 
138*b86efd96Sagiri 	char		dev_path[MAXPATHLEN];
139*b86efd96Sagiri 	ldi_handle_t	lh;
140*b86efd96Sagiri 	dl_info_ack_t	info;
141*b86efd96Sagiri 	int		ret = 0;
142*b86efd96Sagiri 	int		i = 0;
143*b86efd96Sagiri 
144*b86efd96Sagiri 	(void) strcpy(dev_path, "/dev/");
145*b86efd96Sagiri 
146*b86efd96Sagiri 	/*
147*b86efd96Sagiri 	 * ibd devices are only style 2 devices
148*b86efd96Sagiri 	 * so we will open only style 2 devices
149*b86efd96Sagiri 	 * by ignoring the ppa
150*b86efd96Sagiri 	 */
151*b86efd96Sagiri 	while (isalpha(name[i])) {
152*b86efd96Sagiri 		i++;
153*b86efd96Sagiri 	}
154*b86efd96Sagiri 
155*b86efd96Sagiri 	if (i == 0) {
156*b86efd96Sagiri 		/*
157*b86efd96Sagiri 		 * null name.
158*b86efd96Sagiri 		 */
159*b86efd96Sagiri 		return (B_FALSE);
160*b86efd96Sagiri 	}
161*b86efd96Sagiri 
162*b86efd96Sagiri 	if (strncmp("lo", name, i) == 0) {
163*b86efd96Sagiri 		/*
164*b86efd96Sagiri 		 * loopback interface is considered RDS capable
165*b86efd96Sagiri 		 */
166*b86efd96Sagiri 		return (B_TRUE);
167*b86efd96Sagiri 	}
168*b86efd96Sagiri 
169*b86efd96Sagiri 	(void) strncat((dev_path + sizeof ("/dev/") -1), name, i);
170*b86efd96Sagiri 
171*b86efd96Sagiri 	ret = ldi_open_by_name(dev_path, FREAD|FWRITE, kcred, &lh, rds_li);
172*b86efd96Sagiri 	if (ret != 0) {
173*b86efd96Sagiri 		return (B_FALSE);
174*b86efd96Sagiri 	}
175*b86efd96Sagiri 
176*b86efd96Sagiri 	ret = rds_dl_info(lh, &info);
177*b86efd96Sagiri 
178*b86efd96Sagiri 	(void) ldi_close(lh, FREAD|FWRITE, kcred);
179*b86efd96Sagiri 
180*b86efd96Sagiri 	if (ret != 0 || (info.dl_mac_type != DL_IB &&
181*b86efd96Sagiri 	    !rds_transport_ops->rds_transport_if_lookup_by_name(name))) {
182*b86efd96Sagiri 		return (B_FALSE);
183*b86efd96Sagiri 	}
184*b86efd96Sagiri 
185*b86efd96Sagiri 	return (B_TRUE);
186*b86efd96Sagiri }
187*b86efd96Sagiri 
188*b86efd96Sagiri void
189*b86efd96Sagiri rds_ioctl_copyin_done(queue_t *q, mblk_t *mp)
190*b86efd96Sagiri {
191*b86efd96Sagiri 	char	*addr;
192*b86efd96Sagiri 	mblk_t	*mp1;
193*b86efd96Sagiri 	int	err = 0;
194*b86efd96Sagiri 	struct	iocblk *iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
195*b86efd96Sagiri 
196*b86efd96Sagiri 	if (!(mp1 = mp->b_cont) || !(mp1 = mp1->b_cont)) {
197*b86efd96Sagiri 		err = EPROTO;
198*b86efd96Sagiri 		goto done;
199*b86efd96Sagiri 	}
200*b86efd96Sagiri 
201*b86efd96Sagiri 	addr = (char *)mp1->b_rptr;
202*b86efd96Sagiri 
203*b86efd96Sagiri 	switch (iocp->ioc_cmd) {
204*b86efd96Sagiri 
205*b86efd96Sagiri 	case SIOCGIFNUM: {
206*b86efd96Sagiri 		/* Get number of interfaces. */
207*b86efd96Sagiri 		struct ifconf   kifc;
208*b86efd96Sagiri 		struct ifreq *ifr;
209*b86efd96Sagiri 		int num_ifs;
210*b86efd96Sagiri 		int n;
211*b86efd96Sagiri 
212*b86efd96Sagiri 		err = rds_do_ip_ioctl(iocp->ioc_cmd, sizeof (int),
213*b86efd96Sagiri 		    (char *)&num_ifs);
214*b86efd96Sagiri 		if (err != 0) {
215*b86efd96Sagiri 			break;
216*b86efd96Sagiri 		}
217*b86efd96Sagiri 
218*b86efd96Sagiri 		kifc.ifc_len = num_ifs * sizeof (struct ifreq);
219*b86efd96Sagiri 		kifc.ifc_buf = kmem_zalloc(kifc.ifc_len, KM_SLEEP);
220*b86efd96Sagiri 		err = rds_do_ip_ioctl(SIOCGIFCONF,
221*b86efd96Sagiri 		    sizeof (struct ifconf), (caddr_t)&kifc);
222*b86efd96Sagiri 		if (err != 0) {
223*b86efd96Sagiri 			kmem_free(kifc.ifc_buf, kifc.ifc_len);
224*b86efd96Sagiri 			break;
225*b86efd96Sagiri 		}
226*b86efd96Sagiri 		ifr = kifc.ifc_req;
227*b86efd96Sagiri 		n = num_ifs;
228*b86efd96Sagiri 		for (num_ifs = 0; n > 0; ifr++) {
229*b86efd96Sagiri 			if (rds_is_ib_interface(ifr->ifr_name)) {
230*b86efd96Sagiri 				num_ifs++;
231*b86efd96Sagiri 			}
232*b86efd96Sagiri 			n--;
233*b86efd96Sagiri 		}
234*b86efd96Sagiri 		*((int *)(uintptr_t)addr) = num_ifs;
235*b86efd96Sagiri 		kmem_free(kifc.ifc_buf, kifc.ifc_len);
236*b86efd96Sagiri 	}
237*b86efd96Sagiri 		break;
238*b86efd96Sagiri 
239*b86efd96Sagiri 	case O_SIOCGIFCONF:
240*b86efd96Sagiri 	case SIOCGIFCONF: {
241*b86efd96Sagiri 		STRUCT_HANDLE(ifconf, ifc);
242*b86efd96Sagiri 		caddr_t ubuf_addr;
243*b86efd96Sagiri 		int	ubuf_size;
244*b86efd96Sagiri 		struct ifconf   kifc;
245*b86efd96Sagiri 		struct ifreq *ifr, *ptr;
246*b86efd96Sagiri 		int num_ifs;
247*b86efd96Sagiri 
248*b86efd96Sagiri 		STRUCT_SET_HANDLE(ifc, iocp->ioc_flag,
249*b86efd96Sagiri 		    (struct ifconf *)(uintptr_t)addr);
250*b86efd96Sagiri 
251*b86efd96Sagiri 		ubuf_size = STRUCT_FGET(ifc, ifc_len);
252*b86efd96Sagiri 		ubuf_addr = STRUCT_FGETP(ifc, ifc_buf);
253*b86efd96Sagiri 
254*b86efd96Sagiri 		err = rds_do_ip_ioctl(SIOCGIFNUM, sizeof (int),
255*b86efd96Sagiri 		    (char *)&num_ifs);
256*b86efd96Sagiri 		if (err != 0) {
257*b86efd96Sagiri 			break;
258*b86efd96Sagiri 		}
259*b86efd96Sagiri 
260*b86efd96Sagiri 		kifc.ifc_len = num_ifs * sizeof (struct ifreq);
261*b86efd96Sagiri 		kifc.ifc_buf = kmem_zalloc(kifc.ifc_len, KM_SLEEP);
262*b86efd96Sagiri 		err = rds_do_ip_ioctl(iocp->ioc_cmd,
263*b86efd96Sagiri 		    sizeof (struct ifconf), (caddr_t)&kifc);
264*b86efd96Sagiri 		if (err != 0) {
265*b86efd96Sagiri 			kmem_free(kifc.ifc_buf, kifc.ifc_len);
266*b86efd96Sagiri 			break;
267*b86efd96Sagiri 		}
268*b86efd96Sagiri 		mp1 = mi_copyout_alloc(q, mp, ubuf_addr, ubuf_size, B_FALSE);
269*b86efd96Sagiri 		if (mp1 == NULL) {
270*b86efd96Sagiri 			err = ENOMEM;
271*b86efd96Sagiri 			kmem_free(kifc.ifc_buf, ubuf_size);
272*b86efd96Sagiri 			break;
273*b86efd96Sagiri 		}
274*b86efd96Sagiri 
275*b86efd96Sagiri 		ifr = kifc.ifc_req;
276*b86efd96Sagiri 		ptr = (struct ifreq *)(uintptr_t)mp1->b_rptr;
277*b86efd96Sagiri 		for (; num_ifs > 0 &&
278*b86efd96Sagiri 		    (int)((uintptr_t)mp1->b_wptr - (uintptr_t)mp1->b_rptr) <
279*b86efd96Sagiri 		    ubuf_size; num_ifs--, ifr++) {
280*b86efd96Sagiri 			if (rds_is_ib_interface(ifr->ifr_name)) {
281*b86efd96Sagiri 				ifr->ifr_addr.sa_family = AF_INET_OFFLOAD;
282*b86efd96Sagiri 				bcopy((caddr_t)ifr, ptr, sizeof (struct ifreq));
283*b86efd96Sagiri 				ptr++;
284*b86efd96Sagiri 				mp1->b_wptr = (uchar_t *)ptr;
285*b86efd96Sagiri 			}
286*b86efd96Sagiri 		}
287*b86efd96Sagiri 
288*b86efd96Sagiri 		STRUCT_FSET(ifc, ifc_len, (int)((uintptr_t)mp1->b_wptr -
289*b86efd96Sagiri 		    (uintptr_t)mp1->b_rptr));
290*b86efd96Sagiri 
291*b86efd96Sagiri 		kmem_free(kifc.ifc_buf, kifc.ifc_len);
292*b86efd96Sagiri 	}
293*b86efd96Sagiri 		break;
294*b86efd96Sagiri 	case SIOCGIFMTU:
295*b86efd96Sagiri 		err = rds_do_ip_ioctl(iocp->ioc_cmd,
296*b86efd96Sagiri 		    sizeof (struct ifreq), addr);
297*b86efd96Sagiri 		break;
298*b86efd96Sagiri 
299*b86efd96Sagiri 	case SIOCGIFFLAGS:
300*b86efd96Sagiri 		err = rds_do_ip_ioctl(iocp->ioc_cmd,
301*b86efd96Sagiri 		    sizeof (struct ifreq), addr);
302*b86efd96Sagiri 		break;
303*b86efd96Sagiri 	case TI_GETMYNAME: {
304*b86efd96Sagiri 
305*b86efd96Sagiri 		rds_t *rds;
306*b86efd96Sagiri 		STRUCT_HANDLE(strbuf, sb);
307*b86efd96Sagiri 		ipaddr_t	v4addr;
308*b86efd96Sagiri 		uint16_t port;
309*b86efd96Sagiri 		int addrlen;
310*b86efd96Sagiri 		sin_t *sin;
311*b86efd96Sagiri 
312*b86efd96Sagiri 		STRUCT_SET_HANDLE(sb,
313*b86efd96Sagiri 		    ((struct iocblk *)(uintptr_t)mp->b_rptr)->ioc_flag,
314*b86efd96Sagiri 		    (void *)(uintptr_t)addr);
315*b86efd96Sagiri 		rds = (rds_t *)q->q_ptr;
316*b86efd96Sagiri 		ASSERT(rds->rds_family == AF_INET_OFFLOAD);
317*b86efd96Sagiri 		addrlen = sizeof (sin_t);
318*b86efd96Sagiri 		v4addr = rds->rds_src;
319*b86efd96Sagiri 		port = rds->rds_port;
320*b86efd96Sagiri 		mp1 = mi_copyout_alloc(q, mp, STRUCT_FGETP(sb, buf), addrlen,
321*b86efd96Sagiri 		    B_TRUE);
322*b86efd96Sagiri 		if (mp1 == NULL)
323*b86efd96Sagiri 			return;
324*b86efd96Sagiri 		STRUCT_FSET(sb, len, (int)sizeof (sin_t));
325*b86efd96Sagiri 		sin = (sin_t *)(uintptr_t)mp1->b_rptr;
326*b86efd96Sagiri 		mp1->b_wptr = (uchar_t *)&sin[1];
327*b86efd96Sagiri 		*sin = sin_null;
328*b86efd96Sagiri 		sin->sin_family = AF_INET_OFFLOAD;
329*b86efd96Sagiri 		sin->sin_addr.s_addr = v4addr;
330*b86efd96Sagiri 		sin->sin_port = port;
331*b86efd96Sagiri 
332*b86efd96Sagiri 	}
333*b86efd96Sagiri 		break;
334*b86efd96Sagiri 	default:
335*b86efd96Sagiri 		err = EOPNOTSUPP;
336*b86efd96Sagiri 		break;
337*b86efd96Sagiri 	}
338*b86efd96Sagiri 	if (err == 0) {
339*b86efd96Sagiri 		mi_copyout(q, mp);
340*b86efd96Sagiri 		return;
341*b86efd96Sagiri 	}
342*b86efd96Sagiri done:
343*b86efd96Sagiri 	mi_copy_done(q, mp, err);
344*b86efd96Sagiri }
345*b86efd96Sagiri 
346*b86efd96Sagiri 
347*b86efd96Sagiri void
348*b86efd96Sagiri rds_ioctl_copyin_setup(queue_t *q, mblk_t *mp)
349*b86efd96Sagiri {
350*b86efd96Sagiri 	struct iocblk *iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
351*b86efd96Sagiri 	int	copyin_size;
352*b86efd96Sagiri 
353*b86efd96Sagiri 	if (mp->b_cont == NULL) {
354*b86efd96Sagiri 		iocp->ioc_error = EINVAL;
355*b86efd96Sagiri 		mp->b_datap->db_type = M_IOCNAK;
356*b86efd96Sagiri 		iocp->ioc_count = 0;
357*b86efd96Sagiri 		qreply(q, mp);
358*b86efd96Sagiri 		return;
359*b86efd96Sagiri 	}
360*b86efd96Sagiri 
361*b86efd96Sagiri 	switch (iocp->ioc_cmd) {
362*b86efd96Sagiri 	case O_SIOCGIFCONF:
363*b86efd96Sagiri 	case SIOCGIFCONF:
364*b86efd96Sagiri 		if (iocp->ioc_count == TRANSPARENT)
365*b86efd96Sagiri 			copyin_size = SIZEOF_STRUCT(ifconf, iocp->ioc_flag);
366*b86efd96Sagiri 		else
367*b86efd96Sagiri 			copyin_size = iocp->ioc_count;
368*b86efd96Sagiri 		break;
369*b86efd96Sagiri 
370*b86efd96Sagiri 	case SIOCGIFNUM:
371*b86efd96Sagiri 		copyin_size = sizeof (int);
372*b86efd96Sagiri 		break;
373*b86efd96Sagiri 	case SIOCGIFFLAGS:
374*b86efd96Sagiri 	case SIOCGIFMTU:
375*b86efd96Sagiri 		copyin_size = sizeof (struct ifreq);
376*b86efd96Sagiri 		break;
377*b86efd96Sagiri 	case TI_GETMYNAME:
378*b86efd96Sagiri 		copyin_size = SIZEOF_STRUCT(strbuf, iocp->ioc_flag);
379*b86efd96Sagiri 		break;
380*b86efd96Sagiri 	}
381*b86efd96Sagiri 	mi_copyin(q, mp, NULL, copyin_size);
382*b86efd96Sagiri }
383*b86efd96Sagiri 
384*b86efd96Sagiri void
385*b86efd96Sagiri rds_ioctl(queue_t *q, mblk_t *mp)
386*b86efd96Sagiri {
387*b86efd96Sagiri 	struct iocblk *iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
388*b86efd96Sagiri 
389*b86efd96Sagiri 
390*b86efd96Sagiri 	switch (iocp->ioc_cmd) {
391*b86efd96Sagiri 		case O_SIOCGIFCONF:
392*b86efd96Sagiri 		case SIOCGIFCONF:
393*b86efd96Sagiri 		case SIOCGIFNUM:
394*b86efd96Sagiri 		case SIOCGIFMTU:
395*b86efd96Sagiri 		case SIOCGIFFLAGS:
396*b86efd96Sagiri 		case TI_GETMYNAME:
397*b86efd96Sagiri 			rds_ioctl_copyin_setup(q, mp);
398*b86efd96Sagiri 			break;
399*b86efd96Sagiri 		default:
400*b86efd96Sagiri 			cmn_err(CE_CONT, "rds_wput unsupported IOCTL \n");
401*b86efd96Sagiri 			miocnak(q, mp, 0, ENOTSUP);
402*b86efd96Sagiri 			break;
403*b86efd96Sagiri 	}
404*b86efd96Sagiri }
405*b86efd96Sagiri 
406*b86efd96Sagiri boolean_t
407*b86efd96Sagiri rds_verify_bind_address(ipaddr_t addr)
408*b86efd96Sagiri {
409*b86efd96Sagiri 	int	numifs;
410*b86efd96Sagiri 	struct ifconf   kifc;
411*b86efd96Sagiri 	struct ifreq *ifr;
412*b86efd96Sagiri 	boolean_t ret = B_FALSE;
413*b86efd96Sagiri 
414*b86efd96Sagiri 
415*b86efd96Sagiri 	if (rds_do_ip_ioctl(SIOCGIFNUM, sizeof (int), (caddr_t)&numifs)) {
416*b86efd96Sagiri 		return (ret);
417*b86efd96Sagiri 	}
418*b86efd96Sagiri 
419*b86efd96Sagiri 	kifc.ifc_len = numifs * sizeof (struct ifreq);
420*b86efd96Sagiri 	kifc.ifc_buf = kmem_zalloc(kifc.ifc_len, KM_SLEEP);
421*b86efd96Sagiri 
422*b86efd96Sagiri 	if (rds_do_ip_ioctl(SIOCGIFCONF, sizeof (struct ifconf),
423*b86efd96Sagiri 	    (caddr_t)&kifc)) {
424*b86efd96Sagiri 		goto done;
425*b86efd96Sagiri 	}
426*b86efd96Sagiri 
427*b86efd96Sagiri 	ifr = kifc.ifc_req;
428*b86efd96Sagiri 	for (numifs = kifc.ifc_len / sizeof (struct ifreq);
429*b86efd96Sagiri 	    numifs > 0; numifs--, ifr++) {
430*b86efd96Sagiri 		struct	sockaddr_in	*sin;
431*b86efd96Sagiri 
432*b86efd96Sagiri 		sin = (struct sockaddr_in *)(uintptr_t)&ifr->ifr_addr;
433*b86efd96Sagiri 		if ((sin->sin_addr.s_addr == addr) &&
434*b86efd96Sagiri 		    rds_is_ib_interface(ifr->ifr_name)) {
435*b86efd96Sagiri 				ret = B_TRUE;
436*b86efd96Sagiri 				break;
437*b86efd96Sagiri 		}
438*b86efd96Sagiri 	}
439*b86efd96Sagiri 
440*b86efd96Sagiri done:
441*b86efd96Sagiri 	kmem_free(kifc.ifc_buf, kifc.ifc_len);
442*b86efd96Sagiri 	return (ret);
443*b86efd96Sagiri }
444