b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri/*
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * CDDL HEADER START
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri *
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * The contents of this file are subject to the terms of the
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * Common Development and Distribution License (the "License").
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * You may not use this file except in compliance with the License.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri *
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * or http://www.opensolaris.org/os/licensing.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * See the License for the specific language governing permissions
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * and limitations under the License.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri *
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * When distributing Covered Code, include this CDDL HEADER in each
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * If applicable, add the following below this CDDL HEADER, with the
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * fields enclosed by brackets "[]" replaced with your own identifying
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * information: Portions Copyright [yyyy] [name of copyright owner]
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri *
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * CDDL HEADER END
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri */
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri/*
721fffe35d40e548a5a58dc53a2ec9c6762172d9Kacheong Poon * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * Use is subject to license terms.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri */
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/sockio.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/stream.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/errno.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/cmn_err.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/strsun.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <inet/common.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <net/if.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <net/if_types.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <inet/mi.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/t_kuser.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/stropts.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/pathname.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/kstr.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/timod.h>
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem#include <sys/sunddi.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/ib/clients/rds/rds.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri#include <sys/ib/clients/rds/rds_transport.h>
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri/*
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri * Just pass the ioctl to IP and the result to the caller.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri */
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiriint
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemrds_do_ip_ioctl(int cmd, int len, void *arg)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri{
af4c679f647cf088543c762e33d41a3ac52cfa14Sean McEnroe vnode_t *kkvp, *vp;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri TIUSER *tiptr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri struct strioctl iocb;
c1f8b08e52d9b30bd55daeac694e3a7f50d3cd21agiri k_sigset_t smask;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri int err = 0;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
af4c679f647cf088543c762e33d41a3ac52cfa14Sean McEnroe if (lookupname("/dev/udp", UIO_SYSSPACE, FOLLOW, NULLVPP, &kkvp) == 0) {
af4c679f647cf088543c762e33d41a3ac52cfa14Sean McEnroe if (t_kopen((file_t *)NULL, kkvp->v_rdev, FREAD|FWRITE,
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri &tiptr, CRED()) == 0) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri vp = tiptr->fp->f_vnode;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri } else {
af4c679f647cf088543c762e33d41a3ac52cfa14Sean McEnroe VN_RELE(kkvp);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri return (EPROTO);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri } else {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (EPROTO);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri iocb.ic_cmd = cmd;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri iocb.ic_timout = 0;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri iocb.ic_len = len;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem iocb.ic_dp = (caddr_t)arg;
c1f8b08e52d9b30bd55daeac694e3a7f50d3cd21agiri sigintr(&smask, 0);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri err = kstr_ioctl(vp, I_STR, (intptr_t)&iocb);
c1f8b08e52d9b30bd55daeac694e3a7f50d3cd21agiri sigunintr(&smask);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri (void) t_kclose(tiptr, 0);
af4c679f647cf088543c762e33d41a3ac52cfa14Sean McEnroe VN_RELE(kkvp);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri return (err);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri}
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
c1f8b08e52d9b30bd55daeac694e3a7f50d3cd21agiri/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Check if the IP interface named by `lifrp' is RDS-capable.
c1f8b08e52d9b30bd55daeac694e3a7f50d3cd21agiri */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic boolean_t
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemrds_capable_interface(struct lifreq *lifrp)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem char ifname[LIFNAMSIZ];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem char drv[MAXLINKNAMELEN];
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t ppa;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem char *cp;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (lifrp->lifr_type == IFT_IB)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (B_TRUE);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Strip off the logical interface portion before getting
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * intimate with the name.
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(ifname, lifrp->lifr_name, LIFNAMSIZ);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((cp = strchr(ifname, ':')) != NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *cp = '\0';
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strcmp("lo0", ifname) == 0) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * loopback is considered RDS-capable
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (B_TRUE);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (ddi_parse(ifname, drv, &ppa) == DDI_SUCCESS &&
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem rds_transport_ops->rds_transport_if_lookup_by_name(drv));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem}
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Issue an SIOCGLIFCONF down to IP and return the result in `lifcp'.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * lifcp->lifc_buf is dynamically allocated to be *bufsizep bytes.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemstatic int
e11c3f44f531fdff80941ce57c065d2ae861cefcmeemrds_do_lifconf(struct lifconf *lifcp, uint_t *bufsizep)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int err;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int nifs;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((err = rds_do_ip_ioctl(SIOCGIFNUM, sizeof (int), &nifs)) != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (err);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Pad the interface count to account for additional interfaces that
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * may have been configured between the SIOCGLIFNUM and SIOCGLIFCONF.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nifs += 4;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem bzero(lifcp, sizeof (struct lifconf));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem lifcp->lifc_family = AF_INET;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem lifcp->lifc_len = *bufsizep = (nifs * sizeof (struct lifreq));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem lifcp->lifc_buf = kmem_zalloc(*bufsizep, KM_NOSLEEP);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (lifcp->lifc_buf == NULL)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (ENOMEM);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = rds_do_ip_ioctl(SIOCGLIFCONF, sizeof (struct lifconf), lifcp);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (err != 0) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem kmem_free(lifcp->lifc_buf, *bufsizep);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (err);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
c1f8b08e52d9b30bd55daeac694e3a7f50d3cd21agiri return (0);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri}
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagirivoid
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagirirds_ioctl_copyin_done(queue_t *q, mblk_t *mp)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem void *addr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri mblk_t *mp1;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri int err = 0;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct iocblk *iocp = (void *)mp->b_rptr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri if (!(mp1 = mp->b_cont) || !(mp1 = mp1->b_cont)) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri err = EPROTO;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri goto done;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem addr = mp1->b_rptr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri switch (iocp->ioc_cmd) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFNUM: {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t bufsize;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct lifconf lifc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct lifreq *lifrp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int i, nifs, retval = 0;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((err = rds_do_lifconf(&lifc, &bufsize)) != 0)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nifs = lifc.lifc_len / sizeof (struct lifreq);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (lifrp = lifc.lifc_req, i = 0; i < nifs; i++, lifrp++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strlen(lifrp->lifr_name) <= IFNAMSIZ &&
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem rds_capable_interface(lifrp)) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem retval++;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem *((int *)addr) = retval;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem kmem_free(lifc.lifc_buf, bufsize);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case O_SIOCGIFCONF:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFCONF: {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri STRUCT_HANDLE(ifconf, ifc);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri caddr_t ubuf_addr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri int ubuf_size;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t bufsize;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int i, nifs;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct lifconf lifc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct lifreq *lifrp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct ifreq *ifrp;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem STRUCT_SET_HANDLE(ifc, iocp->ioc_flag, (struct ifconf *)addr);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri ubuf_size = STRUCT_FGET(ifc, ifc_len);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri ubuf_addr = STRUCT_FGETP(ifc, ifc_buf);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if ((err = rds_do_lifconf(&lifc, &bufsize)) != 0)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri mp1 = mi_copyout_alloc(q, mp, ubuf_addr, ubuf_size, B_FALSE);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri if (mp1 == NULL) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri err = ENOMEM;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem kmem_free(lifc.lifc_buf, bufsize);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ifrp = (void *)mp1->b_rptr;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nifs = lifc.lifc_len / sizeof (struct lifreq);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (lifrp = lifc.lifc_req, i = 0; i < nifs &&
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem MBLKTAIL(mp1) >= sizeof (struct ifreq); i++, lifrp++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Skip entries that are impossible to return with
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * SIOCGIFCONF, or not RDS-capable.
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (strlen(lifrp->lifr_name) > IFNAMSIZ ||
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem !rds_capable_interface(lifrp)) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem continue;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ifrp->ifr_addr = *(struct sockaddr *)&lifrp->lifr_addr;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ifrp->ifr_addr.sa_family = AF_INET_OFFLOAD;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem (void) strlcpy(ifrp->ifr_name, lifrp->lifr_name,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem IFNAMSIZ);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ifrp++;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem mp1->b_wptr += sizeof (struct ifreq);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem STRUCT_FSET(ifc, ifc_len, MBLKL(mp1));
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem kmem_free(lifc.lifc_buf, bufsize);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFMTU:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFFLAGS:
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem err = rds_do_ip_ioctl(iocp->ioc_cmd, sizeof (struct ifreq),
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem addr);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem case TI_GETMYNAME: {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri rds_t *rds;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri STRUCT_HANDLE(strbuf, sb);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri ipaddr_t v4addr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri uint16_t port;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri int addrlen;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri sin_t *sin;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri STRUCT_SET_HANDLE(sb,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem ((struct iocblk *)(uintptr_t)mp->b_rptr)->ioc_flag, addr);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri rds = (rds_t *)q->q_ptr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri ASSERT(rds->rds_family == AF_INET_OFFLOAD);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri addrlen = sizeof (sin_t);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri v4addr = rds->rds_src;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri port = rds->rds_port;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri mp1 = mi_copyout_alloc(q, mp, STRUCT_FGETP(sb, buf), addrlen,
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri B_TRUE);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri if (mp1 == NULL)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri return;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri STRUCT_FSET(sb, len, (int)sizeof (sin_t));
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri sin = (sin_t *)(uintptr_t)mp1->b_rptr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri mp1->b_wptr = (uchar_t *)&sin[1];
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri *sin = sin_null;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri sin->sin_family = AF_INET_OFFLOAD;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri sin->sin_addr.s_addr = v4addr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri sin->sin_port = port;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri default:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri err = EOPNOTSUPP;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri if (err == 0) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri mi_copyout(q, mp);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri return;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiridone:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri mi_copy_done(q, mp, err);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri}
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagirivoid
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagirirds_ioctl_copyin_setup(queue_t *q, mblk_t *mp)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri{
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri struct iocblk *iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri int copyin_size;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri if (mp->b_cont == NULL) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri iocp->ioc_error = EINVAL;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri mp->b_datap->db_type = M_IOCNAK;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri iocp->ioc_count = 0;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri qreply(q, mp);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri return;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri switch (iocp->ioc_cmd) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case O_SIOCGIFCONF:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFCONF:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri if (iocp->ioc_count == TRANSPARENT)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri copyin_size = SIZEOF_STRUCT(ifconf, iocp->ioc_flag);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri else
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri copyin_size = iocp->ioc_count;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFNUM:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri copyin_size = sizeof (int);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFFLAGS:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFMTU:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri copyin_size = sizeof (struct ifreq);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case TI_GETMYNAME:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri copyin_size = SIZEOF_STRUCT(strbuf, iocp->ioc_flag);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri mi_copyin(q, mp, NULL, copyin_size);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri}
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagirivoid
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagirirds_ioctl(queue_t *q, mblk_t *mp)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri{
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri struct iocblk *iocp = (struct iocblk *)(uintptr_t)mp->b_rptr;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri switch (iocp->ioc_cmd) {
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case O_SIOCGIFCONF:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFCONF:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFNUM:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFMTU:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case SIOCGIFFLAGS:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri case TI_GETMYNAME:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri rds_ioctl_copyin_setup(q, mp);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri default:
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri cmn_err(CE_CONT, "rds_wput unsupported IOCTL \n");
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri miocnak(q, mp, 0, ENOTSUP);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri}
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiriboolean_t
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagirirds_verify_bind_address(ipaddr_t addr)
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem int i, nifs;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem uint_t bufsize;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct lifconf lifc;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct lifreq *lifrp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem struct sockaddr_in *sinp;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem boolean_t retval = B_FALSE;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (rds_do_lifconf(&lifc, &bufsize) != 0)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (B_FALSE);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem nifs = lifc.lifc_len / sizeof (struct lifreq);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem for (lifrp = lifc.lifc_req, i = 0; i < nifs; i++, lifrp++) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sinp = (struct sockaddr_in *)&lifrp->lifr_addr;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (rds_capable_interface(lifrp) &&
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem sinp->sin_addr.s_addr == addr) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem retval = B_TRUE;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem break;
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri }
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem kmem_free(lifc.lifc_buf, bufsize);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem return (retval);
b86efd96f8acd85ddaa930a2f0c1d664237e4aafagiri}