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