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