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
kivoid_to_sock(int af,void * source,void * dest)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
kdlifconfig(TIUSER * tiptr,int af,void * myIPaddr,void * mymask,struct in_addr * mybraddr,struct in_addr * gateway,char * ifname)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
kifioctl(TIUSER * tiptr,int cmd,struct netbuf * nbuf,char * ifname)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
ksetifflags(TIUSER * tiptr,uint_t value,char * ifname)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