1*6cefaae1SJack Meng /* 2*6cefaae1SJack Meng * CDDL HEADER START 3*6cefaae1SJack Meng * 4*6cefaae1SJack Meng * The contents of this file are subject to the terms of the 5*6cefaae1SJack Meng * Common Development and Distribution License (the "License"). 6*6cefaae1SJack Meng * You may not use this file except in compliance with the License. 7*6cefaae1SJack Meng * 8*6cefaae1SJack Meng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6cefaae1SJack Meng * or http://www.opensolaris.org/os/licensing. 10*6cefaae1SJack Meng * See the License for the specific language governing permissions 11*6cefaae1SJack Meng * and limitations under the License. 12*6cefaae1SJack Meng * 13*6cefaae1SJack Meng * When distributing Covered Code, include this CDDL HEADER in each 14*6cefaae1SJack Meng * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6cefaae1SJack Meng * If applicable, add the following below this CDDL HEADER, with the 16*6cefaae1SJack Meng * fields enclosed by brackets "[]" replaced with your own identifying 17*6cefaae1SJack Meng * information: Portions Copyright [yyyy] [name of copyright owner] 18*6cefaae1SJack Meng * 19*6cefaae1SJack Meng * CDDL HEADER END 20*6cefaae1SJack Meng */ 21*6cefaae1SJack Meng 22*6cefaae1SJack Meng /* 23*6cefaae1SJack Meng * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24*6cefaae1SJack Meng * Use is subject to license terms. 25*6cefaae1SJack Meng */ 26*6cefaae1SJack Meng 27*6cefaae1SJack Meng #include <sys/t_kuser.h> 28*6cefaae1SJack Meng #include <sys/netconfig.h> 29*6cefaae1SJack Meng #include <netinet/in.h> 30*6cefaae1SJack Meng #include <net/route.h> 31*6cefaae1SJack Meng #include <net/if.h> 32*6cefaae1SJack Meng #include <sys/kstr.h> 33*6cefaae1SJack Meng #include <rpc/clnt.h> 34*6cefaae1SJack Meng #include <sys/stropts.h> 35*6cefaae1SJack Meng #include <sys/socket.h> 36*6cefaae1SJack Meng #include <sys/sockio.h> 37*6cefaae1SJack Meng #include <sys/bootprops.h> 38*6cefaae1SJack Meng 39*6cefaae1SJack Meng static int 40*6cefaae1SJack Meng kivoid_to_sock(int af, void *source, void *dest) 41*6cefaae1SJack Meng { 42*6cefaae1SJack Meng struct sockaddr_in *sin = NULL; 43*6cefaae1SJack Meng struct sockaddr_in6 *sin6 = NULL; 44*6cefaae1SJack Meng 45*6cefaae1SJack Meng if (source == NULL || dest == NULL) { 46*6cefaae1SJack Meng return (-1); 47*6cefaae1SJack Meng } 48*6cefaae1SJack Meng if (af == AF_INET) { 49*6cefaae1SJack Meng sin = (struct sockaddr_in *)dest; 50*6cefaae1SJack Meng (void) bcopy(source, &sin->sin_addr, 51*6cefaae1SJack Meng sizeof (struct in_addr)); 52*6cefaae1SJack Meng sin->sin_family = af; 53*6cefaae1SJack Meng } else if (af == AF_INET6) { 54*6cefaae1SJack Meng sin6 = (struct sockaddr_in6 *)dest; 55*6cefaae1SJack Meng (void) bcopy(source, &sin6->sin6_addr, 56*6cefaae1SJack Meng sizeof (struct in6_addr)); 57*6cefaae1SJack Meng sin6->sin6_family = af; 58*6cefaae1SJack Meng } else { 59*6cefaae1SJack Meng return (-1); 60*6cefaae1SJack Meng } 61*6cefaae1SJack Meng return (0); 62*6cefaae1SJack Meng } 63*6cefaae1SJack Meng 64*6cefaae1SJack Meng int 65*6cefaae1SJack Meng kdlifconfig(TIUSER *tiptr, int af, void *myIPaddr, void *mymask, 66*6cefaae1SJack Meng struct in_addr *mybraddr, struct in_addr *gateway, char *ifname) 67*6cefaae1SJack Meng { 68*6cefaae1SJack Meng int rc; 69*6cefaae1SJack Meng struct netbuf sbuf; 70*6cefaae1SJack Meng struct sockaddr_in sin; 71*6cefaae1SJack Meng struct sockaddr_in6 sin6; 72*6cefaae1SJack Meng struct rtentry route; 73*6cefaae1SJack Meng struct sockaddr_in *rt_sin; 74*6cefaae1SJack Meng 75*6cefaae1SJack Meng if (myIPaddr == NULL || mymask == NULL) { 76*6cefaae1SJack Meng return (-1); 77*6cefaae1SJack Meng } 78*6cefaae1SJack Meng 79*6cefaae1SJack Meng if (af == AF_INET) { 80*6cefaae1SJack Meng rc = kivoid_to_sock(af, mymask, &sin); 81*6cefaae1SJack Meng if (rc != 0) { 82*6cefaae1SJack Meng return (rc); 83*6cefaae1SJack Meng } 84*6cefaae1SJack Meng sbuf.buf = (caddr_t)&sin; 85*6cefaae1SJack Meng sbuf.maxlen = sbuf.len = sizeof (sin); 86*6cefaae1SJack Meng } else { 87*6cefaae1SJack Meng rc = kivoid_to_sock(af, mymask, &sin6); 88*6cefaae1SJack Meng if (rc != 0) { 89*6cefaae1SJack Meng return (rc); 90*6cefaae1SJack Meng } 91*6cefaae1SJack Meng sbuf.buf = (caddr_t)&sin6; 92*6cefaae1SJack Meng sbuf.maxlen = sbuf.len = sizeof (sin6); 93*6cefaae1SJack Meng } 94*6cefaae1SJack Meng if (rc = kifioctl(tiptr, SIOCSLIFNETMASK, &sbuf, ifname)) { 95*6cefaae1SJack Meng return (rc); 96*6cefaae1SJack Meng } 97*6cefaae1SJack Meng 98*6cefaae1SJack Meng if (af == AF_INET) { 99*6cefaae1SJack Meng rc = kivoid_to_sock(af, myIPaddr, &sin); 100*6cefaae1SJack Meng if (rc != 0) { 101*6cefaae1SJack Meng return (rc); 102*6cefaae1SJack Meng } 103*6cefaae1SJack Meng sbuf.buf = (caddr_t)&sin; 104*6cefaae1SJack Meng sbuf.maxlen = sbuf.len = sizeof (sin); 105*6cefaae1SJack Meng } else { 106*6cefaae1SJack Meng rc = kivoid_to_sock(af, myIPaddr, &sin6); 107*6cefaae1SJack Meng if (rc != 0) { 108*6cefaae1SJack Meng return (rc); 109*6cefaae1SJack Meng } 110*6cefaae1SJack Meng sbuf.buf = (caddr_t)&sin6; 111*6cefaae1SJack Meng sbuf.maxlen = sbuf.len = sizeof (sin6); 112*6cefaae1SJack Meng } 113*6cefaae1SJack Meng 114*6cefaae1SJack Meng if (rc = kifioctl(tiptr, SIOCSLIFADDR, &sbuf, ifname)) { 115*6cefaae1SJack Meng return (rc); 116*6cefaae1SJack Meng } 117*6cefaae1SJack Meng /* 118*6cefaae1SJack Meng * Only IPv4 has brocadcast address. 119*6cefaae1SJack Meng */ 120*6cefaae1SJack Meng if (af == AF_INET && mybraddr != NULL) { 121*6cefaae1SJack Meng if (mybraddr->s_addr != INADDR_BROADCAST) { 122*6cefaae1SJack Meng rc = kivoid_to_sock(af, mybraddr, &sin); 123*6cefaae1SJack Meng if (rc != 0) { 124*6cefaae1SJack Meng return (rc); 125*6cefaae1SJack Meng } 126*6cefaae1SJack Meng sbuf.buf = (caddr_t)&sin; 127*6cefaae1SJack Meng sbuf.maxlen = sbuf.len = sizeof (sin); 128*6cefaae1SJack Meng if (rc = kifioctl(tiptr, SIOCSLIFBRDADDR, &sbuf, 129*6cefaae1SJack Meng ifname)) { 130*6cefaae1SJack Meng return (rc); 131*6cefaae1SJack Meng } 132*6cefaae1SJack Meng } 133*6cefaae1SJack Meng } 134*6cefaae1SJack Meng 135*6cefaae1SJack Meng /* 136*6cefaae1SJack Meng * Now turn on the interface. 137*6cefaae1SJack Meng */ 138*6cefaae1SJack Meng if (rc = ksetifflags(tiptr, IFF_UP, ifname)) { 139*6cefaae1SJack Meng return (rc); 140*6cefaae1SJack Meng } 141*6cefaae1SJack Meng 142*6cefaae1SJack Meng /* 143*6cefaae1SJack Meng * Set the default gateway. 144*6cefaae1SJack Meng */ 145*6cefaae1SJack Meng if (af == AF_INET && gateway != NULL) { 146*6cefaae1SJack Meng (void) memset(&route, 0, sizeof (route)); 147*6cefaae1SJack Meng rt_sin = (struct sockaddr_in *)&route.rt_dst; 148*6cefaae1SJack Meng rt_sin->sin_family = AF_INET; 149*6cefaae1SJack Meng 150*6cefaae1SJack Meng rt_sin = (struct sockaddr_in *)&route.rt_gateway; 151*6cefaae1SJack Meng rt_sin->sin_addr.s_addr = gateway->s_addr; 152*6cefaae1SJack Meng route.rt_flags = RTF_GATEWAY | RTF_UP; 153*6cefaae1SJack Meng sbuf.buf = (caddr_t)&route; 154*6cefaae1SJack Meng sbuf.maxlen = sbuf.len = sizeof (route); 155*6cefaae1SJack Meng if (rc = kifioctl(tiptr, SIOCADDRT, &sbuf, ifname)) { 156*6cefaae1SJack Meng return (rc); 157*6cefaae1SJack Meng } 158*6cefaae1SJack Meng } 159*6cefaae1SJack Meng return (0); 160*6cefaae1SJack Meng } 161*6cefaae1SJack Meng 162*6cefaae1SJack Meng int 163*6cefaae1SJack Meng kifioctl(TIUSER *tiptr, int cmd, struct netbuf *nbuf, char *ifname) 164*6cefaae1SJack Meng { 165*6cefaae1SJack Meng struct strioctl iocb; 166*6cefaae1SJack Meng struct lifreq lifr; 167*6cefaae1SJack Meng vnode_t *vp = NULL; 168*6cefaae1SJack Meng char *buf = NULL; 169*6cefaae1SJack Meng int rc = 0; 170*6cefaae1SJack Meng 171*6cefaae1SJack Meng (void) memset(&lifr, 0, sizeof (lifr)); 172*6cefaae1SJack Meng /* 173*6cefaae1SJack Meng * Now do the one requested. 174*6cefaae1SJack Meng */ 175*6cefaae1SJack Meng if (nbuf->len) { 176*6cefaae1SJack Meng if (nbuf->len == sizeof (struct rtentry)) { 177*6cefaae1SJack Meng if (cmd != SIOCADDRT) { 178*6cefaae1SJack Meng return (-1); 179*6cefaae1SJack Meng } 180*6cefaae1SJack Meng /* 181*6cefaae1SJack Meng * Set up gateway parameters. 182*6cefaae1SJack Meng */ 183*6cefaae1SJack Meng iocb.ic_len = nbuf->len; 184*6cefaae1SJack Meng iocb.ic_dp = nbuf->buf; 185*6cefaae1SJack Meng } else { 186*6cefaae1SJack Meng if (nbuf->len != sizeof (struct sockaddr_in) && 187*6cefaae1SJack Meng nbuf->len != sizeof (struct sockaddr_in6)) { 188*6cefaae1SJack Meng return (-1); 189*6cefaae1SJack Meng } 190*6cefaae1SJack Meng buf = (char *)&lifr.lifr_addr; 191*6cefaae1SJack Meng bcopy(nbuf->buf, buf, nbuf->len); 192*6cefaae1SJack Meng iocb.ic_len = sizeof (lifr); 193*6cefaae1SJack Meng iocb.ic_dp = (caddr_t)&lifr; 194*6cefaae1SJack Meng } 195*6cefaae1SJack Meng } else { 196*6cefaae1SJack Meng iocb.ic_len = sizeof (lifr); 197*6cefaae1SJack Meng iocb.ic_dp = (caddr_t)&lifr; 198*6cefaae1SJack Meng } 199*6cefaae1SJack Meng (void) strncpy((caddr_t)&lifr.lifr_name, ifname, 200*6cefaae1SJack Meng sizeof (lifr.lifr_name)); 201*6cefaae1SJack Meng iocb.ic_cmd = cmd; 202*6cefaae1SJack Meng iocb.ic_timout = 0; 203*6cefaae1SJack Meng 204*6cefaae1SJack Meng vp = tiptr->fp->f_vnode; 205*6cefaae1SJack Meng rc = kstr_ioctl(vp, I_STR, (intptr_t)&iocb); 206*6cefaae1SJack Meng if (rc) { 207*6cefaae1SJack Meng return (rc); 208*6cefaae1SJack Meng } 209*6cefaae1SJack Meng 210*6cefaae1SJack Meng return (0); 211*6cefaae1SJack Meng } 212*6cefaae1SJack Meng 213*6cefaae1SJack Meng int 214*6cefaae1SJack Meng ksetifflags(TIUSER *tiptr, uint_t value, char *ifname) 215*6cefaae1SJack Meng { 216*6cefaae1SJack Meng int rc; 217*6cefaae1SJack Meng struct strioctl iocb; 218*6cefaae1SJack Meng struct lifreq lifr; 219*6cefaae1SJack Meng 220*6cefaae1SJack Meng if (ifname == NULL) { 221*6cefaae1SJack Meng return (-1); 222*6cefaae1SJack Meng } 223*6cefaae1SJack Meng 224*6cefaae1SJack Meng (void) memset(&lifr, 0, sizeof (lifr)); 225*6cefaae1SJack Meng 226*6cefaae1SJack Meng (void) strncpy((caddr_t)&lifr.lifr_name, ifname, 227*6cefaae1SJack Meng sizeof (lifr.lifr_name)); 228*6cefaae1SJack Meng iocb.ic_cmd = SIOCGLIFFLAGS; 229*6cefaae1SJack Meng iocb.ic_timout = 0; 230*6cefaae1SJack Meng iocb.ic_len = sizeof (lifr); 231*6cefaae1SJack Meng iocb.ic_dp = (caddr_t)&lifr; 232*6cefaae1SJack Meng if (rc = kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb)) 233*6cefaae1SJack Meng return (rc); 234*6cefaae1SJack Meng 235*6cefaae1SJack Meng lifr.lifr_flags |= value; 236*6cefaae1SJack Meng iocb.ic_cmd = SIOCSLIFFLAGS; 237*6cefaae1SJack Meng return (kstr_ioctl(tiptr->fp->f_vnode, I_STR, (intptr_t)&iocb)); 238*6cefaae1SJack Meng } 239